Aliases X propertyName problems
gildonei opened this issue · comments
Hi,
I guess that Cake isn't preserving table alias when creating some associations like in the case below.
I have the following Table objects
PessoasTable
class PessoasTable extends AppTable { public function initialize(array $config) { parent::initialize($config); $this->setAlias('Pessoa'); $this->setEntityClass('Pessoa'); $this->setTable('pessoas'); $this->setPrimaryKey('id'); $this->setDisplayField('ds_nome'); $this->addAssociations([ 'hasOne' => [ 'Usuarios' => [ 'className' => 'Usuarios', 'propertyName' => 'Usuario', 'foreignKey' => 'id', 'joinType' => 'LEFT', 'dependent' => true, ], 'Pessoafisicas' => [ 'className' => 'Pessoafisicas', 'propertyName' => 'Pessoafisica', 'foreignKey' => 'id', 'joinType' => 'LEFT', 'dependent' => true, ], ...
UsuariosTable
class UsuariosTable extends AppTable { public function initialize(array $config) { parent::initialize($config); $this->setAlias('Usuario'); $this->setEntityClass('Usuario'); $this->setTable('usuarios'); $this->setPrimaryKey('id'); $this->setDisplayField('ds_login'); $this->addAssociations([ 'belongsTo' => [ 'Pessoas' => [ 'className' => 'Pessoas', 'propertyName' => 'Pessoa', 'foreignKey' => 'id', 'joinType' => 'INNER', ] ], ]); } ...
PessoafisicasTable
class PessoafisicasTable extends AppTable { public function initialize(array $config) { parent::initialize($config); $this->setAlias('Pessoafisica'); $this->setEntityClass('Pessoafisica'); $this->setTable('pessoafisicas'); $this->setDisplayField('nr_cpf'); $this->setPrimaryKey('id'); $this->addAssociations([ 'belongsTo' => [ 'Pessoas' => [ 'className' => 'Pessoas', 'propertyName' => 'Pessoa', 'foreignKey' => 'id', 'joinType' => 'INNER', ], ] ]); } ...
In UsuariosController the following find is producing the SQL query bellow
$usuario = $this->Usuarios->get($id, [ 'fields' => ['id', 'ds_login'], 'contain' => [ 'Pessoas' => [ 'fields' => ['id', 'ds_nome'], 'Pessoafisicas' ], ]);
SQL output
SELECT Usuario.id AS `Usuario__id`, Usuario.ds_login AS `Usuario__ds_login`, Pessoas.id AS `Pessoas__id`, Pessoas.ds_nome AS `Pessoas__ds_nome` FROM usuarios Usuario INNER JOIN pessoas Pessoas ON Pessoas.id = (Usuario.id) LEFT JOIN pessoafisicas Pessoafisicas ON Pessoa.id = (Pessoafisicas.id) WHERE Usuario.id = 4 LIMIT 1
Error Note that CakePHP isn't respecting my table Alias name in Pessoas and neither in Pessoafisicas but in ON condition thru Pessoa and Pessoafisica it is.
I think it is not documented coreectly, but the alis for each table does is set by the association name, for example, when you created the hasOne association.
The alias is the key name in the array, and you set it as Usuarios, instead of Usuario, for example.
Since the alias is overridden when creating the association, it is generally not recommended to call setAlias() yourself and it will just cause confusion.
So why UsuariosTable is being aliased on result SQL?
It depends on the table you query, but the associations alias will always take precedence, and can lead to this kind of problems. Just use the association aliasing and not the setAlias() function
It does not make sense, according to your comment above, all my query should be in singular like it happen to Usuario not plural because I adopted the same name rule for Pessoas e Pessoafisicas.
Debugging code, I guess in \Cake\ORM\Association -> _joinCondition -> $tAlias = $this->_name should be $this->getTarget()->getAlias() just like $sAlias = $this->getSource()->getAlias();
@gildonei did my explanation help fixing your problem?
Not yet, I am still debuggin to find where the ORM get the table name to mount associations to create joins. I think it is using _name intead of _alias just like it is happening in _joinCondition
I give up! Cound't find a solution! I will remove setAlias from tables. If possible I would like to ask ORM team to perform some tests with this case. I am sure that something odd happening, like I mentioned in \Cake\ORM\Association -> _joinCondition (method).
In all honesty, having setAlias()
as a method in the table was a big mistake in my original design, it causes this kind of confusions. Try to avoid it in the future and use the aliasing provided by the association classes.