pagination; Results from multiple models - cakephp

I have built a cake model that, when searched, needs to return paginated results that exclude some items based on data in another model.
I have a model called Box and a model called Item.
Each box can have 0 or more items, but I only want the boxes with 1 or more items with the category of Fruit to appear in a pagination result.
The Box model has a 'hasMany' association with the Item model.
The Item model has a field called 'is_friut'.
take care,
lee

This will make an inner join between the tables, only when the item is_fruit.
public $paginate = array(
'joins' => array(
array(
'table' => 'items',
'alias' => 'ItemJoin',
'type' => 'INNER',
'conditions' => array(
'ItemJoin.is_fruit' => 1
)
)
)
);

Related

how to make associations between grand parent & parent & child in cakephp 2

I have 4 tabels
stores
categories
items
item_images
Now i want to make association between them categories have store_id foreign key and items table have category_id and item_images have item_id foreign key.
public $hasMany = array(
'Item' => array(
'className' => 'Item',
'foreignKey' => 'category_id'
));
The above association is for category that find the related items but i want to do associate it with item_images. How i can do it with item_images now?
In Controller i have this query
$storeCategoriesDetails = $this->Category->find("all", array('conditions' => array('Category.storeId' => $id)));
You want to put your association for the item_images on the Item model like you've done for items on the Category model. You can then retrieve the item images along with the items when retrieving categories using contain:-
$storeCategoriesDetails = $this->Category->find('all', array(
'contain' => array('Item' => array('ItemImage'))
'conditions' => array('Category.storeId' => $id)
));
I added this line in my controller function and it's working now.
$this->Category->Behaviors->load('Containable');

Getting data by search filter from associated models

i have an question regarding search filter in cakephp. Without complicating my question, below are the structure of what i want....
1) I have a projects table.
2) another one is project_funder_names table which is associated with projects table. project_id is in project_funder_names table. i have made project_funder_names table because i need multiple funder names for a single project, thats why i have made this table.
3) now the main point is i want if i search multiple funders in search filter which is coming in dropdown with checkbox, i will get project details according to these values. so how it would happen.
here is my cakephp find all query....
$project_info = $this->Project->find('all', array(
'conditions' =>
array(
'Project.status' => 1,
'OR' => array($search)),
'fields' => array('id', 'title', 'short_description', 'budget_allocation', 'currency', 'total_comments', 'published_date'),
'contain' => array(
'ProjectFunderName' => array(
'conditions' => array($search_funder)),
'Currency' => array('currency_symbol'),
'ProjectBookmark' => array('project_id', 'user_id')
)
)
);
problem is in $search_funder.
please help me for this.. thanks.
Looks like you need to search results based on associated models. One drawback of using containable behavior is if you're trying to assign a condition to an associated model, the main model will be retrieved no matter what.
In situations where you'd want to retrieve the main as well as the associated records based on a condition for the associated model, I'd suggest you to use join.
$joins = array(
array('table' => 'project_funder_names',
'alias' => 'ProjectFunderName',
'type' => 'LEFT',
'conditions' => array('ProjectFunderName.project_id = Project.id')
),
array('table' => 'currencies',
'alias' => 'Currency',
'type' => 'LEFT',
// It's unclear how currencies is associated with the other tables. Use appropriate table join condition here
),
array('table' => 'project_bookmarks',
'alias' => 'ProjectBookmark',
'type' => 'LEFT',
'conditions' => array('ProjectBookmark.project_id = Project.id')
)
)
);
$project_info = $this->Project->find('all',
array(
"joins" => $joins,
"fields" => array(.........) // Specify all your desired fields here
"conditions" => array(....) // Specify all conditions for Project, ProjectFunderName models.
)
);
Hope this helps.
Peace! xD

Select records which have atleast one hasMany relation row in Cakephp

I'm facing a problem with cakephp associations in Models.
I have to Select records which have atleast one hasMany reation row
Model
class Category extends AppModel
{
public $hasMany = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'CategoryId',
)
);
}
Query
$categories = $this->Category->find('all');
I only needed the categories which have atleast one product entry
Categories Like : Shirts, Footwear, Glasses etc
Products like :
Small, medium, large (Shirts)
With Frame, UV protected (Glass)
So, i jus want to get Shirts and Glasses Categories only because for the above example there is no products for Footwear
Use counterCache or joins
Please refer to CakePHP - Find and count how many associated records exist
The most simple way with the best performance would be using a properly indexed counter cache field as shown in the linked answer.
Sice the linked answer is not an exact duplicate with respect to the join, here's some additional info, instead of using HAVING COUNT with the join you'd use a IS NOT NULL condition. Here's an (untested) example:
$this->Category->find('all', array(
'joins' => array(
array(
'table' => 'products',
'alias' => 'Product',
'type' => 'LEFT',
'conditions' => array('Category.id = Product.CategoryId')
)
),
'conditions' => array(
'Product.CategoryId IS NOT NULL'
)
'group' => 'Category.id'
));
Depending on the used DBMS and version you might get better performance using an inner join:
$this->Category->find('all', array(
'joins' => array(
array(
'table' => 'products',
'alias' => 'Product',
'type' => 'INNER',
'conditions' => array('Category.id = Product.CategoryId')
)
),
'group' => 'Category.id'
));

Pagination issue when search result

I have 2 Model Playlist and PlaylistTrack PlalistTrack model contains track of playlist. One playlist has many tracks.
Table: Playlist(id,name)
Table: PlaylistTrack(id,track_id,playlist_id)
Following my code.
$conditions=array();
if(isset($this->params->query['search']) && $this->params->query['search']!="")
{
$conditions['AND']['Playlist.name LIKE']="%".$this->params->query['search']."%";
}
$this->paginate = array(
'fields'=>array('Playlist.*','count(`PlaylistTrack`.`track_id`) as tracks'),
'group' => "Playlist.id",
'limit' => 10,
'conditions'=>$condtions,
'joins'=>array(
array(
'table' => 'playlist_tracks',
'alias' => 'PlaylistTrack',
'type' => 'LEFT',
'conditions' => array(
'Playlist.id=PlaylistTrack.playlist_id'
)
)
)
);
$data = $this->paginate('Playlist');
For all record pagination will work fine but when I search from playlist by playlist_name then Display one record with search parameter but there There are two page for one record.
If any further code required just tell me I explain in detail.

CakePHP 2.1 - Saving (and creating) multiple Join Models and associated models

My model relationship is as follows:
Student hasMany ClassStudent
Class hasMany ClassStudent
ClassStudent belongsTo Student
ClassStudent belongsTo Class
ClassStudent is a join model.
What I want to do is create Student(s), use an existing Class or create a new one, and create a join model record that links the Students and classes.
I want to do this all in one call to save (if this is even possible).
I have tried:
$data = array(
'Student' => array(
'0' => array( ... ), // Data in here
'1' => array( ... ),
...,
'n' => array( ... )
),
'Class' => array(
'class_id' => x // The class that I want the above students to be associated with
)
)
What I want to do is create n records of students and also add them to a class (possibly creating a class at the same time if the users wants to add a new one). I also want to create a join model record for each Student to the Class when I am creating the Student records.
Is this possible? I am using Cake 2.1.0 (today's stable release), and I have tried the different types of saveAll (saveAssociated and saveMany) with $options['deep'] = true.
Is it possible my data array is not in the correct format?
EDIT:
I have also tried:
$data = array(
'ClassStudent' => array(
'0' => array(
'Student' => array (...), // Data
'Class' => array(id => x) // The id of the Class the Student should be associated to
...,
'n' => array(
'Student' => array(...), // n-th Student
'Class' => array(id => x)
)
);
$this->saveAll($data['ClassStudent'], array('deep' => true));
In the above case, it successfully creates new Student records in the students table, but nothing is created in the join table.
saveAll (saveAll is a wrapper to saveMany and saveAssociated) is the right tool for the job. Take a look at the documentation for saveAll, I don't see any notes about it changing for 2.1. Having taking more time to read, here are some thoughts
First off, is there a type in your array structure. You have
'Class' => array ( 'class_id' => x )
If the Class is already defined and you are just wanting to add a student, then it would be
'ClassStudent' => array( 'class_id' => x )
With that said, CakesPHP ORM should allow you to use a saveAll with on a hasMany using a numerical index, so if assuming you have a typo, there follow might work for you
$data = array(
'Student' => array(
'0' => array( ... ), // Data in here
'1' => array( ... ),
...,
'n' => array( ... )
),
'ClassStudent' => array(
'class_id' => x // The class that I want the above students to be associated with
)
)
$this->ClassStudent->saveAll($data);

Resources