cakephp 3 保存自引用 belongsToMany
cakephp 3 saving self referencing belongsToMany
我有一个nodes
table和一个nodes_nodes
table。
nodes table
+----+--------+
| id | name |
+----+--------+
| 1 | Node1 |
| 2 | Node2 |
| 3 | Node3 |
| 4 | Node4 |
| 5 | Node5 |
+----+--------+
nodes_nodes table
+----+----------------+---------------+
| id | parent_node_id | child_node_id |
+----+----------------+---------------+
| 1 | 2 | 3 |
| 2 | 1 | 4 |
| 3 | 1 | 5 |
+----+----------------+---------------+
一个节点可以有一个或多个父节点和一个或多个子节点
NodesTable.php:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('nodes');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('ChildNodes', [
'className' => 'Nodes',
'joinTable' => 'nodes_nodes',
'foreignKey' => 'parent_node_id',
'targetForeignKey' => 'child_node_id'
]);
$this->belongsToMany('ParentNodes', [
'className' => 'Nodes',
'joinTable' => 'nodes_nodes',
'foreignKey' => 'child_node_id',
'targetForeignKey' => 'parent_node_id'
]);
}
Node.php
class Node extends Entity
{
protected $_accessible = [
'*' => true,
'id' => false,
'ParentNodes' => true,
'ChildNodes' => true,
'_joinData' => true,
];
}
NodesController.php
public function add()
{
$node = $this->Nodes->newEntity();
if ($this->request->is('post')) {
$node = $this->Nodes->patchEntity($node, $this->request->data);
debug($node);
if ($this->Nodes->save($node)) {
$this->Flash->success(__('The node has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The node could not be saved. Please, try again.'));
}
$nodes = $this->Nodes->find('list', ['limit' => 200]);
$this->set(compact('node', 'nodes'));
$this->set('_serialize', ['node']);
}
add.ctp形式:
<?= $this->Form->create($node) ?>
<fieldset>
<legend><?= __('Add Node') ?></legend>
<?php
echo $this->Form->input('name');
echo $this->Form->input('ParentNodes._ids', ['options' => $nodes]);
echo $this->Form->input('ChildNodes._ids', ['options' => $nodes]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
add() 函数中 $node 实体调试的输出:
object(App\Model\Entity\Node) {
'name' => 'Node6',
'ParentNodes' => [
'_ids' => [
(int) 0 => '15',
(int) 1 => '12'
]
],
'ChildNodes' => [
'_ids' => [
(int) 0 => '13'
]
],
'[new]' => true,
'[accessible]' => [
'*' => true,
'ParentNodes' => true,
'ChildNodes' => true,
'_joinData' => true
],
'[dirty]' => [
'name' => true,
'ParentNodes' => true,
'ChildNodes' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Nodes'
}
当我保存一个新节点时,关联并没有被保存。
我尝试在 $this->Nodes->save()
上添加 ['associated' => ['ParentNodes', 'ChildNodes']]
但没有成功
您没有正确遵循命名约定。 属性 belongsToMany
关联的名称默认为小写、带下划线的关联别名的复数变体,即 parent_nodes
和 child_nodes
。如果需要,可以通过 propertyName
关联选项更改。
echo $this->Form->input('parent_nodes._ids', ['options' => $nodes]);
echo $this->Form->input('child_nodes._ids', ['options' => $nodes]);
此外,如果您已将 *
设置为 true
,则无需将属性添加到 $_accessible
,因为这样可以批量分配所有内容。
另见
我有一个nodes
table和一个nodes_nodes
table。
nodes table
+----+--------+
| id | name |
+----+--------+
| 1 | Node1 |
| 2 | Node2 |
| 3 | Node3 |
| 4 | Node4 |
| 5 | Node5 |
+----+--------+
nodes_nodes table
+----+----------------+---------------+
| id | parent_node_id | child_node_id |
+----+----------------+---------------+
| 1 | 2 | 3 |
| 2 | 1 | 4 |
| 3 | 1 | 5 |
+----+----------------+---------------+
一个节点可以有一个或多个父节点和一个或多个子节点
NodesTable.php:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('nodes');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('ChildNodes', [
'className' => 'Nodes',
'joinTable' => 'nodes_nodes',
'foreignKey' => 'parent_node_id',
'targetForeignKey' => 'child_node_id'
]);
$this->belongsToMany('ParentNodes', [
'className' => 'Nodes',
'joinTable' => 'nodes_nodes',
'foreignKey' => 'child_node_id',
'targetForeignKey' => 'parent_node_id'
]);
}
Node.php
class Node extends Entity
{
protected $_accessible = [
'*' => true,
'id' => false,
'ParentNodes' => true,
'ChildNodes' => true,
'_joinData' => true,
];
}
NodesController.php
public function add()
{
$node = $this->Nodes->newEntity();
if ($this->request->is('post')) {
$node = $this->Nodes->patchEntity($node, $this->request->data);
debug($node);
if ($this->Nodes->save($node)) {
$this->Flash->success(__('The node has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The node could not be saved. Please, try again.'));
}
$nodes = $this->Nodes->find('list', ['limit' => 200]);
$this->set(compact('node', 'nodes'));
$this->set('_serialize', ['node']);
}
add.ctp形式:
<?= $this->Form->create($node) ?>
<fieldset>
<legend><?= __('Add Node') ?></legend>
<?php
echo $this->Form->input('name');
echo $this->Form->input('ParentNodes._ids', ['options' => $nodes]);
echo $this->Form->input('ChildNodes._ids', ['options' => $nodes]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
add() 函数中 $node 实体调试的输出:
object(App\Model\Entity\Node) {
'name' => 'Node6',
'ParentNodes' => [
'_ids' => [
(int) 0 => '15',
(int) 1 => '12'
]
],
'ChildNodes' => [
'_ids' => [
(int) 0 => '13'
]
],
'[new]' => true,
'[accessible]' => [
'*' => true,
'ParentNodes' => true,
'ChildNodes' => true,
'_joinData' => true
],
'[dirty]' => [
'name' => true,
'ParentNodes' => true,
'ChildNodes' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Nodes'
}
当我保存一个新节点时,关联并没有被保存。
我尝试在 $this->Nodes->save()
上添加 ['associated' => ['ParentNodes', 'ChildNodes']]
但没有成功
您没有正确遵循命名约定。 属性 belongsToMany
关联的名称默认为小写、带下划线的关联别名的复数变体,即 parent_nodes
和 child_nodes
。如果需要,可以通过 propertyName
关联选项更改。
echo $this->Form->input('parent_nodes._ids', ['options' => $nodes]);
echo $this->Form->input('child_nodes._ids', ['options' => $nodes]);
此外,如果您已将 *
设置为 true
,则无需将属性添加到 $_accessible
,因为这样可以批量分配所有内容。
另见