CakePHP3.4:不理解保存 belongsToMany 关联的错误
CakePHP3.4: don't understand error saving a belongsToMany association
我尝试在表单中输入一个 belongsToMany
关联,但是一个非常特殊的关联描述。
因为我的实体 Site
可以将语言用于 2 种不同的用途,所以我使用 2 个连接表。
所以架构如下
Relationship Join Table Fields
Sites belongsToMany Vislanguages sites_vislanguages.id, sites_vislanguages.language_id, sites_vislanguages.site_id
Relationship Join Table Fields
Sites belongsToMany Reclanguages sites_reclanguages.id, sites_reclanguages.language_id, sites_reclanguages.site_id
所以 Table
class 是:
class VislanguagesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('languages');
$this->displayField('name_fr');
$this->primaryKey('id');
$this->belongsToMany('Sites', [
'foreignKey' => 'language_id',
'targetForeignKey' => 'site_id',
'joinTable' => 'sites_vislanguages',
]);
}
}
class SitesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->belongsToMany('Reclanguages', [
'joinTable' => 'sites_reclanguages',
'className' => 'Languages',
'propertyName' => 'reclanguages'
]);
$this->belongsToMany('Vislanguages', [
'joinTable' => 'sites_vislanguages',
'className' => 'Languages',
'propertyName' => 'vislanguages'
]);
}
class SitesVislanguagesTable 扩展 Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('sites_vislanguages');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Sites', [
'foreignKey' => 'site_id',
]);
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
]);
}
我当然有add
和edit
形式的问题,但我这里以edit
为例。
如果我find()
一个现成的site
,数据结构是:
object(App\Model\Entity\Site) {
'id' => (int) 23098,
'Vislanguages' => [
(int) 0 => object(App\Model\Entity\Language) {
'id' => (int) 1,
'_joinData' => object(App\Model\Entity\SitesVislanguage) {
'id' => (int) 4409,
'site_id' => (int) 23098,
'language_id' => (int) 1,
...,
'[repository]' => 'SitesVislanguages'
},
...,
'[repository]' => 'Vislanguages'
},
(int) 1 => object(App\Model\Entity\Language) {
'id' => (int) 9,
'_joinData' => object(App\Model\Entity\SitesVislanguage) {
'id' => (int) 4410,
'site_id' => (int) 23098,
'language_id' => (int) 9,
...,
'[repository]' => 'SitesVislanguages'
},
...,
'[repository]' => 'Vislanguages'
}
],
...,
'[repository]' => 'Sites'
}
而我对应的ctp
文件是:
<?= $this->Form->control('vislanguages._ids', ['options' => $languages, 'label' => __('Spoken languages:'), 'multiple' => true]); ?>
在输入中正确预选了语言。
如果我不做任何修改提交,打补丁的实体是:
对象(App\Model\Entity\Site) {
'id' => (int) 23098,
...,
'vislanguages' => [
(int) 0 => object(App\Model\Entity\Language) {
'id' => (int) 1,
...,
'[repository]' => 'Vislanguages'
},
(int) 1 => object(App\Model\Entity\Language) {
'id' => (int) 9,
...,
'[repository]' => 'Vislanguages'
}
],
'[repository]' => 'Sites'
}
这似乎是正确的,但当我保存它时,出现以下错误:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'vislanguage_id' in 'where clause'
查询是:
(SELECT SitesVislanguages.id AS `SitesVislanguages__id`, SitesVislanguages.site_id AS `SitesVislanguages__site_id`, SitesVislanguages.language_id AS `SitesVislanguages__language_id` FROM sites_vislanguages SitesVislanguages WHERE (site_id = :c0 AND vislanguage_id = :c1))
UNION (SELECT SitesVislanguages.id AS `SitesVislanguages__id`, SitesVislanguages.site_id AS `SitesVislanguages__site_id`, SitesVislanguages.language_id AS `SitesVislanguages__language_id` FROM sites_vislanguages SitesVislanguages WHERE (site_id = :c2 AND vislanguage_id = :c3))
为什么我们在 WHERE
子句中看到 vislanguage_id
而在 SELECT
子句中却正确地考虑了 language_id
?
同时,这里的UNION
我也不是很懂
为了让它工作,我必须指定 targetForeignKey
:
class SitesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->belongsToMany('Reclanguages', [
'targetForeignKey' => 'language_id,
'joinTable' => 'sites_reclanguages',
'className' => 'Languages',
'propertyName' => 'reclanguages'
]);
$this->belongsToMany('Vislanguages', [
'targetForeignKey' => 'language_id,
'joinTable' => 'sites_vislanguages',
'className' => 'Languages',
'propertyName' => 'vislanguages'
]);
}
我尝试在表单中输入一个 belongsToMany
关联,但是一个非常特殊的关联描述。
因为我的实体 Site
可以将语言用于 2 种不同的用途,所以我使用 2 个连接表。
所以架构如下
Relationship Join Table Fields
Sites belongsToMany Vislanguages sites_vislanguages.id, sites_vislanguages.language_id, sites_vislanguages.site_id
Relationship Join Table Fields
Sites belongsToMany Reclanguages sites_reclanguages.id, sites_reclanguages.language_id, sites_reclanguages.site_id
所以 Table
class 是:
class VislanguagesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('languages');
$this->displayField('name_fr');
$this->primaryKey('id');
$this->belongsToMany('Sites', [
'foreignKey' => 'language_id',
'targetForeignKey' => 'site_id',
'joinTable' => 'sites_vislanguages',
]);
}
}
class SitesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->belongsToMany('Reclanguages', [
'joinTable' => 'sites_reclanguages',
'className' => 'Languages',
'propertyName' => 'reclanguages'
]);
$this->belongsToMany('Vislanguages', [
'joinTable' => 'sites_vislanguages',
'className' => 'Languages',
'propertyName' => 'vislanguages'
]);
}
class SitesVislanguagesTable 扩展 Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('sites_vislanguages');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Sites', [
'foreignKey' => 'site_id',
]);
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
]);
}
我当然有add
和edit
形式的问题,但我这里以edit
为例。
如果我find()
一个现成的site
,数据结构是:
object(App\Model\Entity\Site) {
'id' => (int) 23098,
'Vislanguages' => [
(int) 0 => object(App\Model\Entity\Language) {
'id' => (int) 1,
'_joinData' => object(App\Model\Entity\SitesVislanguage) {
'id' => (int) 4409,
'site_id' => (int) 23098,
'language_id' => (int) 1,
...,
'[repository]' => 'SitesVislanguages'
},
...,
'[repository]' => 'Vislanguages'
},
(int) 1 => object(App\Model\Entity\Language) {
'id' => (int) 9,
'_joinData' => object(App\Model\Entity\SitesVislanguage) {
'id' => (int) 4410,
'site_id' => (int) 23098,
'language_id' => (int) 9,
...,
'[repository]' => 'SitesVislanguages'
},
...,
'[repository]' => 'Vislanguages'
}
],
...,
'[repository]' => 'Sites'
}
而我对应的ctp
文件是:
<?= $this->Form->control('vislanguages._ids', ['options' => $languages, 'label' => __('Spoken languages:'), 'multiple' => true]); ?>
在输入中正确预选了语言。 如果我不做任何修改提交,打补丁的实体是:
对象(App\Model\Entity\Site) {
'id' => (int) 23098,
...,
'vislanguages' => [
(int) 0 => object(App\Model\Entity\Language) {
'id' => (int) 1,
...,
'[repository]' => 'Vislanguages'
},
(int) 1 => object(App\Model\Entity\Language) {
'id' => (int) 9,
...,
'[repository]' => 'Vislanguages'
}
],
'[repository]' => 'Sites'
}
这似乎是正确的,但当我保存它时,出现以下错误:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'vislanguage_id' in 'where clause'
查询是:
(SELECT SitesVislanguages.id AS `SitesVislanguages__id`, SitesVislanguages.site_id AS `SitesVislanguages__site_id`, SitesVislanguages.language_id AS `SitesVislanguages__language_id` FROM sites_vislanguages SitesVislanguages WHERE (site_id = :c0 AND vislanguage_id = :c1))
UNION (SELECT SitesVislanguages.id AS `SitesVislanguages__id`, SitesVislanguages.site_id AS `SitesVislanguages__site_id`, SitesVislanguages.language_id AS `SitesVislanguages__language_id` FROM sites_vislanguages SitesVislanguages WHERE (site_id = :c2 AND vislanguage_id = :c3))
为什么我们在 WHERE
子句中看到 vislanguage_id
而在 SELECT
子句中却正确地考虑了 language_id
?
同时,这里的UNION
我也不是很懂
为了让它工作,我必须指定 targetForeignKey
:
class SitesTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->belongsToMany('Reclanguages', [
'targetForeignKey' => 'language_id,
'joinTable' => 'sites_reclanguages',
'className' => 'Languages',
'propertyName' => 'reclanguages'
]);
$this->belongsToMany('Vislanguages', [
'targetForeignKey' => 'language_id,
'joinTable' => 'sites_vislanguages',
'className' => 'Languages',
'propertyName' => 'vislanguages'
]);
}