I have two tables like this:
CREATE TABLE IF NOT EXISTS `publications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`numerated` tinyint(1) NOT NULL DEFAULT '0',
`title` text COLLATE utf8_unicode_ci,
`collection_id` int(11) NOT NULL,
`note` text CHARACTER SET utf8,
`adminNote` text CHARACTER SET utf8,
PRIMARY KEY (`id`),
KEY `collectionId` (`collection_id`)
KEY `numerated` (`numerated`),
) ;
CREATE TABLE IF NOT EXISTS `publication_numerations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication_id` int(11) NOT NULL,
`published` tinyint(1) NOT NULL DEFAULT '0',
`book` int(11) DEFAULT NULL,
`number` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `publication_id` (`publication_id`)
) ;
CREATE TABLE IF NOT EXISTS `properties` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication_id` int(11) NOT NULL,
`value` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `publication_id` (`publication_id`)
)
All I need is to have list of all records from table publications and publication_numerations. Tryed with cake bake model/controller/view, but all the time it joins
publications and properties, without publication_numerations.
Can you help me to solve this?
Thank you very much in advance!
UPDATED: so, all I need is to create and use it as default query:
SELECT * FROM `publications`
LEFT JOIN `publication_numerations` ON (`publications`.`id` = publication_numerations.`publication_id`)
UPDATED: here are my models
publications model
var $hasOne = array(
'Publisher' => array(
'className' => 'Publisher',
'foreignKey' => 'publication_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
var $belongsTo = array(
'Collection' => array(
'className' => 'Collection',
'foreignKey' => 'collection_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'PublicationProperty' => array(
'className' => 'PublicationProperty',
'foreignKey' => 'publication_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'PublicationNumeration' => array(
'className' => 'PublicationNumeration',
'foreignKey' => 'publication_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
?>
PublicationNumeration model
var $belongsTo = array(
'Publication' => array(
'className' => 'Publication',
'foreignKey' => 'publication_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'Publication' => array(
'className' => 'Publication',
'foreignKey' => 'publication_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
?>
Collection modes
var $hasMany = array(
'Property' => array(
'className' => 'Property',
'foreignKey' => 'collection_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Publication' => array(
'className' => 'Publication',
'foreignKey' => 'collection_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
?>
You can do joins in cake like so:
$joins = array(
array('table' => 'publication_numerations',
'alias' => 'PublicationNumeration',
'type' => 'LEFT',
'conditions' => array(
'Publication.id = PublicationNumeration.publication_id',
)
)
);
$this->Publication->find('all', array('joins' => $joins));
Tryed with cake bake
model/controller/view, but all the
time it joins publications and
properties, without
publication_numerations.
So, create associations manually - Associations: Linking Models Together. It does not seems that you need 'joins'. By setting associations correctly you will be able to get the list you need by using find('list') in your controller - http://book.cakephp.org/view/1017/Retrieving-Your-Data#find-list-1022.
Try making the type attribute of $join array 'LEFT OUTER' instead of 'LEFT'.
Related
I'm cloning a milestone record with associated data. I first find the data from the source milestone, then change the contents of the array and remove all 'id' fields. Then I attempt a 'saveAll'. All the associated data is being created properly but the 'milestones' table now has 2 new records instead of 1. The second record contains the ID used by the associated data, so why does the first record even exist?
The Data (simplified) and Call:
$test = array(
'Milestone' => array(
'name' => 'Clone Test',
'customer_status' => '',
'time_to_complete' => '1',
'is_active' => true,
),
'MilestoneAlert' => array(
(int) 0 => array(
'name' => 'Clone Test',
'type' => 'customer',
'milestone_alert_type_id' => '0',
'email' => null,
'subject' => 'First alert!',
'message' => 'Add a message',
'recipient_name' => '',
'is_active' => true,
),
(int) 1 => array(
'name' => 'Clone Test 1',
'type' => 'customer',
'milestone_alert_type_id' => '0',
'email' => null,
'subject' => 'Second alert!',
'message' => 'Add a message',
'recipient_name' => '',
'is_active' => true,
)
),
'MilestoneCondition' => array(
(int) 0 => array(
'name' => 'Clone Test',
'condition' => 'First condition.',
'is_active' => true,
),
(int) 1 => array(
'name' => 'Clone Test 1',
'condition' => 'Second condition.',
'is_active' => true,
)
)
);
$this->loadModel('Milestone');
$this->Milestone->create();
$this->Milestone->saveAll($test);
In Model/Milestone.php:
public $hasMany = array(
'MilestoneAlert' => array(
'className' => 'MilestoneAlert',
'foreignKey' => 'milestone_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'MilestoneCondition' => array(
'className' => 'MilestoneCondition',
'foreignKey' => 'milestone_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => 'MilestoneCondition.order',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
In Model/MilestoneAlert.php:
public $belongsTo = array(
'Milestone' => array(
'className' => 'Milestone',
'foreignKey' => 'milestone_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
In Model/MilestoneCondition.php:
public $belongsTo = array(
'Milestone' => array(
'className' => 'Milestone',
'foreignKey' => 'milestone_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
After running the method, there are two records in 'milestone_conditions', two records in 'milestone_alerts', and two identical records in 'milestones'. How do I keep it from creating two 'milestone' records?
Try to get the original data like this:
$test= $this->Milestone->findById('insert your id');
$this->Milestone->create(); // Create a new record
$this->Milestone->saveAll($test,array('deep' => true)); // And save it
I'm in trouble with a more complex situation of HABTM in Cakephp. Ina nutshel, the situation is: a have users and movies, the relationship between then is HABTM, but i also need a relationship types.
USERS - HABTM - MOVIES
|
RELATION_TYPES
The relationship between users and movies could be many different types: author type, public type, etc.
When i try to use the contain behavior, i get an error message that says:
Model "MoviesUser" is not associated with model "RelationType".
But all the models are associated.
These are the models:
User Model
public $hasAndBelongsToMany = array(
'Movie' => array(
'className' => 'Movie',
'joinTable' => 'movies_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'movie_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => 'Movie.title',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
Movie Model
public $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'movies_users',
'foreignKey' => 'movie_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
MoviesUser Model
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Movie' => array(
'className' => 'Movie',
'foreignKey' => 'movie_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'RelationType' => array(
'className' => 'RelationType',
'foreignKey' => 'relation_type_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
In the MoviesController, i'm trying to get some movies and the relation with users and the type of the relation. Here is where i call the Contain on Movies Controller:
$this->Movie->contain(array(
'Person' => array(
'order' => array(
'Person.name'=>'ASC'
),
'Activity'
),
'Country' => array(
'order'=>array(
'Country.name'=>'ASC'
)
),
'User'=>array(
'conditions'=>array(
'User.id'=>$this->Session->read('Auth.User.id')
),
'MoviesUser'=>array(
'RelationType'
)
)
));
When i try to run this i get the message Model "MoviesUser" is not associated with the model "RelationType".
The fields of movies_user are:
id, user_id, relation_type_id, rate, comment
The fields of relation_types are:
id, title
And here my $has_many property on RelationType Model:
public $hasMany = array(
'MoviesUser' => array(
'className' => 'MoviesUser',
'foreignKey' => 'relation_type_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
Suppose I have a table/model Products.
Suppose I have a table/model Equivalencies which has among its columns this 2:
original_id
equivalent_id
Both original_id and equivalent_id have as foreign keys the primary key of Products. So, I can't follow the convention of naming original_id as product_id, because I also have to deal with equivalent_id (which would also be product_id).
What should I do?
Currently, I have the Product model configured as this:
public $hasMany = array(
'Original' => array(
'className' => 'Equivalency',
'foreignKey' => 'original_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => '',
'table' => 'products',
),
'Equivalent' => array(
'className' => 'Equivalency',
'foreignKey' => 'equivalent_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
);
Could anyone tell me if this is how it's supposed to be done?
What I Want
I want to be able to find all the equivalencies of a given product, but with conditions over the relation (the one with original_id, equivalent_id).
This doesn't work:
$original = $this->Product->find('all',
array(
'contain' => 'Product.Original.deleted_equivalent = false',
'conditions' => array('Product.id' => $id)
));
Your model is fine, that's the way you should do it.
Your call to find is not.
Try this
$original = $this->Product->find('all',
array(
'contain' => array('Equivalent'),
'conditions' => array('Product.id' => $id)
));
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' => ''
),
);
<?php
class Product extends AppModel {
var $name = 'Product';
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Category' => array(
'className' => 'Category',
'foreignKey' => 'category_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Brand'
);
var $hasOne = array(
'PhotoSmall' => array(
'className' => 'Photo',
'foreignKey' => 'product_id',
'dependent' => true,
'conditions' => 'PhotoSmall.tipo = "small"',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
);
var $hasMany = array(
'PhotoBig' => array(
'className' => 'Photo',
'foreignKey' => 'product_id',
'dependent' => true,
'conditions' => 'PhotoBig.tipo = "big"',
'fields' => '',
'order' => 'PhotoBig.order',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Rating' => array(
'className' => 'Rating',
'foreignKey' => 'product_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
I need all my finds (except in the admin area) to retrieve only products with images.
In the case of PhotoSmall is easy, I can do PhotoSmall.id IS NOT NULL in a condition because CakePhp generates a left join, but i can not find a way to require a least on PhotoBig because CakePhp does two queries to return its results.
The requirement is the following, I can only show products with a PhotoSmall and a least one PhotoBig system wide (except for the admin section of the site), the solution should work with CakePhp pagination
I've tried the following code without success, it only returns product data, not photo data:
$this->Product->recursive = -1;
$conditions = array('Product.category_id'=> $cats);
$joins = array(
array('table' => 'photos',
'alias' => 'PhotoBig',
'type' => 'INNER',
'conditions' => array(
'Product.id = PhotoBig.product_id',
)
),
array('table' => 'photos',
'alias' => 'PhotoSmall',
'type' => 'INNER',
'conditions' => array(
'Product.id = PhotoBig.product_id',
)
)
);
$this->paginate = array(
'limit' => 12,
'conditions' => $conditions,
'joins' => $joins,
);
you need to additionally use contain - at least that worked for me
(due to your recursive=-1):
'contain' => array('PhotoSmall', 'PhotoBig'),
the joins are only the setup configuration. without specifying your data you will only get the one model's data.
do you use the containable behavior? would be the easiest solution.
if not, try to set recursive to 0 or 1.
PS: and your second alias is wrong inside the 'conditions' (should be PhotoSmall there).
Well firstly you're setting recursive to -1 which should just give you Product data no matter what kind of find you do.
Why don't you do an AND condition in a find on the Product model like so:
$this->Product->find('all', array('recursive' => 1, 'conditions' => array(
"NOT" => array('PhotoSmall.id' => NULL, 'PhotoBig.id' => NULL))));
Note: recursive will need to be at least one because you want related data.