Hi Im just wondering if it is possible to save multiple data that has hasMany: and if it is possible what is the array structure before executing $this->Model->saveAll($this->data).
example is that you are going to save multiple posts at a time like this:
array(
[Post] => Array
(
[0] => Array
(
[title] => title One
[content] => desc One
)
[1] => Array
(
[title] => title two
[content] => desc two
)
)
So in the given array above we can save all the Post with saveAll but what if each Post have hasMany comment each. how the array should look like if i have to insert the array below:
array(
[Comment] => Array
(
[0] => Array
(
[comment] => 1st Comment for Post One
)
[1] => Array
(
[comment] => 2nd Comment for Post One
)
[2] => Array
(
[comment] => 1st Comment for Post Two
)
[3] => Array
(
[comment] => 2nd Comment for Post Two
)
)
How can I combine the two array to execute saveAll();
Thanks in advance. ^_^
Assuming the association for "post has many comments" is called "Comments", the data would look something like
array(
'Post' => array(
array(
'title' => 'title1',
'content' => 'content1',
'Comments' => array(
array('comment'=>'1st comment for post 1'),
array('comment'=>'2nd comment for post 1'),
),
array(
'title' => 'title2',
'content' => 'content2',
'Comments' => array(
array('comment'=>'1st comment for post 2'),
array('comment'=>'2nd comment for post 2'),
),
),
),
)
To save you could use something like:
$this->Model->saveMany($data, array('deep'=>TRUE));
Note that the "deep" option requires CakePHP 2.1. Without it the associated Comment records would not be saved.
All this is documented in http://book.cakephp.org/2.0/en/models/saving-your-data.html
Related
I am trying to save multiple data at once, but cannot save data.
I have model of Post and model of Comment.
Post has many comments.
$this->WhAreaAllocation->saveAll($tempArray, array('deep' => true));
$tempArray is as below :
array(
'post' => array(
(int) 0 => array(
'title' => 'title1',
'content' => 'content1',
'comment' => array(
(int) 0 => array(
'comment'=>'1st comment for post 1'
),
(int) 1 => array(
'comment'=>'2nd comment for post 1'
)
)
),
(int) 1 => array(
'title' => 'title2',
'content' => 'content2',
'comment' => array(
(int) 0 => array(
'comment'=>'1st comment for post 2'
),
(int) 1 => array(
'comment'=>'2nd comment for post 2'
)
)
)
)
)
Saving hasMany through data
I don't know that you are saving post comments using form and also i am not sure about that which version of cakephp you are using but my solution is for cakephp2.x .If you wanna save data using form then create your post form like this and for saving has many mentioned related model name in fields.For example here you want save related comment of post see the code below
<?php echo $this->Form->create('Post'); ?>
<?php echo $this->Form->input('Post.title'); ?>
<?php echo $this->Form->input('Post.content'); ?>
<?php echo $this->Form->input('Comment.comment'); ?>
<button type="submit">Save</button>
<?php echo $this->Form->end(); ?>
Using this form u will get the request data like this.
Array
(
[0] => Array
(
[Post] => Array
(
[title] => It is a post title
[content] => you post content
)
[Comment] => Array
(
[comment] => this is my post comment
)
)
)
or if you wanna save data with out using form then u have to create data like this and also see CakePhp Save hasmany
Array
(
[0] => Array
(
[Post] => Array
(
[title] => It is a post title
[content] => you post content
)
[0] => Array
(
[Comment] => Array
(
[comment] => this is my post comment1
)
)
[1] => Array
(
[Comment] => Array
(
[comment] => this is my post comment2
)
)
)
)
I have two tables posts and users. The post.user_id=users.id.
The fields are
user: id, username, password
post: id, user_id, post_name
I would like to select post.id, post.post_name, user.username.
How to select this in CakePHP?
I have two Models named User and Post. It calls the Model from PostController.
If you have correctly defined the relationship between those two models, this should just happen when you use the Post model's find method:
// In PostsController
$posts = $this->Post->find('all');
// $posts should be an array like this
Array
(
[0] => Array
(
[Post] => Array
(
// Model data
)
[User] => Array
(
// Model data
)
)
)
Hope this helps.
You should properly define the relations between the two models in order to simplify your life, but if you want to use a join, here is the syntax:
find('all', array(
'conditions' => array('name' => 'Thomas Anderson'),
'joins' => array(
array(
'alias' => 'Thought',
'table' => 'thoughts',
'type' => 'LEFT',
'conditions' => '`Thought`.`person_id` = `Person`.`id`'
)
)
));
From the CakePHP manual:
Let's say you had a belongsTo relationship between Posts and Authors. Let's say you wanted to find all the posts that contained a certain keyword ("magic") or were created in the past two weeks, but you want to restrict your search to posts written by Bob:
array (
"Author.name" => "Bob",
"OR" => array (
"Post.title LIKE" => "%magic%",
"Post.created >" => date('Y-m-d', strtotime("-2 weeks"))
)
)
However, its not working for me. I've got Scrapes belongsTo Vargroup, and Vargroup hasMany Scrape. My scrapes table has a field vargroup_id
When I do:
$this->Vargroup->contain('Scrape');
$this->Vargroup->find('first');
I get:
Array
(
[Vargroup] => Array
(
[id] => 16950
[item_id] => 1056
[image] => cn4535d266.jpg
[price] => 22.95
[instock] => 1
[timestamp] => 2012-10-29 11:35:10
)
[Scrape] => Array
(
[0] => Array
(
[id] => 18163
[item_id] => 1056
[vargroup_id] => 16950
[timestamp] => 2012-05-23 15:24:31
[instock] => 1
[price] => 22.95
)
)
)
But when I do :
$this->Vargroup->contain('Scrape');
$this->Vargroup->find('first', array(
'conditions' => array(
'not' => array(
array('Scrape.timestamp >' => $today)
)
)
));
Im getting The following error with associated sql output
Warning (512): SQL Error: 1054: Unknown column 'Scrape.timestamp' in 'where clause'
Query: SELECT `Vargroup`.`id`, `Vargroup`.`item_id`, `Vargroup`.`image`, `Vargroup`.`price`, `Vargroup`.`instock`, `Vargroup`.`timestamp` FROM `vargroups` AS `Vargroup` WHERE `Scrape`.`timestamp` = '2012-10-29
It doesn't look like its binding the table at all..
Any help would be appreciated.
Thanks
Try with this:
$this->Vargroup->contain('Scrape');
$this->Vargroup->find('first', array(
'conditions' => array(
'not' => array(
'Scrape.timestamp >' => array($today)
)
)
));
i think this examples from cakephp page tell the right way to do a "not" condition,
check it out.
array(
"NOT" => array("Post.title" => array("First post", "Second post", "Third post"))
)
this is the complex find conditions page if you have more questions. Cakephp complex find conditions
Imagine I have 2 models: Item and Category. Category hasMany Items and Item belongsTo Category.
I would like to obtain an array "reversed" on how cakephp normally return it: Usually I get something like
[Item]
...some props...
[Category]
...some props...
While I want something like:
Array
[0][Category]
Array
[0][Item]
...some props...
[1][Item]
[1][Category]
...and so on
How can I obtain this result with find method if possible? Otherwise, how to obtain it?
My current model is much more complex but I think I could apply this teory to all my models (I have a Category => Group => Item relationship).
Thanks for suggestions and answers.
According to the title of your question, if the point is to get only Items that are linked to categories named 'bla', you can just call the find() method on the Category model instead of the Item model.
Instead of
$this->Item->find('all', array('conditions' => array('Category.name' => 'bla')));
do
$this->Item->Category->find('all', array('conditions' => array('Category.name' => 'bla')));
This way it will first filter the corresponding Categories and then get the linked Items. So you will obtain something like
Array
(
[0] => Array
(
[Category] => Array
(
[id] => 1
[name] => bla
...
)
[Item] => Array
(
[0] => Array
(
[id] => 1
...
)
[1] => Array
(
[id] => 2
...
)
)
)
)
EDIT
With three models linked together, it is a bit more complicated. The only solution I can think of to prevent loading a lot of data is to build a query with INNER JOINs:
$categories = $this->Category->find('all', array('fields' => array('Category.id', 'Category.name', 'Item.id', 'Item.name'),
'joins' => array(
array( 'table' => 'groups',
'alias' => 'Group',
'type' => 'inner',
'conditions' => 'Group.category_id = Category.id'
),
array( 'table' => 'items',
'alias' => 'Item',
'type' => 'inner',
'conditions' => array('Item.group_id = Group.id', 'Item.name' => 'bla')
))));
It will return an array like this:
Array
(
[0] => Array
(
[Category] => Array
(
[id] => 2
[name] => Shop
)
[Item] => Array
(
[id] => 1
[name] => Bla
)
)
)
EDIT2
A last word about the structure of the array you'll get: it is not exactly like you wanted. The Item array is at the same level that the Category array. So you may end up with many pairs of Category-Item for the same Category.
But a simple foreach loop would then allow you to build an array with the exact struture you wish and this query has the advantage to get only what is neccessary from the database.
Here's an example...
I'm using a table to manage all of my Statuses with the tree behavior. I have a Book model which has a status for it's condition and one for it's availability. So the Book model HABTM Statuses even thought it can only have one condition and one availability.
Is there a way to use the $paginator->sort('Condition', '?') with a HABTM ? I would like to sort the title from the array below.
This is what $this->data is giving me :
[Status] => Array
(
[0] => Array
(
[id] => 2
[parent_id] => 1
[lft] => 2
[rght] => 3
[title] => Mint
[created] => 2010-01-18 16:20:54
[modified] => 2010-01-18 16:20:54
[active] => 1
[BooksStatus] => Array
(
[id] => 7
[book_id] => 3
[status_id] => 2
)
)
)
i would use 2 x belongsTo with different names.
$belongsTo = array(
'BookStatus' => array(
'className' => 'Status',
'foreignKey' => 'book_status_id'
),
'BookCondition' => array(
'className' => 'Status',
'foreignKey' => 'book_condition_id'
)
)
dont know how this would then fit into your tree strut
if that doesnt work then Try $paginator->sort('Condition', 'BooksStatus.status_id');
you will need to make sure the query used to retrieve the above does a join(unBind/bind on the fly)