-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can not call ActiveRecord::all()
method with specified connection for database with different scheme
#89
Comments
You can override MyActiveRecordModel
|
@FabrizioCaldarelli Thank you for your answer. But if I do that, all queries will be use the second connection. But I need to use it only for a single query I solve my case by changing of |
@HaruAtari any way it can be fixed without breaking things? |
Without taking backwards compatibility in account, I'd say it's a wrong behavior that given explicit DB connection it uses schema from another connection. |
@samdark I don't know. I'm not enough good in this part of the framework. |
I took a deeper look at this and I think with the current implementation of AR it would be very difficult to fix it (just too many static methods all over the place), not to mention the most probable BC break will be introduced. I don't think fixing this unusual case is worth it here (hopefully Yii 3 can do something about it). Adding it to the "known problems" list would be handy. |
Moved issue to standalone AR implementation. @HaruAtari if you know a good backwards compatible way to change it in Yii 2, let us know. |
I certainly understand that the thoughts that came to my mind are an evil crutch, but nevertheless, this option is most likely to work (I have not checked). The idea is to throw the connection object through the entire method chain, up to public static function populateRecord($record, $row, $db = null)
{
$columns = static::getTableSchema($db)->columns;
foreach ($row as $name => $value) {
if (isset($columns[$name])) {
$row[$name] = $columns[$name]->phpTypecast($value);
}
}
parent::populateRecord($record, $row);
} And already at public static function getTableSchema($db = null)
{
$db = $db ?? static::getDb();
$tableSchema = $db
->getSchema()
->getTableSchema(static::tableName());
if ($tableSchema === null) {
throw new InvalidConfigException('The table does not exist: ' . static::tableName());
}
return $tableSchema;
} This way we can maintain backward compatibility, however, at the cost of the fact that in |
That won't be backwards compatible so can't be done in Yii 2. This way you will force updating all the AR classes that implement populateRecord or else you'll get an error:
|
Then one of the dirty options is to do something like that. class ActiveQuery
{
protected $db = null;
public function all($db = null)
{
$this->db = $db;
return parent::all($db);
}
public function populateRecord($record, $row)
{
$modelClass = get_class($model);
if ($this->db === null) {
$modelClass::populateRecord($record, $row);
} else {
$columns = $this->db->getSchema()
->getTableSchema($modelClass::tableName())->columns;
foreach ($row as $name => $value) {
if (isset($columns[$name])) {
$row[$name] = $columns[$name]->phpTypecast($value);
}
}
BaseActiveRecord::populateRecord($record, $row);
}
}
} ActiveQueryTrait trait ActiveQueryTrait
{
protected function createModels($rows)
{
if ($this->asArray) {
return $rows;
} else {
$models = [];
/* @var $class ActiveRecord */
$class = $this->modelClass;
foreach ($rows as $row) {
$model = $class::instantiate($row);
$this->populateRecord($model, $row);
$models[] = $model;
}
return $models;
}
}
} It's shameful, but it should solve the problem. |
I still came across that issue: Yii 2.0.47:
The But:
Whats the state of the "bug"? |
@Commifreak try ask in yii2 repo. this one for yii3 |
Ok, will do it. Just wondering, as the author was using Yii 2 as well. |
Yes. The issue was initially opened in Yii2 then moved here. |
Currently you can specify a db connection when create an $userQuery = new ActiveQuery(User::class, $db);
$users = $userQuery->all(); |
I have two database connections. The main connection (
\Yii::$app->db
) is empty now. And the second which connected to a database with existed tables. Also I have an activeRecord model for an existed table from the second connection.My code:
When I run it, I have an error:
The table does not exist: {{%my_active_record_model}}
. But how I said this table exists.The method
\yii\db\Query::all()
takes data (rows) from the second database successfully. After that it try to populate records into activeRecord models. It calls\yii\db\ActiveQuery::populate()
->\yii\db\ActiveQueryTrait::createModels()
->\yii\db\ActiveRecord::populateRecord()
. And here we have a problem.This method takes a list of columns from the table schema from the
\Yii::$app->db
connections, but not from the connection, which was specified inall()
call.So I can't specify connection to take data from database with scheme different from the current connection.
Additional info
The text was updated successfully, but these errors were encountered: