yii2: joinWith + criteria over multiple databases not working
Introduction First of all; I’m not sure if this is not working by design or that it’s a bug.
What I tried is making a join over two tables in separate databases with a WHERE statement on it.
The use case is that we have a second database with log tables and in the backend would like to join this with live data. I made a simplified test case.
I tried searching the forum + issues but couldn’t find a similar issue.
Environment
- PHP 5.4.3
- Yii 2.0.0-dev
- MySQL 5
Reproduce
Create two database configs in /config/web.php (with according settings):
'db' => require(__DIR__ . '/db.php'),
'db2' => require(__DIR__ . '/db2.php')
Create database setup for database #1:
CREATE TABLE IF NOT EXISTS `shop` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `shop` (`id`, `name`) VALUES
(1, 'Shop #1'),
(2, 'Shop #2');
Then create setup for database #2:
CREATE TABLE IF NOT EXISTS `employee` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`shop_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK__yii2_test1.shop` (`shop_id`),
CONSTRAINT `FK__yii2_test1.shop` FOREIGN KEY (`shop_id`) REFERENCES `yii2_test1`.`shop` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `employee` (`id`, `name`, `shop_id`) VALUES
(1, 'Jon Doe', 1),
(2, 'Abraham Lincoln', 1),
(3, 'John Lennon', 2);
Then we create two models, first Shop.php:
/**
* Shop model
*/
class Shop extends \yii\db\ActiveRecord
{
/**
* Define default database for the sake of clarity
*/
public static function getDb() {
return \Yii::$app->db;
}
/**
* Relation to Employee
*
* @return Relation
*/
public function getEmployees() {
return $this->hasMany(Employee::className(), ['shop_id' => 'id']);
}
}
And Employee.php:
/**
* Employee model
*/
class Employee extends \yii\db\ActiveRecord
{
/**
* Use different database
*/
public static function getDb() {
return \Yii::$app->db2;
}
/**
* Relation to Shop
*
* @return Relation
*/
public function getShop() {
return $this->hasOne(Shop::className(), ['id'=>'shop_id']);
}
}
Now in a controller I would like to fetch some data with a criteria:
$employeesShop1 = \app\models\Employee::find()
->joinWith(array('shop' => function($query) { return $query->andWhere(array('shop_id' => 1)); }))
->all();
This results in an error:

The statement would work if the query is created like this:
SELECT `employee`.* FROM `employee` LEFT JOIN `yii2_test1`.`shop` ON `employee`.`shop_id` = `yii2_test1`.`shop`.`id` WHERE `shop_id`=1
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 1
- Comments: 22 (16 by maintainers)
Of course you cannot. What you expected? But try this
I am not sure it will work 😄
IMHO, it is not rare to have multiple DB’s of the same DBMS wired to an app. An since we support it anyways, it would be logical to have this working out of the box.
With respect to the overhead. That’s another thing to be tackled, of course.
Doing that automatically would introduce a lot of overhead to support a very rarely used feature.
To automate this process in MySQL we can do smthng like this:
Profit - we don’t need to hardcode db-name into the model, just to define it in config. Request in
getDbName()can be cached