HABTM与自己需要2x的行在连接表中? [英] HABTM with self requires 2x the rows in join table?

查看:101
本文介绍了HABTM与自己需要2x的行在连接表中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用 Nodes 作为主要模型来构建CMS。每个节点 belongsTo a NodeType $ c> Node 可以与任何/每其他节点相关。



- 认为这叫HABTM:

  //节点模型
public $ hasAndBelongsToMany = array(
' AssociatedNode'=> array(
'className'=>'Node',
'foreignKey'=>'node_id',
'associationForeignKey'=>'associated_node_id',
'joinTable'=>'node_associations'

);

问题是,它似乎唯一的方式是,如果我有两个行的每个关联



节点




  • ER(id = 1)

  • George Clooney(id = 2)



描述这两个节点之间的关系的连接表中的一行:




  • 'node_id'= 1

  • 'associated_node_id'= 2



我查询电视节目并包含它的Actor节点:

  $ nodes = $ this-> Node-& all',array(
'conditions'=> array(
'Node.node_type_id'=>'645'// tv显示
),
' > array(
'AssociatedNode'=> array(
'conditions'=&array; array(
'AssociatedNode.node_type_id'=>'239'// actors
),


));

这样工作,我得到ER - > George Clooney。



但是 - 如果我想拉所有乔治·克鲁尼所有的节目呢?

  $ nodes = $ this-> Node-> find('all',array(
'conditions'=> array(
'Node.node_type_id'=>'239'// actors
),
'contains'=> array(
'AssociatedNode'=> array(
'conditions'=&array; array(
'AssociatedNode.node_type_id'=& '645'//电视显示
),


));

这不工作,因为它正在寻找乔治·克鲁尼的ID在node_id



我想到的唯一解决方案是为每一行保留两行协会。但这似乎过分。但是,然后我必须提出一些自定义的东西,确保保持每个副本同步w /其他每次关联保存或删除...等 - 这似乎是一个大罐的蠕虫。 / p>

有没有我遗漏的东西?

解决方案

做一个自定义查询,但是为了保持标准的Cake函数,我可以想到的一件事是声明节点之间的两个关系:

  public $ hasAndBelongsToMany = array(
'AssociatedNode1'=> array(
'className'=>'Node',
'foreignKey'=>'node_id' ,
'associationForeignKey'=>'associated_node_id',
'joinTable'=>'node_associations'
),
'AssociatedNode2'=& 'className'=>'Node',
'foreignKey'=>'associated_node_id',
'associationForeignKey'=>'node_id',
'joinTable'=>'node_associations '

);

,然后可以在afterFind回调中合并这两个数组。

  function afterFind($ results)
{
foreach($ results as& $ result)
{
if ($($ result ['AssociatedNode1'])|| isset($ result ['AssociatedNode2']))
{
$ associated_nodes = array

if(isset($ result ['AssociatedNode1']))
{
foreach($ result ['AssociatedNode1'] as $ associated_node)
{
$ associated_nodes [] = $ associated_node;
}
}

if(isset($ result ['AssociatedNode2']))
{
foreach($ result ['AssociatedNode2'] as $ associated_node)
{
$ associated_nodes [] = $ associated_node;
}
}

$ result ['AssociatedNode'] = $ associated_nodes;
}
}
unset($ result);

return $ results;
}

但这会迫使您在调用中声明AssociatedNode1和AssociatedNode2 ();


I'm trying to build a CMS with Nodes as the main model. Each Node belongsTo a NodeType, and every Node can be related to any/every other Node.

So - thought this called for HABTM:

//Node model
public $hasAndBelongsToMany = array(
    'AssociatedNode' => array(
        'className' => 'Node',
        'foreignKey' => 'node_id',
        'associationForeignKey' => 'associated_node_id',
        'joinTable' => 'node_associations'
    )
);

The problem is, it seems like the only way it works is if I have TWO rows for each association.

Example with just one association row:

Nodes

  • ER (id=1)
  • George Clooney (id=2)

A single row in the join-table describing the relationship between those two nodes:

  • 'node_id' = 1
  • 'associated_node_id' = 2

Now - If I query for TV Shows and Contain it's Actor nodes:

$nodes = $this->Node->find('all', array(
        'conditions' => array(
            'Node.node_type_id' => '645' //tv shows
        ),
        'contain' => array(
            'AssociatedNode' => array(
                'conditions' => array(
                    'AssociatedNode.node_type_id' => '239' //actors
                ),
            )
        )
    ));

This works, and I get ER -> George Clooney.

But - what if I want to pull all shows that George Clooney is in?

$nodes = $this->Node->find('all', array(
        'conditions' => array(
            'Node.node_type_id' => '239' //actors
        ),
        'contain' => array(
            'AssociatedNode' => array(
                'conditions' => array(
                    'AssociatedNode.node_type_id' => '645' //tv shows
                ),
            )
        )
    ));

This doesn't work because it's looking for George Clooney's ID to be in the 'node_id' field, and ER's ID to be in the 'associated_node_id' field - when in reality they're reversed.

The only solution I've thought of is to keep two rows for EVERY association. But this seems overkill. But then I have to come up with some kind of custom something that makes sure to keep each duplicate in sync w/ the other every time an association is saved or deleted...etc - and this seems like a large can of worms.

Is there something I'm missing?

解决方案

You could probably do it with a custom query, but to keep with standard Cake functions, one thing I can think of would be to declare two relationships between the Nodes:

public $hasAndBelongsToMany = array(
  'AssociatedNode1' => array(
      'className' => 'Node',
      'foreignKey' => 'node_id',
      'associationForeignKey' => 'associated_node_id',
      'joinTable' => 'node_associations'
  ),
  'AssociatedNode2' => array(
      'className' => 'Node',
      'foreignKey' => 'associated_node_id',
      'associationForeignKey' => 'node_id',
      'joinTable' => 'node_associations'
  )
);

and then you could merge both arrays in an afterFind callback.

function afterFind($results)
{
  foreach($results as &$result)
  {
    if(isset($result['AssociatedNode1']) || isset($result['AssociatedNode2']))
    {
      $associated_nodes = array();

      if(isset($result['AssociatedNode1']))
      {
        foreach($result['AssociatedNode1'] as $associated_node)
        {
          $associated_nodes[] = $associated_node;
        }
      }

      if(isset($result['AssociatedNode2']))
      {
        foreach($result['AssociatedNode2'] as $associated_node)
        {
          $associated_nodes[] = $associated_node;
        }
      }

      $result['AssociatedNode'] = $associated_nodes;
    }
  }
  unset($result);

  return $results;
}

But this would force you to declare both AssociatedNode1 and AssociatedNode2 in the call to contain();

这篇关于HABTM与自己需要2x的行在连接表中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆