gpt4 book ai didi

cakephp - 自 "HABTM"或 "HasMany Through"概念混淆

转载 作者:行者123 更新时间:2023-12-02 20:31:27 25 4
gpt4 key购买 nike

赏金:

+500 代表奖励给一个好的解决方案。我已经用头撞墙两周了,准备好寻求帮助了。

表格/模型(简化以显示关联)

  • 节点
    • ID
    • 姓名
    • node_type_id
  • 节点关联
    • ID
    • node_id
    • other_node_id
  • 节点类型
    • ID
    • 姓名

总体思路:

用户可以创建节点类型(例如“电视台”、“电视节目”和“ Actor ”......任何内容)。如果我提前知道节点类型是什么以及每个节点之间的关联,我只需为它们制作模型 - 但我希望这是非常开放的,以便用户可以创建他们想要的任何节点类型。然后,每个节点(特定节点类型的)可以与任何其他节点类型的任何其他节点相关。

描述和我的尝试:

每个节点都应该能够与任何/每个其他节点相关。

我的假设是,要做到这一点,我必须有一个关联表 - 所以我制作了一个名为“node_associations”的表,其中包含 node_idother_node_id

然后我建立了我的关联(通过我相信使用 hasMany ):(以下是我对设置的最佳记忆......可能略有偏差)

//Node model
public $hasMany = array(
'Node' => array(
'className' => 'NodeAssociation',
'foreignKey' => 'node_id'

),
'OtherNode' => array(
'className' => 'NodeAssociation',
'foreignKey' => 'other_node_id'
)
);

//NodeAssociation model
public $belongsTo = array(
'Node' => array(
'className' => 'Node',
'foreignKey' => 'node_id'

),
'OtherNode' => array(
'className' => 'Node',
'foreignKey' => 'other_node_id'
)
);

起初,我以为我明白了 - 这是有道理的。但后来我开始尝试检索数据,并且在过去的两周里一直在用头撞墙。

示例问题:

假设我有以下节点:

  • 全国广播公司
  • ER
  • 乔治·克鲁尼
  • 安东尼·爱德华兹
  • 今晚秀:莱诺
  • 杰·雷诺
  • 狐狸
  • 居家男人

如何设置我的数据结构,以便能够提取所有电视台,并包含他们的电视节目,其中包含他们的 Actor (作为示例)?这对于正常的模型设置来说很简单:

$this->TvStation->find('all', array(
'contain' => array(
'TvShow' => array(
'Actor'
)
)
));

然后,也许我想检索所有男性 Actor 并包含包含电视台的电视节目。或者晚上 9 点开始的电视节目,包含 Actor 和电台...等等。

但是 - 使用 HABTM 或 HasMany 通过 self(更重要的是,未知的数据集),我不知道模型是哪个字段(node_id 或 other_node_id),总的来说,我无法理解我的想法就可以得到内容了。

最佳答案

想法

让我们尝试用约定来解决这个问题,node_id 将是别名按字母顺序排在第一位的模型,而 other_node_id 将是第二位的别名。

对于每个包含的模型,我们动态创建一个与 Node 类的 HABTM 关联,​​为每个关联创建一个别名(请参阅 bindNodesbindNode 方法)。

我们查询的每个表都会在 node_type_id 上添加一个额外条件,以仅返回该类型节点的结果。 NodeType 的 id 通过 getNodeTypeId() 选择,并且应该被缓存。

要在深度相关的关联中使用条件过滤结果,您需要手动添加额外的联接,为每个具有唯一别名的可连接创建联接,然后使用别名联接每个节点类型本身,以便能够应用条件(例如,选择具有 Actor x 的所有 TvChannel。在 Node 类中为此创建一个辅助方法。

注释

在我的演示中,我将 foreignKey 用于 node_id,将 associationForeignKey 用于 other_node_id

节点(不完整)

<?php
/**
* @property Model NodeType
*/
class Node extends AppModel {

public $useTable = 'nodes';

public $belongsTo = [
'NodeType',
];

public function findNodes($type = 'first', $query = []) {
$node = ClassRegistry::init(['class' => 'Node', 'alias' => $query['node']]);
return $node->find($type, $query);
}

// TODO: cache this
public function nodeTypeId($name = null) {
if ($name === null) {
$name = $this->alias;
}
return $this->NodeType->field('id', ['name' => $name]);
}

public function find($type = 'first', $query = []) {
$query = array_merge_recursive($query, ['conditions' => ["{$this->alias}.node_type_id" => $this->nodeTypeId()]]);
if (!empty($query['contain'])) {
$query['contain'] = $this->bindNodes($query['contain']);
}
return parent::find($type, $query);
}

// could be done better
public function bindNodes($contain) {
$parsed = [];
foreach($contain as $assoc => $deeperAssoc) {
if (is_numeric($assoc)) {
$assoc = $deeperAssoc;
$deeperAssoc = [];
}
if (in_array($assoc, ['conditions', 'order', 'offset', 'limit', 'fields'])) {
continue;
}
$parsed[$assoc] = array_merge_recursive($deeperAssoc, [
'conditions' => [
"{$assoc}.node_type_id" => $this->nodeTypeId($assoc),
],
]);
$this->bindNode($assoc);
if (!empty($deeperAssoc)) {
$parsed[$assoc] = array_merge($parsed[$assoc], $this->{$assoc}->bindNodes($deeperAssoc));
foreach($parsed[$assoc] as $k => $v) {
if (is_numeric($k)) {
unset($parsed[$assoc][$k]);
}
}
}
}
return $parsed;
}

public function bindNode($alias) {
$models = [$this->alias, $alias];
sort($models);
$this->bindModel(array(
'hasAndBelongsToMany' => array(
$alias => array(
'className' => 'Node',
'foreignKey' => ($models[0] === $this->alias) ? 'foreignKey' : 'associationForeignKey',
'associationForeignKey' => ($models[0] === $alias) ? 'foreignKey' : 'associationForeignKey',
'joinTable' => 'node_associations',
)
)
), false);
}

}

示例

$results = $this->Node->findNodes('all', [
'node' => 'TvStation', // the top-level node to fetch
'contain' => [ // all child associated nodes to fetch
'TvShow' => [
'Actor',
]
],
]);

关于cakephp - 自 "HABTM"或 "HasMany Through"概念混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12224596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com