I have a few Tables/Models and I want to show the content of the models in one view.
My Schema:
My Models:
Adress:
var $name = "Adress";
public $belongsTo = array("Customer", "Country");
public $hasAndBelongsToMany = array(
'Contactperson' => array(
'className' => 'Contactperson'
)
);
ContactPerson:
var $name = "Contactperson";
public $hasAndBelongsToMany = array(
'Adress' => array(
'className' => 'Adress'
)
);
Country:
var $name = "Country";
public $hasMany = "Adress";
Customer:
var $name = "Customer";
public $hasMany = array(
'Adress' => array(
'className' => 'Adress',
'order' => array('Adress.mainadress DESC', 'Adress.created DESC')
)
);
My CustomerController:
$customer = $this->Customer->findByid($customerId);
$this->set('customer', $customer);
The return value is the content of the customer and the adress table but I want to get the content of every table.
I want to get a array with the content from customers, addresses, contactpeople and countries.
Thanks for helping.
Once you setup and linking each table correctly (with foreign key and db design), then you can retrieve all the related field easily with CakePHP.
Read up on CakePHP containable.
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
Recursive will also works, but higher recursive value can hurt your system if its getting too big.
Related
I am trying to make multiple relation on model as describes in cake kbook
I have two model Account and Tax like this
Account(id, name, code)
Tax(id.name, sales_tax_gl, purchase_tax_gl)
both sales_tax_gl and purchase_tax_gl related to Account.id
these are the model I have created
class Tax extends AppModel {
var $name = 'Tax';
var $displayField = 'name';
var $belongsTo = array(
'SalesTax' => array(
'className' => 'Account',
'foreignKey' => 'sales_tax_gl',
'conditions' => '',
'fields' => '',
'order' => ''
),
'PurchaseTax' => array(
'className' => 'Account',
'foreignKey' => 'purchase_tax_gl',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
Account Model
class Account extends AppModel {
var $name = 'Account';
var$primaryKey = 'id';
var $hasMany = array(
'TaxSalesTax' => array(
'className' => 'Tax',
'foreignKey' => 'sales_tax_gl' ),
'TaxPurchaseTax' => array(
'className' => 'Tax',
'foreignKey' => 'purchase_tax_gl' )
);
}
But it fails with this message "Warning (2): pg_query() [function.pg-query]: Query failed: ERROR: missing FROM-clause entry for table "Account"
What'swrong with the model? I am using postgreSql, thank for your help
In first model your model name is SalesTax and in the second one (Account Model) the model name is TaxSalesTax,please correct it into the correct one and try.
I am thinking that i found the problem. That's cause I use virtual fields in account model like below
var $name = 'Account';
var $primaryKey = 'id';
var $displayField = 'name';
var $order=array('Account.id');
var $virtualFields = array('dropdown_name' => 'Account.id || \' \' || Account.name');
when I uncomment $virtualFields it work as it should, but I still don't know why?
I'm building a CakePHP powered website, where users can refer each other, i was thinking about a "Has and Belongs to many" relationship (A user can have multiple referrals, but can be referred only by one)
is this the right way or it's better with another association / road ?
Thanks in advance!
If I'm correct in assuming that a User can refer many, but may only be referred by one, then something like this should suffice for what you're doing:
//User model
$belongsTo = array(
'Referrer' => array(
'className' => 'User',
'foreignKey' = > 'referrer_id'
)
);
$hasMany = array(
'Referree' => array(
'className' => 'User',
'foreignKey' => 'referrer_id'
)
);
Details about Multiple relations to the same model.
An example of how to retrieve the data:
//User model
public $actsAs = array('Containable');
public $recursive = -1; //better to set in AppModel IMO
public function getUser($userId = null) {
if(empty($userId)) return false;
return $this->find('first', array(
'conditions' => array(
$this->alias . '.' . $this->primaryKey => $userId
),
'contain' => array(
'Referrer',
'Referee'
)
));
}
I have a problem with my comments.
I have User model:
public $hasMany = array('Photo','Comment');
Comment model:
public $belongsTo = array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
),
'Photo'=>array(
'className'=>'Photo',
'foreignKey'=>'photo_id'
)
);
and Photo Model
public $belongsTo = array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
);
public $hasMany = array(
'Comment'=>array(
'className'=>'Comment',
'foreignKey'=>'photo_id'
)
);
When I read data of a photo I got:
'Photo' => array -> info about photo which is ok for me
'User' => array -> info about user ok for me
'Comment' => array -> all comments but only with id of users.
How can I connet comments with users to get username related with comment while retrieving data about photo?
You need to call $this->recursive = 2 before you call find(), that will fetch all associations of every object returned by your query. Alternatively you can set the $recursive variable inside any of your models.
The different types of recursion are as follows:
-1 Cake fetches Photo data only, no joins.
0 Cake fetches Photo data and its domain
1 Cake fetches a Photo, its domain and its associated Comments
2 Cake fetches a Photo, its domain, its associated Comments, and the
Comments’ associated Users
I also suggest considering Containable since you have complete control of all the data that is returned, down to specifying each field in any association
The photo model:
<?php
class Photo extends AppModel {
public $actsAs = array('Containable');
}
And your find method will look like this:
<?php
$this->Photo->find('all', array(
'contain' => array(
'User',
'Comment' => array(
'User' = array(
'fields' => array('username')
),
'conditions' => array(
'Comment.erased' => 0
)
))
'conditions' => array(
'Photo.id' => $id
)));
I'm building an MMA (mixed martial arts) website with CakePHP. I've got a fights table in my database that has three columns at its simplest: id, fighter_a, and fighter_b.
I'm having trouble getting my head around what type of relation my Fight model would have with my Fighter module. Am I right in thinking fighter_a and fighter_b would be two hasOne relations?
I tried this with the following in my Fight model:
<?php
class Fight extends AppModel {
public $name = 'Fight';
public $hasOne = array(
'FighterA' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_a'
),
'FighterB' => array(
'className' => 'Fighter',
'foreignKey' => 'fighter_b'
)
);
}
And then this in my Fighter model:
<?php
class Fighter extends AppModel {
public $name = 'Fighter';
public $hasMany = array(
'Fight'
);
}
But this threw an error in my CakePHP application when calling $this->Fight->findById($id) (where $id was the ID of a fighter):
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Fight.fighter_id' in 'field list'
How can I link my models so that I can call all fights a fighter has been in?
Distilled from conversation under the question, the solution would be this:
Rewrite the $hasMany in your FighterModel to look like:
public $hasMany = array(
'Fight' => array(
'className' => 'Fight',
'finderQuery' => 'SELECT * FROM fights AS Fight WHERE Fight.fighter_a_id = {$__cakeID__$} OR Fight.fighter_b_id = {$__cakeID__$};'
)
);
I have the model AccountLicense, when I execute the method getExpiringLicenes for some reason the association I have with the parent model (AccountUser) the primary key of AccountUser is not being used, it is instead using the default primary key 'id'. I am not sure why this is happening. This is all part of a plugin.
Any help with this is greatly appreciated.
This is the exception I am getting:
Warning (512): SQL Error: 1054: Unknown column 'AccountUser.id' in 'on clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 684]
This is the query that is being executed:
SELECT `AccountLicense`.`license_id`, `AccountLicense`.`user_id`,
`AccountLicense`.`board_id`, `AccountLicense`.`license_number`,
`AccountLicense`.`license_state`, `AccountLicense`.`license_designation_id`,
`AccountLicense`.`active_date`, `AccountLicense`.`expire_date`,
`AccountLicense`.`is_active`, `AccountLicense`.`is_confirmed`,
`AccountLicense`.`is_primary`, `AccountUser`.`user_id`, `AccountUser`.`user_name`,
`AccountUser`.`user_pass`, `AccountUser`.`user_status`, `AccountUser`.`user_group`,
`AccountUser`.`instance_id`, `AccountUser`.`is_logged_in`, `AccountUser`.`is_visible`,
`AccountUser`.`created_by`, `AccountUser`.`last_modified_by`,
`AccountUser`.`created_date`, `AccountUser`.`last_modified_date`
FROM `account_licenses` AS `AccountLicense`
LEFT JOIN `account_users` AS `AccountUser`
ON (`AccountLicense`.`user_id` = `AccountUser`.`id`)
WHERE `AccountLicense`.`expire_date` BETWEEN '2011-10-05' and '2011-11-04'
This is my AccountLicenses model:
<?php
class AccountLicense extends AppModel {
var $name = 'AccountLicense';
var $primaryKey = 'license_id';
var $plugin = 'AccountModule';
var $belongsTo = array(
'AccountUser' => array(
'className' => 'AccountUser',
'foreignKey' => 'user_id'
)
);
public function getExpiringLicenses($date = null)
{
if(is_null($date))
$date = date('Y-m-d',strtotime("+30 days"));
return $this->find(
'all',
array(
'conditions' => array(
$this->name . '.expire_date BETWEEN ? and ?' =>array(date('Y-m-d'),$date)
)
)
);
}
}
?>
This is my AccountUser model:
<?php
class AccountUser extends AppModel {
var $name = 'AccountUser';
var $primaryKey = 'user_id';
var $actsAs = array('Containable');
var $validate = array(
'user_name'=>array(
'rule'=>'isUnique',
'message'=>'This username has already been taken. Please try again'
),
'user_pass' => array(
'rule' => array('between', 8, 16),
'message' => 'Passwords must be between 8 and 16 characters long.')
);
var $hasMany = array(
'AccountLicense' => array(
'className' => 'AccountLicense',
'foreignKey' => 'user_id'
)
);
?>
Since is a plugin your association should have the plugin name
Example:
If your plugin name is AccountModule your association should look like
var $belongsTo = array(
'AccountUser' => array(
'className' => 'AccountModule.AccountUser',
'foreignKey' => 'user_id'
)
);
Also is not wrong, but the correct way to declare a model class inside a plugin is
<?php
class AccountLicense extends AccountModuleAppModel {
If it is in the correct place in your folder structure and correctly declared you won't need this line
var $plugin = 'AccountModule';