hasOne relationship only serves if you have 1 to 1 association to be able to access the associated model within the model which has no foreign key.
belongsTo
In your case, you want to use belongsTo, belongsTo is used as soon as you have a foreign key in your model pointing to another model, your Operator model has foreign keys pointing to Contact, Address, Land which are resp. contact_id, address_id and land_id.
Since the contact_id field is in the Operator model, then the Operator model belongsTo the Contact model.
class Operator extends AppModel {
public $belongsTo = array('Contact') ;
}
When fetching an Operator entry, you will get something like:
Array(
[Operator] => Array
(
[id] => 42,
[name] => 'operator',
[contact_id] => 33
)
[Contact] => Array
(
[id] => 33,
[name] => 'contact'
)
)
hasOne and hasMany
Since your Operator belongsTo Contact, your Contact hasOne OR hasMany Operator. Let's illustrate the difference between the two:
- Each of your
Contact entry is associated to only one Operator, you could add a operator_id foreign key inside your Contact model but it would be redundant because you already have the association using contact_id in Operator. Thus, what you do is create a hasOne association inside the Contact model, so Contact hasOne Operator.
class Contact extends AppModel {
public $hasOne = array('Operator') ;
}
Again, when fetching a Contact entry you will get:
Array(
[Contact] => Array
(
[id] => 33,
[name] => 'contact'
)
[Operator] => Array
(
[id] => 42,
[name] => 'operator',
[contact_id] => 33
)
)
Note that this is the same as when fecthing an Operator with a belongsTo Contact. The difference between hasOne and belongsTo is mainly which model has a foreign key pointing to the other.
- Eah of your
Contact entry is associated to multiple (many) Operator, in this case your Contact hasMany Operator.
class Contact extends AppModel {
public $hasMany = array('Operator') ;
}
Again, the output of $this->Contact->find():
Array(
[Contact] => Array
(
[id] => 33,
[name] => 'contact'
)
[Operator] => Array
(
[0] => Array
(
[id] => 42,
[name] => 'operator 42',
[contact_id] => 33
)
[0] => Array
(
[id] => 47,
[name] => 'operator 47',
[contact_id] => 33
)
)
)
hasAndBelongsToMany
Now, assume one Operator can have multiple Contact, and one Contact can serve multiple Operator. In this case, you need an extra table (which should be called operators_contacts if you follow CakePHP naming convention), with two fields operator_id and contact_id:
class Contact extends AppModel {
public $hasAndBelongsToMany = array('Operator') ;
}
class Operator extends AppModel {
public $hasAndBelongsToMany = array('Contact') ;
}
The output of $this->Contact->find('all') will be similar to the one using the hasMany relationship, main difference would be that their is no operator_id or contact_id field in the model.
Full example
Let's assume I have the following models: Company, Employee, Address, and the following constraints:
- A
Company has various Employee but only one CEO which is part of its Employee
- A
Company has one Address, and there is at most one company at each Address
You have the following tables:
CREATE TABLE companies (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
ceo_id INTEGER REFERENCES employees (id)
) ;
CREATE TABLE employees (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
company_id INTEGER REFERENCES companies (id)
) ;
CREATE TABLE addresses (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
company_id INTEGER REFERENCES companies (id)
) ;
Note that in this case, you cannot the table with all the constraints because you have a loop between companies and employees, you need to add the constraints after.
And the following CakePHP models:
class Company extends AppModel {
/* A Company has many Employee. */
public $hasMany = array('Employee') ;
/* A Company has one CEO, but the key is in the Company model,
so it is a belongsTo relationship. */
public $belongsTo = array(
'CEO' => array(
'className' => 'Employee', // It's an Employee
'foreignKey' => 'ceo_id'
)
) ;
/* A Company has one address. */
public $hasOne = array('Address') ;
} ;
class Employee extends AppModel {
/* An Employee belongs to a Company. */
public $belongsTo = array('Company') ;
} ;
class Address extends AppModel {
/* An address belongs to a Company. */
public $belongsTo = array('Company') ;
} ;
Notice I have put a company_id foreign key in the Address model, so Address belongsTo Company and Company hasOne Address, I could have put a address_id inside the Company model and I would have had Company belongsTo Address and Address hasOne Company. I made an arbitrary choice here, in a real application you should think of which of the two above cases is the most meaningful.
Also note that the way I defined my model, there is nothing that prevent an Employee to be the CEO of a Company without being one of its own Employee.
You can find more information in the CakePHP 2.x Book.
contactstable have any records?belongsToinOperator? Doesn't a Contact belong to a Operator?XbelongsTo anotherYif it has a foreign keyy_idpointing toY.id. SinceOperatorhas a keycontact_idpointing toContact.id,OperatorbelongsToContact.Contactdoes not have aoperator_idkey (I assumed so), soContactdoes not belongsToOperator, butContactmay hasOne or hasManyOperator.