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?
Related
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.
i'm new in CakePHP and i'm having problems in an example i'm building to learn.
I'm building a plugin with 3 models (Categoria,Plato,Imagen)
The relationships between them are the following:
Categoria - Plato (n-n)
Plato - Imagen (1-n)
If I go to Plato view, I get all Imagen by the relationship, but when I access through a category, I can't just reach the Imagen associated with each Plato. Why? What's the problem?
Models code:
Plato:
App::uses('AppModel', 'Model');
class Plato extends ErestaurantAppModel {
public $name = 'Plato';
//public $actsAs = array('Containable');
public $hasAndBelongsToMany = array(
'Categoria' => array(
'className' => 'Categoria',
'joinTable' => 'categorias_platos',
'foreignKey' => 'plato_id',
'associationForeignKey' => 'categoria_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
public $hasMany = array('Imagen' =>
array('foreingkey' => array('plato_id')));
}
Categoria:
App::uses('AppModel', 'Model');
class Categoria extends ErestaurantAppModel {
public $name = 'Categoria';
//public $actsAs = array('Containable');
public $hasAndBelongsToMany = array(
'Plato' => array(
'className' => 'Plato',
'joinTable' => 'categorias_platos',
'foreignKey' => 'categoria_id',
'associationForeignKey' => 'plato_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
}
Imagen:
App::uses('AppModel', 'Model');
class Imagen extends ErestaurantAppModel {
public $name = 'Imagen';
//public $actsAs = array('Containable');
public $belongsTo = array('Plato');
}
Finally, the code I'm launching when i go to a Categoria view.
App::uses('AppController', 'Controller');
class CategoriasController extends ErestaurantAppController {
public $uses = array('Erestaurant.Categoria');
public function index() {
$this->Categoria->recursive = 0;
$this->set('data', $this->Categoria->find('all'));
}
public function view($id = null) {
if (!$this->Categoria->exists($id)) {
throw new NotFoundException(__('Registro inválido.'));
}
/*
$this->Categoria->recursive = -1;
$options = array('conditions' =>
array('Categoria.'.$this->Categoria->primaryKey => $id),
'contain' => array(
'Plato' => array(
'Imagen'
)
)
);
*/
$this->Categoria->recursive = 2;
$options = array('conditions' =>
array('Categoria.'.$this->Categoria->primaryKey => $id));
$this->set('item', $this->Categoria->find('first', $options));
}
}
The commented code you see it's another way I tried, using Containable, but at the end I get error "Plato is not associated with model Imagen"
Database seems all ok, with each table created as needed (categorias, platos, imagens, categorias_platos) and with all foering keys created and trying to keep CakePHP default names.
Thank you!
To access deep relations you must use containable behavior. You have a definition of containable behavior in your model, but for some reason it is commented.
public $actsAs = array('Containable');
Uppon uncommenting this line in your Categoria, you can access deep relations in this way:
$this->Categoria->find('all', array(
'contain'=>array(
'Plato.Imagen'
)
));
...or something like this. For more information plase visit this link Containable Behavior
sorry for my english and i'm new using CAKEPHP 2.3
i get a problem using model association where i can't get "joined data" ( i understand that cakephp get automatically joined data if models are set good , obviously i make it wrong )
I have 2 tables in my database:
departements (with the following columns)
-id
-name
-region_id ( region_id is a foreign key on regions(id) )
regions (with the following columns)
-id
-name
i make two models in cakePhp:
Region.php
<?php
class Region extends AppModel {
var $name = 'Region';
var $actsAs = array( 'Containable' );
public $hasMany = array(
'Departement' => array(
'className' => 'Departement',
'foreignKey' => 'region_id',
'dependent' => false
)
);
}
?>
Departement.php
<?php
class Departement extends AppModel {
var $name = 'Departement';
var $actsAs = array( 'Containable' );
public $belongsTo=array(
'Region' => array(
'className' => 'Region',
'foreignKey' => 'region_id',
'dependent' => false
)
);
}
?>
in a another controller where i need departements and regions, i tryed many thinks but after yours i need your help please !!!
i make this :
first attempt:
<?php
class SignalementsController extends AppController {
public $helpers = array('Html', 'Form');
var $name = 'Signalements';
var $uses = array('Signalements','Regions','Departements','Communes');
public $recursive = 4;
public function index() {
$departements = $this->Departements->find('all');
$this->set('departements', $departements);
}
}
who output in the index view:
array(
(int) 0 => array(
'Departements' => array(
'id' => '1',
'name' => 'AIN',
'region_id' => '82'
)
),
(int) 1 => array(
'Departements' => array(
'id' => '10',
'name' => 'AUBE',
'region_id' => '21'
)
)
...
)
but there is no region joined automatically
second attempt: i change the find models from
$regions = $this->Regions->find('all');
$this->set('regions', $regions);
who output :
array(
(int) 0 => array(
'Regions' => array(
'id' => '11',
'name' => 'ILE-DE-FRANCE'
)
), ... );
but there is no departements joined automatically
last
$fields=array('Region.id','Region.nom','Departement.id','Departement.nom');
$all= $this->Regions->Departements->find('all',$fields);
/* or all this not working as execpted
$all= $this->Departements->Regions->find('all',$fields);
$all= $this->Departements->find('all',$fields);
$all= $this->Regions->find('all',$fields);
*/
$this->set('all', $all);
i try to get the regions data inside each departemts for exemple like this
array(
(int) 0 => array(
'Departements' => array(
'id' => '1',
'nom' => 'AIN',
'region' => array( 'id' => '82', 'nom' => 'POITOU-CHARENTES')
)
),
but i get only this :
array(
(int) 0 => array(
'Departements' => array(
'id' => '1',
'nom' => 'AIN',
'region_id' => '82'
)
),
If you have any idea please leave it
thank you very much
You are using Containable behaviour in your model, so try the find with this:
$departements = $this->Departement->find('all', array('contain' => 'Region'));
Also the maximum level for recursive is 2, setting it to 4 (or 1000) has the effect of 2.
Your ID is of type varchar and should be int.
Also, here is a stripped down version of your code
Region.php
<?php
class Region extends AppModel {
var $actsAs = array( 'Containable' );
public $hasMany = array( 'Departement' );
}
?>
Departement.php
<?php
class Departement extends AppModel {
var $actsAs = array( 'Containable' );
public $belongsTo=array( 'Region' );
}
?>
<?php
class SignalementsController extends AppController {
public $helpers = array('Html', 'Form');
var $uses = array('Signalements','Regions','Departements','Communes');
public function index() {
$this->Departement->recursive = 1;
$departements = $this->Departements->find('all');
$this->set('departements', $departements);
}
}
index.ctp
<?php print_r($departements); ?>
What does it give you?
I keep getting a "Call to a member function on a non-object" error in the index function of one of my controllers. Here is the code:
class ModulesController extends AppController {
public $uses = array('Module', 'User');
public $scaffold;
function index() {
if ($this->request->is('get')) { //Technically unecessary but good practice
$email = AuthComponent::user('email');
$user = $this->Module->User->findByEmail($email);
//Code omitted
}
}
And this is my Module model:
class Module extends AppModel {
public $name = 'Module';
public $hasMany = array(
'Slide' => array(
'className' => 'Slide',
'foreignKey' => 'module_id',
'order' => 'Slide.position ASC' //Let's make sure that name is correct
));
public $belongsTo = array(
'Creator' => array(
'className' => 'User'));
public $hasAndBelongsToMany = array(
'OUser' => array(
'className' => 'User',
'joinTable' => 'modules_users',
'foreignKey' => 'module_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
));
} //Unnecessary code omitted
And this is the code for my user model:
class User extends AppModel {
public $name = 'User';
public $uses = 'users';
public $hasMany = array(
'OModule' => array( //Owner of Modules
'className' => 'Module',
'foreignKey' => 'user_id',
'order' => 'Module.created DESC'
));
public $hasAndBelongsToMany = array(
'Module' => array(
'className' => 'Module',
'joinTable' => 'modules_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
));
} //Unnecessary code omitted
It is worth mentioning that User and Module have both a belongsTo and a HABTM relationship, so User has the aliases Creator and OUser respectively. In the code above, the findByEmail is trying to use the Creator relationship, but that gives me the same error.
My question is, how do I call the findByEmail() method without error?
Change:
$user = $this->Module->User->findByEmail($email);
To:
$user = $this->User->findByEmail($email);
Voila!
Reason:
Somehow, there is either 1) no relationship between Module and User, 2) a mistake in the relationship, or 3) your using an alias for either or both of them so that using Module->User wouldn't be correct.
You're loading the 'User' model anyway though, so there's no reason to go through the Module model to access it - just access it directly (like example above).
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';