即使我指定了外键,CakePHP 3 仍使用主键 (setPrimaryKey) 执行 JOIN
CakePHP 3 is using primary key (setPrimaryKey) to do a JOIN even though I've specified a foreign key
CakePHP 3.7
我有2个型号Table 类如下:
/src/Model/Table/SubstancesTable.php
/src/Model/Table/TblOrganisationSubstancesTable.php
MySQL 中每个 table 的架构如下:
1.
mysql> describe substances;
+-------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| app_id | varchar(8) | NO | UNI | NULL | |
| name | varchar(1500) | NO | | NULL | |
| date | date | NO | | NULL | |
+-------------+-----------------------+------+-----+---------+----------------+
2.
mysql> describe tbl_organisation_substances;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| o_sub_id | int(255) | NO | PRI | NULL | auto_increment |
| o_id | int(255) | NO | MUL | NULL | |
| app_id | varchar(15) | YES | | NULL | |
| os_name | varchar(255) | YES | | NULL | |
| ec | varchar(35) | YES | | NULL | |
| cas | varchar(255) | YES | | NULL | |
| upload_id | int(100) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
我编写了一个自定义查找器,它需要在这 2 个 table 之间执行 JOIN
。自定义查找器看起来像这样,位于 SubstancesTable.php
:
public function findDistinctSubstancesByOrganisation(Query $query, array $options)
{
$o_id = $options['o_id'];
$query = $this->find()->select('id')->contain('TblOrganisationSubstances')->where(['TblOrganisationSubstances.o_id' => $o_id]);
return $query;
}
每个 table 都有一个 app_id
列,这是链接 2 table 的外键。
最初我收到一个错误:
The TblOrganisationSubstances association is not defined on Substances.
这是有道理的,因为尚未制定任何定义。
所以在 SubstancesTable.php
中我定义了这个:
$this->setPrimaryKey('id');
// ...
$this->belongsTo('TblOrganisationSubstances', [
'foreignKey' => 'app_id',
'joinType' => 'INNER'
]);
但这会产生以下 SQL 语句:
SELECT Substances.id AS `Substances__id` FROM substances Substances INNER JOIN tbl_organisation_substances TblOrganisationSubstances ON TblOrganisationSubstances.o_sub_id = (Substances.app_id) WHERE TblOrganisationSubstances.o_id = :c0
这是行不通的,因为 TblOrganisationSubstances.o_sub_id = (Substances.app_id)
是错误的。需要根据app_id
进行JOIN,也就是说应该是:
TblOrganisationSubstances.app_id = (Substances.app_id)
我还尝试将 belongsTo
更改为 hasMany
关联(甚至不确定哪个是正确的!):
$this->hasMany('TblOrganisationSubstances', [
'foreignKey' => 'app_id',
]);
但加入似乎甚至没有发生。产生的SQL是:
SELECT Substances.id AS `Substances__id` FROM substances Substances WHERE TblOrganisationSubstances.o_id = :c0
我也试过在TblOrganisationSubstances.php
中放一个belongsTo
来尝试定义双方的关系:
$this->belongsTo('Substances', [
'foreignKey' => 'app_id',
'joinType' => 'INNER'
]);
同样,这不起作用。它在没有连接的情况下生成 SQL。
请有人帮忙建议哪种关联类型是正确的(hasMany
vs belongsTo
)以及如何根据 app_id
执行连接,这是链接 2 tables.
的外键
在 BelongsTo
关联中,source table 持有外键,因此根据您的配置,它将在 Substances
,并与TblOrganisationSubstances
.
的主键进行比较
为了得到你正在寻找的查询,你还必须定义bindingKey
,即目标的外键table,这样它就不会使用它的主键:
$this->belongsTo('TblOrganisationSubstances', [
'foreignKey' => 'app_id', // Substances.app_id
'bindingKey' => 'app_id', // TblOrganisationSubstances.app_id
'joinType' => 'INNER'
]);
是 HasMany
还是 BelongsTo
取决于您的数据,以及您想要检索数据的内容和方式。一般如果一个Substances
有0个或1个TblOrganisationSubstances
(1:1
),那么就是BelongsTo
或HasOne
。如果一个Substances
可以有多个TblOrganisationSubstances
(1:n
),那么就是HasMany
.
如果您想按 HasMany
关联进行过滤,则需要使用匹配或连接(matching()
、innerJoinWith()
、leftJoinWith()
),因为 HasMany
相关记录将在使用 contain()
.
时在单独的查询中检索
另见
SELECT * FROM sample
LEFT JOIN user
ON sample
.rac_id
=user
.userrac_id
UNION ALL SELECT * FROM sample
RIGHT JOIN user ON sample
.rac_id
=user
.userrac_id
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => ''
)
);
}````
CakePHP 3.7
我有2个型号Table 类如下:
/src/Model/Table/SubstancesTable.php
/src/Model/Table/TblOrganisationSubstancesTable.php
MySQL 中每个 table 的架构如下:
1.
mysql> describe substances;
+-------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| app_id | varchar(8) | NO | UNI | NULL | |
| name | varchar(1500) | NO | | NULL | |
| date | date | NO | | NULL | |
+-------------+-----------------------+------+-----+---------+----------------+
2.
mysql> describe tbl_organisation_substances;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| o_sub_id | int(255) | NO | PRI | NULL | auto_increment |
| o_id | int(255) | NO | MUL | NULL | |
| app_id | varchar(15) | YES | | NULL | |
| os_name | varchar(255) | YES | | NULL | |
| ec | varchar(35) | YES | | NULL | |
| cas | varchar(255) | YES | | NULL | |
| upload_id | int(100) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
我编写了一个自定义查找器,它需要在这 2 个 table 之间执行 JOIN
。自定义查找器看起来像这样,位于 SubstancesTable.php
:
public function findDistinctSubstancesByOrganisation(Query $query, array $options)
{
$o_id = $options['o_id'];
$query = $this->find()->select('id')->contain('TblOrganisationSubstances')->where(['TblOrganisationSubstances.o_id' => $o_id]);
return $query;
}
每个 table 都有一个 app_id
列,这是链接 2 table 的外键。
最初我收到一个错误:
The TblOrganisationSubstances association is not defined on Substances.
这是有道理的,因为尚未制定任何定义。
所以在 SubstancesTable.php
中我定义了这个:
$this->setPrimaryKey('id');
// ...
$this->belongsTo('TblOrganisationSubstances', [
'foreignKey' => 'app_id',
'joinType' => 'INNER'
]);
但这会产生以下 SQL 语句:
SELECT Substances.id AS `Substances__id` FROM substances Substances INNER JOIN tbl_organisation_substances TblOrganisationSubstances ON TblOrganisationSubstances.o_sub_id = (Substances.app_id) WHERE TblOrganisationSubstances.o_id = :c0
这是行不通的,因为 TblOrganisationSubstances.o_sub_id = (Substances.app_id)
是错误的。需要根据app_id
进行JOIN,也就是说应该是:
TblOrganisationSubstances.app_id = (Substances.app_id)
我还尝试将 belongsTo
更改为 hasMany
关联(甚至不确定哪个是正确的!):
$this->hasMany('TblOrganisationSubstances', [
'foreignKey' => 'app_id',
]);
但加入似乎甚至没有发生。产生的SQL是:
SELECT Substances.id AS `Substances__id` FROM substances Substances WHERE TblOrganisationSubstances.o_id = :c0
我也试过在TblOrganisationSubstances.php
中放一个belongsTo
来尝试定义双方的关系:
$this->belongsTo('Substances', [
'foreignKey' => 'app_id',
'joinType' => 'INNER'
]);
同样,这不起作用。它在没有连接的情况下生成 SQL。
请有人帮忙建议哪种关联类型是正确的(hasMany
vs belongsTo
)以及如何根据 app_id
执行连接,这是链接 2 tables.
在 BelongsTo
关联中,source table 持有外键,因此根据您的配置,它将在 Substances
,并与TblOrganisationSubstances
.
为了得到你正在寻找的查询,你还必须定义bindingKey
,即目标的外键table,这样它就不会使用它的主键:
$this->belongsTo('TblOrganisationSubstances', [
'foreignKey' => 'app_id', // Substances.app_id
'bindingKey' => 'app_id', // TblOrganisationSubstances.app_id
'joinType' => 'INNER'
]);
是 HasMany
还是 BelongsTo
取决于您的数据,以及您想要检索数据的内容和方式。一般如果一个Substances
有0个或1个TblOrganisationSubstances
(1:1
),那么就是BelongsTo
或HasOne
。如果一个Substances
可以有多个TblOrganisationSubstances
(1:n
),那么就是HasMany
.
如果您想按 HasMany
关联进行过滤,则需要使用匹配或连接(matching()
、innerJoinWith()
、leftJoinWith()
),因为 HasMany
相关记录将在使用 contain()
.
另见
SELECT * FROM sample
LEFT JOIN user
ON sample
.rac_id
=user
.userrac_id
UNION ALL SELECT * FROM sample
RIGHT JOIN user ON sample
.rac_id
=user
.userrac_id
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => ''
)
);
}````