I have 2 models Profiles and Messages. When i try to get all messages in its controller, cake doesn`t return any profiles in result array.
In Message controller:
$this->Message->recursive=3;
$m=$this->Message->find('all');
Models:
class Message extends AppModel {
var $name = 'Message';
var $primaryKey = 'id';
var $useTable = 'messages';
var $belongsTo = array(
'Profile' => array(
'className' => 'Profile',
'foreignKey' => 'author_id',
'conditions' => '',
'fields' => '',
'order' => ''
));
And
class Profile extends AppModel {
var $name = 'Profile';
var $primaryKey = 'id';
var $useTable = 'profiles';
var $belongsTo = array(
'Account' => array(
'className' => 'Account',
'foreignKey' => 'account_id',
'conditions' => '',
'fields' => '',
'order' => ''
));
var $hasMany = array(
'Message' => array(
'className' => 'Message',
'foreignKey' => 'Author_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
));
P.S. I cant wait 7 hours for answer option.
I found solution eventually, my Message model filename was messageS.php, as soon as i renamed it to message.php, got everything i needed. I it helps someone
Per your answer, (but also relevant to other people), if you're pretty sure your associations are correct, the next step is to check your filenames to make sure they fit the conventions (singular model).
Another note, if you're using recursive 3, (wasn't aware it went higher than 2, but apparently it does), you're probably better off using CakePHP's Containable Behavior. Even using recursive of 2 is usually excessive.
write in Message.php model file:
var $belongsTo = array(
'Profile' => array(
'className' => 'Profile',
'foreignKey' => 'author_id',
'conditions' => '',
'fields' => '',
'order' => ''
));
write in Profile.php model file:
var $hasMany = array(
'Message' => array(
'className' => 'Message',
'foreignKey' => 'Author_id', // Hear you "Author_id" should change as "author_id"
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
));
Controller:
$m=$this->Message->find('all');
Now its working fine...Enjoy..
Related
can someone provide an explanation for me?
I've got a database where I'm trying to update 4 tables from one page, Organizations, OrganizationsDetails, Account, AccountRoles. The add view itself would contain fields for the Account and the Organization. When I call the OrganizationsController add function, I want to then call add on AccountController, AccountRolesController (set Account as an administrator role), and OrganizationDetailsController (set that Account as the administrator for that specific Organization).
Should I be using components for this? When I call add() on the Organizations, I always intend to perform these steps - never solely create the Organizations entry below. Should I be doing this directly in that function or some other method?
Let me know if I need to explain more, thanks!
EDIT: Added the four models below:
Organization
class Organization extends AppModel {
public $hasMany = array(
'Account' => array(
'className' => 'Account',
'foreignKey' => 'organization_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
public $hasOne = array(
'OrganizationDetail' => array(
'className' => 'OrganizationDetail',
'foreignKey' => 'organization_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
OrganizationDetail
class OrganizationDetail extends AppModel {
public $belongsTo = array(
'Organization' => array(
'className' => 'Organization',
'foreignKey' => 'organization_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Account' => array(
'className' => 'Account',
'foreignKey' => 'account_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
AccountRole
class AccountRole extends AppModel {
public $belongsTo = array(
'Account' => array(
'className' => 'Account',
'foreignKey' => 'account_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Role' => array(
'className' => 'Role',
'foreignKey' => 'role_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
Account
class Account extends AppModel {
public $belongsTo = array(
'Organization' => array(
'className' => 'Organization',
'foreignKey' => 'organization_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
public $hasOne = array(
'OrganizationDetail' => array(
'className' => 'OrganizationDetail',
'foreignKey' => 'account_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
public $hasMany = array(
'AccountRole' => array(
'className' => 'AccountRole',
'foreignKey' => 'account_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
You've got wrong the whole MVC idea. Controllers should not call methods in other controllers (or at least not in this scenario).
The right approach would be to set up OrganizationsController->add() so that it saves all the data by independent calls to each Model->save($data), or by using
Organization->saveAssociated($data,array('deep' => true))
Your form fields need to be named properly for this to work. For example:
echo $this->Form->create('Organization', array('action' => 'add'));
echo $this->Form->input('Organization.name'));
echo $this->Form->input('Account.0.name', array('label' => 'Account name'));
echo $this->Form->input('OrganizationDetail.details', array('label' => 'Org. Details'));
echo $this->Form->input('Account.0.AccountRole.id', array('label' => 'Account Role'));
echo $this->Form->end('Add');
However, you may get into trouble if you try to go too many levels deep. If you find yourself in this situation, it's probably because you data model is flawed.
This is what your data model currently looks like:
This is what I believe it should look like:
It is critical to have your data model right before you start coding. It can save you many headaches!
I have two Model. One is user and onother is UserProfile and in created their tables users and user_profiles respectivly. I want when i delete user data thenrelated UserProfile should also automatically deleted. I created hasone and belongs to relation. One more thing i am deleting data using checkbox with delete button so i could able to delete multiple record at once.
User.php
public $hasOne = array(
'UserProfile' => array(
'className' => 'UserProfile',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
);
UserProfile.php
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
In UsersController i have a deleteSelected function
UsersController.php
public function deleteSelected()
{
foreach($this->data['User'] as $key => $value)
{
if($value != 0)
{
$this->User->delete($value);
}
}
$this->redirect($this->referer());
}
finaaly i am getting an Error: Table groups_users for model GroupsUser was not found in datasource default. Please tell whats wrong in my code. Thanks.
set dependent to true
public $hasOne = array(
'UserProfile' => array(
'className' => 'UserProfile',
'foreignKey' => 'user_id',
'dependent' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
);
i recently upgraded my 1.3-app to 2.4 with https://github.com/dereuromark/upgrade
But now some usages of $this->Model->find() doesn't work. Especially the joins to the associated models/tables.Resulting in "Unknown column 'Bill.customer_id' in where clause".
My setup:
Tables and Associations: http://i.stack.imgur.com/bjOIz.png (Image)
Models:
App::uses('AppModel', 'Model');
class Customer extends AppModel {
public $actsAs = array('Logable', 'Containable');
public $hasMany = array(
'Bill' => array(
'className' => 'Bill',
'foreignKey' => 'customer_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)...
-----------------------------------------------------------------
App::uses('AppModel', 'Model');
class Bill extends AppModel {
public $actsAs = array('Containable', 'Logable', 'Lockable');
public $belongsTo = array(
'Customer' => array(
'className' => 'Customer',
'foreignKey' => 'customer_id',
'conditions' => '',
'fields' => '',
'order' => ''
)...
public $hasAndBelongsToMany = array(
'Stage' => array(
'className' => 'Stage',
'joinTable' => 'bills_stages',
'foreignKey' => 'bill_id',
'associationForeignKey' => 'stage_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)...
--------------------------------------------------------------
App::uses('AppModel', 'Model');
class BillsStage extends AppModel {
public $actsAs = array('Containable', 'Logable', 'Lockable');
public $belongsTo = array(
'Bill' => array(
'className' => 'Bill',
'foreignKey' => 'bill_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Stage' => array(
'className' => 'Stage',
'foreignKey' => 'stage_id',
'conditions' => '',
'fields' => '',
'order' => ''
)...
--------------------------------------------------------
App::uses('AppModel', 'Model');
class Stage extends AppModel {
public $displayField = 'name';
public $actsAs = array('Tree', 'Containable', 'Logable');
public $hasMany = array(
'Bill' => array(
'className' => 'Bill',
'foreignKey' => 'stage_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)...
public $hasAndBelongsToMany = array(
'Bill' => array(
'className' => 'Bill',
'joinTable' => 'bills_stages',
'foreignKey' => 'stage_id',
'associationForeignKey' => 'bill_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)...
In 1.3 the joins are working. In 2.4 only 1-dimensional sql query.
Any idea?
--edit--
$billsStages = $this->Customer->Bill->BillsStage->find('all', array(
'conditions' => array(
'Bill.customer_id' => $this->Customer->id,
'Stage.id' => array_keys($vk_stages)
),
'order' => 'BillsStage.created DESC'
));
Try a join (example taken out from the docs)
$options['joins'] = array(
array('table' => 'bills',
'alias' => 'Bill',
'type' => 'LEFT',
'conditions' => array(
'Bill.customer_id' => $this->Customer->id,
)
),
array('table' => 'stages',
'alias' => 'Stage',
'type' => 'LEFT',
'conditions' => array(
'Stage.id' => array_keys($vk_stages)
)
)
);
$options['conditions'] = array();
$items= $this->Customer->Bill->BillsStage->find('all', $options);
(adjust to your case).
According to this answer, a contain for conditions on the secondary model is not possible, since contain makes a different query. So use joins if you want to apply conditions on secondary models, or create a simple function in your model that does two separate queries and creates a macro array that returns the mixed results if you want to use contain.
Can anyone suggest me why when there are no translation for a field it is returned empty, and not with the default translation?
I will appreciate all suggestions...
Can`t tell what part of my code you want to see, because it is all straight forward from www.book.cake.org. So i pasting some code:
Model definition:
<?php
class Article extends AppModel
{
var $useTable = 'nc_articles';
var $name = 'Article';
var $actsAs = array(
'Translate' => array(
'title', 'content', 'meta_key_words','meta_description'
)
);
// Use a different model
var $translateModel = 'ArticlesI18n';
// Use a different table for translateModel
var $translateTable = 'nc_articles_i18ns';
var $belongsTo = array(
'Author' => array('className' => 'User',
'foreignKey' => 'author_id',
'conditions' => '',
'fields' => array(),
'order' => '',
'counterCache' => ''),
'Modifier' => array('className' => 'User',
'foreignKey' => 'modifier_id',
'conditions' => '',
'fields' => array(),
'order' => '',
'counterCache' => ''),
'Category' => array('className' => 'ArticlesCategory',
'foreignKey' => 'category_id',
'conditions' => '',
'fields' => array(),
'order' => '',
'counterCache' => ''),
'Layout' => array('className' => 'Layout',
'foreignKey' => 'layout_id',
'conditions' => '',
'fields' => array(),
'order' => '',
'counterCache' => ''),
);
var $hasMany = array(
'Comments' => array(
'className' => 'ArticlesComment',
'foreignKey' => 'article_id',
'conditions' => array(),
'order' => '',
'limit' => '',
//'dependent'=> true When dependent is set to true, recursive model deletion is possible. In this example, Comment records will be deleted when their associated User record has been deleted.
)
);
}
?>
And then the function where I am changing Language:
function setLanguage($languageCode='pol')
{
$this->Session->write('Config.language', $languageCode);
$this->redirect($this->referer());
}
Would you like to see something more?
Let me answer my own question. There were few more things I had to write more. First of all I had to declare my Config.language in core.php then for Every model which is translated I had to declare a local variable which is an array of language codes
$this->Article->array('en','pol');
And that's how I managed the problem. But now queries for translation are very long and I am facing an optimization problem.
Another noob question - using v1.2.1.8004 of CakePHP, I think...
I have 3 tables, broker (B), quote_site (QS) and broker_quote_site (BQS) that links them together.
B has many BQS (it belongs to B)
QS has many BQS (it belongs to QS)
I am trying to retrieve quote sites, that are linked to a specific broker, but CakePHP is not doing the joins to the tables behind the scenes.
Here is my query:
$quote_sites = $this->QuoteSite->find('all', array(
'conditions' => array(
'Broker.company_id' => $company_id,
'BrokerQuoteSite.is_active' => true
),
'contain' => array(
'BrokerQuoteSite' => array(
'Broker'
)
)
));
Here are the related models:
<?php
class QuoteSite extends AppModel
{
var $name = 'QuoteSite';
//$validate set in __construct for multi-language support
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasMany = array(
'BrokerQuoteSite' => array(
'className' => 'BrokerQuoteSite',
'foreignKey' => 'quote_site_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
?>
Broker:
<?php
class Broker extends AppModel
{
var $name = 'Broker';
//$validate set in __construct for multi-language support
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasMany = array(
'BrokerQuoteSite' => array(
'className' => 'BrokerQuoteSite',
'foreignKey' => 'broker_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
?>
And the last one:
<?php
class BrokerQuoteSite extends AppModel
{
var $name = 'BrokerQuoteSite';
//$validate set in __construct for multi-language support
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Broker' => array(
'className' => 'Broker',
'foreignKey' => 'broker_id',
'conditions' => '',
'fields' => '',
'order' => '',
) ,
'QuoteSite' => array(
'className' => 'QuoteSite',
'foreignKey' => 'quote_site_id',
'conditions' => '',
'fields' => '',
'order' => '',
)
);
}
?>
Thanks in advance for any tips/tricks.
Chris why don't you define Broker as a HABTM relationship then a simple find will retrive the desired results?
class Broker extends AppModel {
var $name = 'Broker';
var $hasAndBelongsToMany = array(
'QuoteSite' =>
array(
'className' => 'QuoteSite',
'joinTable' => 'broker_quote_sites',
'foreignKey' => 'broker_id',
'associationForeignKey' => 'quote_site_id'
)
);
}
http://book.cakephp.org/view/1044/hasAndBelongsToMany-HABTM
Nice question and what I thought is to make it two steps
$this->Broke = ClassRegistry::init("Broke");
$brokeids = $this->Broke->find("list",array("conditions"=>array('Broker.company_id' => $company_id))); //get all B ids
$this->QuoteSite->Behaviors->attach('Containable'); //use containable behavior
$quote_sites = $this->QuoteSite->find('all',array(
'contain'=>array(
'BrokerQuoteSite'=>array(
'conditions'=>array(
"BrokerQuoteSite.broke_id"=>$brokeids,
"BrokerQuoteSite.is_active" => true
)
)
)
)
);
The code is NOT tested yet,maybe some syntax mistakes out there.Hope it helps.
update
$this->Broke = ClassRegistry::init("Broke");
$this->Broke->recursive=2;
$brokes = $this->Broke->find("all",array("conditions"=>array("Broke.company_id"=>$comany_id)));
the QS information you need shall be found if you view the result with debug($brokes); .What you need to do is extracting them from the array.
Cheers.