我同意Twin的例子有点混乱。让我假设你有一个Product
模型(在你的例子中是Twin),它总是有2个连接到它的Component
模型。
components: id - name
products: id - component1_id - component2_id
我会成立产品如下:
var $belongsTo = array(
'Component1' => array(
'className' => 'Component',
'foreignKey' => 'component1_id'
),
'Component2' => array(
'className' => 'Component',
'foreignKey' => 'component2_id'
)
);
和组件为:
var $hasMany = array(
'ProductWithComponentAsComponent1' => array(
'className' => 'Product',
'foreignKey' => 'component1_id'
),
'ProductWithComponentAsComponent2' => array(
'className' => 'Product',
'foreignKey' => 'component2_id'
)
);
基本上,你应该hasMany
取代你hasOne
。每个组件都有许多产品,它是第一个组件。同时,它有许多产品,它是第二个组件。希望能够说清楚。
编辑1:(呵呵,“ProductWithComponentAsComponent#”只是为了解释的目的,你可以根据你的实际模型保留你喜欢的任何简短,甜美的别名。)
编辑2:根据经验,使用hasOne关系规则很简单 - 使用它,只有当你将单个表分成许多(如用户/个人资料)
编辑3:如果你想所有产品的组件,那么你可以通过两种方式做到这一点。 (A)在您的hasMany关系中将外键定义为false
。
var $hasMany = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => false,
'conditions' => array(
'or' => array(
"Product.component1_id = Component.id",
"Product.component2_id = Component.id"
)
)
)
);
(B)如果上面的方法不起作用(蛋糕怪异的行为,然后现在),你也可以使用一个连接,使之服从。在组件模型中创建一个函数,如下所示:
function fetchProducts($id) {
if (!$id) {
return null;
}
return $this->Product->find('all', array(
'fields' => array('Product.*'),
'joins' => array(
array(
'table' => 'components',
'alias' => 'Component',
'foreignKey' => false,
'type' => 'inner',
'conditions' => array(
'or' => array(
"Product.component1_id = Component.id",
"Product.component2_id = Component.id"
),
'Component.id' => $id
)
)
)
));
}
也许我误解了你,但组件模型代表组件的一个实例(不是一种组件类型),组件只能作为一个产品(也是一个实例,而不是一个“类”)的一部分,作为组件1或组件2。那么关系应该不是一个? 此外,随着你的组件模型(基本上与第一个例子中的相同,除了hasOne-> hasMany),问题仍然是如何访问组件的Product而不必检查两个关系(我可能不在乎组件是产品的组件1或组件2)。 – zephyr 2011-01-05 20:58:04
如果您愿意,您可以用ComponentInstance替换Component。关于hasOne,请参阅编辑2:主要在分割表格时使用它。要访问组件的所有产品,请参阅编辑3. :) – RabidFire 2011-01-06 02:56:21
啊。我不知道你可以将ForeignKey设置为false(这是否记录在某处?)。但它似乎打破了递归。对于组件,递归设置为2时,我得到一个“未知列:WHERE子句中的Component.id”错误,因为组件在产品上的单独查询(来自递归)中不存在。对于定期声明的foreignKey关系,这些类型的查询将id作为常量(例如“(3)”而不是“Component”。“id”)。人们可以做类似于你的方法B的事情,但我希望有一种方法可以与CakePHP系统的其他部分更好地集成。 – zephyr 2011-01-06 11:48:52