I’m using cakephp 1.3 with mysql database and engine is MYISAM, I’m getting problem in relationships. I have two tables name Organization and OrgClasses, these two are associated with mbo_studio_id which is common in both table.
organization
Id(PK), name, mbo_studio_id
org_classes
id(PK), name,date, mbo_studio_id
I’m trying to fetch data on the condition of mbo_studio_id, but it adds another condition by primary key of OrgClasses.
var $belongsTo = array(
'OrgClass' => array(
'className' => 'OrgClass',
'foreignKey' => 'mbo_studio_id',
'conditions' => array('OrgClass.mbo_studio_id' => 'Organization.mbo_studio_id'),
'order' => 'OrgClass.date DESC',
'dependent' => false,
)
);
I get following query
SELECT `Organization`.`id`, `Organization`.`name, `Organization`.`mbo_studio_id`, `OrgClass`.` id`,`OrgClass`.`mbo_studio_id`, `OrgClass`.`name`, `OrgClass`.`date`
FROM `organizations` AS `Organization`
LEFT JOIN `org_classes` AS `OrgClass` ON (`Organization`.`mbo_studio_id` = `OrgClass`.`id` AND `OrgClass`.`mbo_studio_id` = Organization.mbo_studio_id)
Here I don’t want Organization.mbo_studio_id = OrgClass.id condition in query.
Thanks
Then you need to set foreignKey to false:
'foreignKey' => false,
This way it will only use your custom conditions.
Related
I have the following problem with CakePHP:
Two tables are joined (filters and accounts). Then I am building conditions and only the second condition Account.active =>1 gets executed. If I print the result, there are still showing filters that are having another mode_id than 3.
$joins= array(
array('table' => 'filters',
'alias' => 'Filter',
'type' => 'right',
'conditions' => array(
'Filter.account_id = Account.id',
)
),
);
Then I execute the request including joins and conditions
$activeAccounts = $this->Account->find('all',array(
'conditions'=>array('AND'=>array('Filter.mode_id'=>3,'Account.active'=>1)),
'joins'=>$joins));
The models were checked and no problems identified. Filter belongs to Account. Account has many Filter.
Below the query that is generated. The results are still showing filters with Filter.mode_id other than 3
Here is the query that is generated. The results are still containing rows with Filter.mode_id other than 3 despite the fact that one condition is 'Filter.mode_id'=>3
SELECT `Account`.`id`, `Account`.`user_id`, `Account`.`name`,
`Account`.`api_key`, `Account`.`account_number`, `Account`.`remaining_balance`,
`Account`.`investment_size`, `Account`.`active`
FROM `baseline_db`.`accounts` AS `Account`
right JOIN `baseline_db`.`filters` AS `Filter`
ON (`Filter`.`account_id` = `Account`.`id`)
WHERE ((`Filter`.`mode_id` = 3) AND
(`Account`.`active` = '1'))
Like say Oldskool, use the Model associations
and for your condition, The "AND" is not necessary,
you cant put :
$activeAccounts = $this->Account->find('all',array(
'conditions' => array(
'Filter.mode_id'=>3,
'Account.active'=>1
)
));
the request you want to make with the type of relation you have, seem to me weird.
If i understand, perhaps with something like that :
$this->loadModel('Filter');
$filters =$this->Filter->find("list", array(
'conditions' => array('Filter.mode_id' => 3),
'fields' => array('Filter.account_id')
));
$activeAccounts = $this->Account->find('all',array(
'conditions' => array(
'Account.account_id'=>$filters,
'Account.active'=>1
)
));
I have two tables: users and posts. I'm trying to select any users that have at least one post.
I'm guessing this require either a join or a subselect. Is there something in CakePHP that makes this simple?
Use counter caching, see http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#belongsto
counterCache: If set to true the associated Model will automatically
increase or decrease the “[singular_model_name]_count” field in the
foreign table whenever you do a save() or delete(). If it’s a string
then it’s the field name to use. The value in the counter field
represents the number of related rows. You can also specify multiple
counter caches by using an array where the key is field name and value
is the conditions. E.g.:
array(
'recipes_count' => true,
'recipes_published' => array('Recipe.published' => 1) ) counterScope: Optional conditions array to use for updating counter
cache field.
No additional query needed in this case. It will automatically in- and decrease the count in the users table if you add/delete posts.
Example:
public $belongsTo = array(
'User' => array(
'foreignKey' => 'user_id',
'counterCache' => true,
'counterScope' => array(
'published' => 1)));
This should select all users that made 1 post or more
SELECT * FROM `users` as u
INNER JOIN `posts` as p ON p.user_id = u.id
In cake you should be able to do something like this:
$this->User->find('all', array('joins' =>
array(
'table' => 'posts',
'alias' => 'p',
'type' => 'inner',
'conditions' => array(
'User.id = p.user_id'
)
)
);
[EDIT]
Maybe you could add
'group' => 'User.id'
or
'fields' => 'DISTINCT User.id, ...'
To remove duplicates entries
I want to create in cake php application with users, games and games platforms (for ex PS3)
I got tables:
userGames (game have one platform)
id, name, platform_id
users (users can have many platforms)
id, username
platforms
id, name
users_platforms
id, platform_id, user_id
And now i want to select all user id=1 platforms, and list it for select tag.
Here is sql query:
SELECT platforms.name, platforms.id FROM platforms LEFT JOIN platforms_users ON platforms_users.platform_id=platforms.id WHERE platforms_users.user_id=1
But i dont know what to list this by find('list') function in cakePHP
I try type in users controller:
$this->User->Platform->find('list', array('conditions', array('User.id'=>'1')));
But this returns sql problem (undefinded User.id)
Anyone can help me?
please try this
$this->loadModel('UserPlatform');
$this->UserPlatform->bindModel(array(
'belongsTo' => array('Platform')
));
$this->UserPlatform->find('list', array(
'fields' => array('Platform.id','Platform.name'),
'conditions' => array('UserPlatform.user_id'=>'1'),
'recursive' => 1
));
you must apply find function on join table
Your find must same as this:
$this->PlatformUser->find('list',array('fields'=>
array('Platform.name','Platform.id'),'conditions'=> array('PlatformUser.id' => 1)));
Your PlatformUser Model must have:
public $belongsTo = array(
'Platform' => array(
'className' => 'Platform',
'foreignKey' => 'platform_id',
),
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
),
);
What you are trying to do is actually a HasAndBelongsToMany Association.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
hasAndBelongsToMany (HABTM)
We’ll need to set up an extra table in the database to handle HABTM associations. This new join table’s name needs to include the names of both models involved, in alphabetical order, and separated with an underscore ( _ ). The contents of the table should be two fields that are foreign keys (which should be integers) pointing to the primary keys of the involved models. To avoid any issues, don’t define a combined primary key for these two fields. If your application requires a unique index, you can define one. If you plan to add any extra information to this table, or use a ‘with’ model, you should add an additional primary key field (by convention ‘id’).
HABTM requires a separate join table that includes both model names.
(This would be the UserPlatform-table if I got that right.)
Make sure primary keys in tables cakes and recipes have “id” fields as assumed by convention. If they’re different than assumed, they must be changed in model’s primaryKey.
class Recipe extends AppModel {
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => ''
)
);
}
There are 2 Models: Project & Category that are bind with HABTM relationship.
I would like to perform a search from projects controller that can do the following:
FIND all DISTINCT Project.scedule WHERE Category.slug != 'uncategorised'
Apologies for the syntax, I'm no sequel expert.
What I have managed to do is to retrieve all projects that do not belong to Category uncategorised into an array however I'm not sure as to how to search again the array result for DISTINCT Project.schedule values (needed to fill out a form drop down)
Before answer this question,again I suggest you to read the HABTM in cookbook of CAKEPHP carefully,then you can finish jobs like this yourself.
$this->Project->bindModel(array(
'hasOne' => array(
'CategorysProject',
'FilterCategory' => array(
'className' => 'Category',
'foreignKey' => false,
'conditions' => array('FilterCategory.id = CategorysProject.category_id')
))));
$this->Project->find('all', array(
'fields' => array(DISTINCT (Project.scedule)),
'conditions'=>array('FilterCategory.slug !='=>'uncategorised')
));
Just a few days ago I found out about this miracle called CakePHP so I am pretty green to it.
I need to build a mail application, so I have followed the convention and created:
Database description:
Table of users <user_id (primary key), fname, lname>.
Table of mails <mail_id(primary key), from (foreign key to user_id), to (foreign key to user_id), content, opened>.
My questions:
1) According to the convention, a foreign key should be called related table+'_id'. How should I call the columns if there are two foreign keys that relate to the same table. Like from and to in the mails table.
2) I would like to do an inner JOIN the between the two tables.
Something like:
SELECT user_id, mail_id
FROM users
INNER JOIN mails
ON users.user_id =mails.to AND mails.opened=false.
But I have no clue how to do it.
When you need to do two relations to the same table, you will need to override the default convention. In your example, I would make 2 foreign keys. One named sender_id and one named recipient_id. Then you would join them in the Model like so:
<?php
class Mail extends AppModel {
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'UserSender' => array(
'className' => 'User',
'foreignKey' => 'sender_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'UserRecipient' => array(
'className' => 'User',
'foreignKey' => 'recipient_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
}
?>
Then to do your conditions, you would reference them like so:
<?php
$this->Mail->find(array('conditions'=>array('Mail.opened'=>false)));
?>
...and to filter on the sender and receiver, your conditions would look like:
<?php
$this->Mail->find(array('conditions'=>array('UserSender.some_field'=>$someValue,
'UserRecipient.some_field'=>$someValue)));
?>
I'm not an expert myself, but following info on the CakePHP site will help you further:
Multiple-relations-to-the-same-model