Suppose (for lack of better example) I have a model Person and another model Twin (meaning a pair of twins). Twins has two Person foreign keys, say first_born_id and second_born_id referencing the id fields of two different people (in Person). How do I set up the relationships in cake?
I guess Twin would have something like:
$belongsTo = array('FirstBorn' => array('className' => 'Person',
'foreignKey' => 'firstborn_id'),
'SecondBorn' => array('className' => 'Person',
'foreignKey' => 'secondborn_id'));
But how should I set up Person? I could do it like:
$hasOne = array('TwinAsFirstborn' => array('className' => 'Twin',
'foreignKey' => 'firstborn_id'),
'TwinAsSecondborn' => array('className' => 'Twin',
'foreignKey' => 'secondborn_id'));
But then when I have a Person and I want to know about its twin I would need to check both relationships. I guess I am hoping there is a way to get a "Twin" relationship in Person representing any of the two ways a Person can be in a Twin relationship.
Or is the开发者_JAVA技巧re a better way to set this up?
I agree with the Twin example being a little confusing. Let me assume that you have a Product
model (Twin in your example) and it always has 2 Component
models attached to it.
components: id - name
products: id - component1_id - component2_id
I would set up Product as follows:
var $belongsTo = array(
'Component1' => array(
'className' => 'Component',
'foreignKey' => 'component1_id'
),
'Component2' => array(
'className' => 'Component',
'foreignKey' => 'component2_id'
)
);
And Component as:
var $hasMany = array(
'ProductWithComponentAsComponent1' => array(
'className' => 'Product',
'foreignKey' => 'component1_id'
),
'ProductWithComponentAsComponent2' => array(
'className' => 'Product',
'foreignKey' => 'component2_id'
)
);
Basically, you should replace your hasOne
with hasMany
. Each component hasMany products where it is the first component. At the same time, it hasMany products where it is the second component. Hope that makes things clear.
EDIT 1: (Oh, and "ProductWithComponentAsComponent#" is just for the purpose of explanation. You can keep whatever short, sweet alias you'd like depending on your actual models.)
EDIT 2: Simple rule of thumb for using hasOne relationships - Use it only when you're splitting a single table into many (like User/Profile)
EDIT 3: If you want all Products for a Component, then you can do this in two ways.
(A) Define the foreignKey as false
in your hasMany relation.
var $hasMany = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => false,
'conditions' => array(
'or' => array(
"Product.component1_id = Component.id",
"Product.component2_id = Component.id"
)
)
)
);
(B) If the above method does not work (Cake acts weird now and then), you can also use a join to make it obey. Create a function in the Component model like so:
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
)
)
)
));
}
Why would you define a twin like this?
A twin, first or second born is a person. The thing that associates them with a parent is the fact they are a "child" and their "DOB" is the same.
So would you not do something like:
Person -> ID, Name, Age, DOB, Parent_ID
The parent_ID is stored into the childs record, and the twin is determined by comparing all children under a parent for DOB?
Does this make it any easier to set up your cakePHP relationships?
精彩评论