Yii2: FindOne error when it using with an associative array or innerJoin

Created on 20 Mar 2018  路  9Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

I have a ActiveQuery class that override one() and all() methods to basically add a innerJoin and where clause at every search of that model and the model that joins has a same column name of primary key (at this case id). So i need to use findOne() method to get only one AR element searching by primary key or another column.

What is the expected result?

Retrieves one element of AR after search.

What do you get instead?

When i try to use findOne([tableName.columnName => $id]) tells me that tableName.columnName is not a column name.
Key "cota.id" is not a column name and can not be used as a filter

When i try to use findOne($id) throws a IntegrityException with the message that idcolumn is ambiguos at sql.
The SQL being executed was: SELECT `cota`.* FROM `cota` INNER JOIN `secretaria` ON secretaria.id = cota.fk_secretaria WHERE `id`='1'

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.15
| PHP version | 7.0
| Operating system | Ubuntu

bug

Most helpful comment

@cebe It does not work with next syntax!!!
findOne(['{{tableName}}.[[columnName]]' => $id])

because in checks for next columns names:

array (size=12)
  0 => string 'uuid' (length=4)
  1 => string 'email' (length=5)
  2 => string 'fname' (length=5)
  3 => string 'lname' (length=5)
  4 => string 'sname' (length=5)
  5 => string 'workflow_uuid' (length=13)
  6 => string '{{%users}}.uuid' (length=15)
  7 => string '{{%users}}.email' (length=16)
  8 => string '{{%users}}.fname' (length=16)
  9 => string '{{%users}}.lname' (length=16)
  10 => string '{{%users}}.sname' (length=16)
  11 => string '{{%users}}.workflow_uuid' (length=24)

instead of

array (size=12)
  0 => string 'uuid' (length=4)
  1 => string 'email' (length=5)
  2 => string 'fname' (length=5)
  3 => string 'lname' (length=5)
  4 => string 'sname' (length=5)
  5 => string 'workflow_uuid' (length=13)
  6 => string '{{%users}}.[[uuid]]' (length=15)
  7 => string '{{%users}}.[[email]]' (length=16)
  8 => string '{{%users}}.[[fname]]' (length=16)
  9 => string '{{%users}}.[[lname]]' (length=16)
  10 => string '{{%users}}.[[sname]]' (length=16)
  11 => string '{{%users}}.[[workflow_uuid]]' (length=24)

All 9 comments

I have a ActiveQuery class that override one() and all() methods to basically add a innerJoin and where clause at every search of that model

Now I see what the problem is, the join is added after the check in findOne/findByCondition. Can you change the code so that the join is added in init() method of the ActiveQuery class?

When i try to use findOne([tableName.columnName => $id]) tells me that tableName.columnName is not a column name.
Key "cota.id" is not a column name and can not be used as a filter

we should allow this when checking in filterCondition().

Thanks @cebe, the ambiguous problem was resolved. But i have one question, when should i use functions like that at init or use overriting one/all method? For the second question, i've already saw that will be fixed at milestone that 2.0.16 that is due up to 20/03, is when is it will be release?

Nope, it's ex 2.0.15 renamed.

So should i wait to be fixed or it's better rollback version?

similar to #15933, going to fix it today.

Fixed in 2.0.15.1. Thanks for reporting this!

@cebe It does not work with next syntax!!!
findOne(['{{tableName}}.[[columnName]]' => $id])

because in checks for next columns names:

array (size=12)
  0 => string 'uuid' (length=4)
  1 => string 'email' (length=5)
  2 => string 'fname' (length=5)
  3 => string 'lname' (length=5)
  4 => string 'sname' (length=5)
  5 => string 'workflow_uuid' (length=13)
  6 => string '{{%users}}.uuid' (length=15)
  7 => string '{{%users}}.email' (length=16)
  8 => string '{{%users}}.fname' (length=16)
  9 => string '{{%users}}.lname' (length=16)
  10 => string '{{%users}}.sname' (length=16)
  11 => string '{{%users}}.workflow_uuid' (length=24)

instead of

array (size=12)
  0 => string 'uuid' (length=4)
  1 => string 'email' (length=5)
  2 => string 'fname' (length=5)
  3 => string 'lname' (length=5)
  4 => string 'sname' (length=5)
  5 => string 'workflow_uuid' (length=13)
  6 => string '{{%users}}.[[uuid]]' (length=15)
  7 => string '{{%users}}.[[email]]' (length=16)
  8 => string '{{%users}}.[[fname]]' (length=16)
  9 => string '{{%users}}.[[lname]]' (length=16)
  10 => string '{{%users}}.[[sname]]' (length=16)
  11 => string '{{%users}}.[[workflow_uuid]]' (length=24)

Also does not work with table aliases:

$authManager = Instance::ensure(Yii::$app->authManager, DbManager::class);
$configurations = Configuration::find()
    ->from(['configuration' => Configuration::tableName()])
    ->distinct('configuration.id')
    ->join('JOIN', [self::FILTER_ALIAS_AUTH_ASSIGNMENT => $authManager->assignmentTable], [
        self::FILTER_ALIAS_AUTH_ASSIGNMENT . '.`user_id`' => $userId,
        self::FILTER_ALIAS_AUTH_ASSIGNMENT . '.`item_name`' => $permissions,
    ])->all();
Was this page helpful?
0 / 5 - 0 ratings