CakePHP Pagination with a model which has a HABTM model - php

I have 3 models (artist, media item, accent)
Artist hasMany media items,
Media items hasAndBelongsToMany accents,
Now what I am having issues with is how to search with pagination, I need to get pages of 8 artists and the media_items which match the accent entered. Hopefully that makes sense.
This is what I have currently
$this->Paginator->settings = array(
'limit' => 8,
'fields' => array("Artist.first_name",
"Artist.last_name", "Artist.image",
"Artist.image", "Artist.slug"),
'order' => "Artist.last_name",
'url' => $this->passedArgs,
'contain' => array(
'MediaItem'=> array(
"fields" => array("MediaItem.file",
"MediaItem.title",
"MediaItem.accent",)
),
'joins' => array(
array(
'table' => 'media_items',
'type' => 'INNER',
'alias' => 'MediaItem',
'conditions' => array(
"AND" => array('Artist.id = MediaItem.artist_id')
)
),
array(
'table' => 'media_accents_media_items',
'type' => 'RIGHT',
'alias' => 'MediaAccentsMediaItems',
'conditions' => array(
"AND" => array('MediaAccentsMediaItems.media_item_id = MediaItem.id')
)
),
array(
'table' => 'media_accents',
'type' => 'RIGHT',
'alias' => 'MediaAccent',
'conditions' => array(
"AND" => array('MediaAccent.id = MediaAccentsMediaItems.media_accent_id'),
"OR" => array('MediaAccent.name LIKE' => "%".$searchFor ."%")
)
)
),
'group' => 'Artist.id',
'update' => '.results-container',
'evalScripts' => true
);
it gets the right artists but returns all their tracks rather than the ones I need. Is there a better way rather than looping through the results pruning them? Which is my current backup plan.

Remove joins and just use Containable Behavior, here is docs for deeper associations.

Related

Custom query pagination in cakephp

I have a query as below in controller with multiple joins
$deals = $this->Deals->find('all', array(
'fields' => array(
'Deals.id',
'Deals.deed_amount',
'Deals.other_amount',
'Deals.cash_amount',
'Deals.total_amount',
'Deals.client_id',
'Deals.project_id',
'Deals.property_id',
'Deals.properties_flat_id',
'Deals.date',
'Deals.status',
'Deals.invoice_no',
'Deals.remain_cash_amount',
'Deals.remain_deed_amount',
'Deals.remain_other_amount',
'Deals.remain_deed_amount',
'Property.name',
'Client.name',
'PropertyFlat.name',
'PropertyFlat.status'
),
'joins' => array(
array(
'table' => 'properties',
'alias' => 'Property',
'type' => 'LEFT',
'conditions' => array(
'Deals.property_id = Property.id'
)
),
array(
'table' => 'clients',
'alias' => 'Client',
'type' => 'LEFT',
'conditions' => array(
'Deals.client_id = Client.id'
)
),
array(
'table' => 'properties_flats',
'alias' => 'PropertyFlat',
'type' => 'LEFT',
'conditions' => array(
'Deals.properties_flat_id = PropertyFlat.id'
)
)
),
// 'conditions'=>$condition
));
I want to add pagination to the view. I tried following
$this->set('deals', $this->Paginator->paginate($deals));
But no use. Please help me in how to add pagination for the custom query. I searched many links but did not get any help.
You can try like this:
$paginate = [
'joins' => array(
array(
'table' => 'properties',
'alias' => 'Property',
'type' => 'LEFT',
'conditions' => array(
'Deals.property_id = Property.id'
)
),
array(
'table' => 'clients',
'alias' => 'Client',
'type' => 'LEFT',
'conditions' => array(
'Deals.client_id = Client.id'
)
),
array(
'table' => 'properties_flats',
'alias' => 'PropertyFlat',
'type' => 'LEFT',
'conditions' => array(
'Deals.properties_flat_id = PropertyFlat.id'
)
)
),
'fields' => array(
'Deals.id',
'Deals.deed_amount',
'Deals.other_amount',
'Deals.cash_amount',
'Deals.total_amount',
'Deals.client_id',
'Deals.project_id',
'Deals.property_id',
'Deals.properties_flat_id',
'Deals.date',
'Deals.status',
'Deals.invoice_no',
'Deals.remain_cash_amount',
'Deals.remain_deed_amount',
'Deals.remain_other_amount',
'Deals.remain_deed_amount',
'Property.name',
'Client.name',
'PropertyFlat.name',
'PropertyFlat.status'
)
];
$this->set('deals', $this->Paginator->paginate($this->Deals->find('all'), $paginate)->toArray());
Firstly, I would recommend to rethink the way you have constructed your query. Why don't you just use the contain() method to retrieve the associated data?
Secondly, You can use custom finders with the paginator. Just create one in your Table class and return constructed query from it and ask the paginator to use it. Read more here. https://book.cakephp.org/3.0/en/controllers/components/pagination.html

how to paginate in cakephp when result comes from several join conditions

I have a problem in cakephp pagination.Before i came deep i would like to display some code that i do in my controller
$this->paginate = array(
'joins' => array(
array(
'table' => 'job_posting_lists',
'conditions'=> array('job_posting_lists.firm_id')),
array(
'table' => 'firmsdetails',
'alias' => 'st',
'conditions'=> array('st.id')),
),
'conditions' =>array('job_posting_lists.select_industry'=>$id,'job_posting_lists.verify'=>1),
'fields' => array('job_posting_lists.*','st.*'),
'limit' => 3,
'contain' => array('job_posting_lists'));
$ListjobBycategories = $this->paginate();
echo "<pre>";print_r($ListjobBycategories); die;
$this->set('jobbycat',$ListjobBycategories);
the result come in ListjobBycategories correct but it returns more data about 1230 and in my job_posting_datas only 5 rows the next page return same result what i do
Try this code, make appropriate changes as per your code,
$this->paginate = array(
'joins' => array(
array(
'table' => 'tbl1',
'alias' => 'alias1',
'conditions'=> array('')
),array(
'table' => 'tbl2',
'alias' => 'alias2',
'conditions'=> array('')
),array(
'table' => 'tbl3',
'alias' => 'alias3',
'type' => 'left',
'conditions'=> array('')
),
),
'conditions' => $displayConditions, // Your query conditions
'fields' => $this->displayFields, // Your field set which you want to retrieve from tables
'limit' => $show_page,// number of records you wish to retrieve in each page
'group' => '', // field by which wish to grouping your data set
'contain' => array(''),//It will contain name of all the Models which are in Join
);
$ListjobBycategories = $this->paginate(); // Call pagination function, it will retrieve all records
Let me know if any query.

Access related models/tables to inner join query in cakephp

I have this inner join query in a paginated model called Application
Application has many AssignedExploration
AssignedExploration belongs to Exploration
Exploration belongs to ExplorationCategory
ExplorationCategory belongs to Season
My query so far is:
$session_condition = array(
'table' => 'assigned_explorations',
'alias' => 'AssignedExploration',
'type' => 'INNER',
'conditions' => array(
'AssignedExploration.application_id = Application.id',
'OR' => array(
array('AssignedExploration.label' => $this->request->named['filter_session'])
)
)
);
I would like to add another query inside the OR that will get applications which has a Season.name = fall
I've tried adding array('Season.name' => 'fall') :
$session_condition = array(
'table' => 'assigned_explorations',
'alias' => 'AssignedExploration',
'type' => 'INNER',
'conditions' => array(
'AssignedExploration.application_id = Application.id',
'OR' => array(
array('AssignedExploration.label' => $this->request->named['filter_session']),
array('Season.name' => 'fall')
)
)
);
But no luck. Seems like Season is not recognized by AssignedExploration.
I would like to nest from AssignedExploration to Exploration to ExplorationCategory and to Season
And I don't have any idea on how to make it thru inner join query via cakephp.
Thanks in advanced.
EDIT: query as of now:
INNER JOIN
`ntc_development`.`assigned_explorations` AS `AssignedExploration` ON (
`AssignedExploration`.`application_id` = `Application`.`id`
AND
`AssignedExploration`.`label` = 'fall'
)
$this->paginate['Application'] = array(
'recursive' => -1,
'joins' => array(
array(
'table' => 'assigned_explorations',
'alias' => 'AssignedExploration',
'type' => 'inner',
'foreignKey' => true,
'conditions' => array('AssignedExploration.application_id = Application.id')
),
array(
'table' => 'seasons',
'alias' => 'Season',
'type' => 'inner',
'foreignKey' => true,
'conditions' => array('Season.id = Application.season_id') # whats your foregin key
),
),
'fields' => array(),
'conditions' => array('Season.name' => 'fail'),
);

CakePHP: Join Operation not working

I have Tables
Items, Attributes,Taxonomies, Taxonomy_attributes,Item_attributes.
Taxonomy_attributes have two fields attribute_id(which is a foreign key to id of attributes table) and taxonomy_id (which is a foreign key to id of taxonomies table).
On the other hand Item_attributes have two fields attribute_id(which is a foreign key to id attributes table) and item_id (which is a foreign key to of id items table).
Attributes table have following fields :- Name, Type and Checkable(which is either 0 or 1).
Items table have fields id and model.
Taxonomies table have fields if and name.
I want to add a method to Attribute model ,that returns list of all attributes with checkable equals 1 and join with items and taxonomies ,that return item model & taxonomy name for each attribute.
My code is as follows:-
public function getCheckables($checkable)
{
$data = $this->find('all',array(
'fields' => array('Attribute.name', 'Attribute.type', 'Item.model', 'Taxonomy.name'),
'conditions' => array('Attribute.checkable' => 1),
'joins' => array(
array(
'table' => 'item_attributes',
'alias' => 'ItemAttribute',
'type' => 'INNER',
'conditions' => 'ItemAttribute.Item_id = Item.id',
),
array(
'table' => 'items',
'alias' => 'Item',
'type' => 'INNER',
'conditions' => 'ItemAttribute.item_id = Item.id'
),
array(
'table' => 'taxonomy_attributes',
'alias' => 'TaxonomyAttribute',
'type' => 'INNER',
'conditions' => 'TaxonomyAttribute.Taxonomy_id = Taxonomy.id'
)
),
'recursive'=>-1
)
);
pr($data); die();
}
Can anybody guide me with the right code?
2 of your joins have the same condition : 'conditions' => 'ItemAttribute.Item_id = Item.id', in case of the first one, Item table was not yet joined and in case of the second one, because your first condition was wrong, the ItemAttribute table was not joined.
The actual Solution
public function getCheckables($checkable)
{
$data = $this->find('all',array(
'fields' => array('Attribute.name', 'Attribute.type', 'Item.model', 'Taxonomy.name'),
'conditions' => array('Attribute.checkable' => 1),
'joins' => array(
array(
'table' => 'item_attributes',
'alias' => 'ItemAttribute',
'type' => 'INNER',
'conditions' => 'ItemAttribute.attribute_id = Attribute.id',
),
array(
'table' => 'items',
'alias' => 'Item',
'type' => 'INNER',
'conditions' => 'ItemAttribute.item_id = Item.id'
),
array(
'table' => 'taxonomies',
'alias' => 'Taxonomy',
'type' => 'LEFT',
'conditions' => 'Item.category_id = Item.id'
)
),
'recursive'=>-1
)
);
pr($data); die();
}

CakePHP - multiple hasAndBelongsToMany relationships not working

New to CakePHP etc and I'm massively confused with following problem so any guidance would be greatly appreciated. Essentially I'm having problems with hasAndBelongsToMany relationships and I don’t know if I’m going about it correctly as I’m doing most of the work inside one controller and one model.
I have a client’s pages, clients have many jobs (this works), clients belong to a client type (this works), clients also have many case studies (also works) and clients have jobs (fine).
Jobs have and belong to many disciplines – this doesn’t work, however, it appears as though the queries are being run (the SQL output in debug mode shows this, so I ran the SQL directly into MySQL - it queries fine) but Cake is not providing me the data into the clients array.
Here is the code for my Client Model and Controller.
Client.php (Model)
public $belongsTo = array(
'ClientType' => array(
'className' => 'ClientType',
'foreignKey' => 'type_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
public $hasMany = array(
'CaseStudy' => array(
'className' => 'CaseStudy',
'foreignKey' => 'main_contractor',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Job' => array(
'className' => 'Job',
'foreignKey' => 'client_id',
'conditions' => '',
'fields' => '',
'order' => 'Job.id desc'
)
);
ClientsController.php (Controller)
$options['joins'] = array(
array('table' => 'case_studies',
'alias' => 'CaseStudy',
'type' => 'LEFT',
'conditions' => array(
'CaseStudy.client_id = Client.id',
)
),
array('table' => 'jobs',
'alias' => 'Job',
'type' => 'LEFT',
'conditions' => array(
'Job.client_id = Client.id',
)
),
array('table' => 'sectors',
'alias' => 'Sector',
'type' => 'LEFT',
'conditions' => array(
'Job.sector_id = Sector.id',
)
),
array('table' => 'disciplines_jobs',
'alias' => 'DisciplinesJobs',
'type' => 'LEFT',
'conditions' => array(
'Job.id = DisciplinesJobs.job_id',
)
),
array(
'table' => 'disciplines',
'alias' => 'Discipline',
'type' => 'LEFT',
'conditions' => array(
'DisciplinesJobs.discipline_id = Discipline.id'
)
)
);
$options['conditions'] = array('Client.id' => $client_id);
$clients = $this->Client->find('all', $options);
Output of $clients array above:
array(
(int) 0 => array(
'Client' => array(
'id' => '47',
'type_id' => '2',
'name' => 'Balfour Beatty',
'logo' => '1361786198_thumbnail_balfour beatty.jpg',
'website_url' => 'http://www.google.com',
'date_added' => '2013-02-25 10:56:38',
'date_modified' => '2013-02-25 10:56:38'
),
'ClientType' => array(
'id' => '2',
'name' => 'Constructors'
),
'CaseStudy' => array(
(int) 0 => array(
'id' => '23',
'client_id' => '47',
'sector_id' => '1',
'name' => 'Shoreham Academy',
'header_image' => '1365088787_thumbnail_1365088787_header copy.jpg',
'main_contractor' => '47',
'architect' => 'Architecture PLB',
'project_value' => '565000',
'scope_of_works' => '<table></table>',
'text' => '<p><</p>',
'type' => 'flooring',
'date_added' => '2013-04-04 11:19:47',
'date_modified' => '2013-04-04 11:19:47'
)
),
'Job' => array(
(int) 0 => array(
'id' => '1',
'client_id' => '47',
'sector_id' => '2',
'project' => 'Shoreham Academy (Project not case study)',
'date' => '2012-10-19',
'cost' => '£416k',
'quantity_of_flooring' => '7000m',
'date_added' => '2013-08-06 21:46:59',
'date_modified' => '2013-08-06 21:47:01'
)
)
)
Notice the above $clients array doesn’t have any disciplines data from the discipline_jobs table but the SQL output is which runs successfully:
SELECT `Client`.`id`, `Client`.`type_id`, `Client`.`name`, `Client`.`logo`, `Client`.`website_url`, `Client`.`date_added`, `Client`.`date_modified`, `ClientType`.`id`, `ClientType`.`name`
FROM `ar_flooring`.`clients` AS `Client`
LEFT JOIN `ar_flooring`.`case_studies` AS `CaseStudy` ON (`CaseStudy`.`client_id` = `Client`.`id`)
LEFT JOIN `ar_flooring`.`jobs` AS `Job` ON (`Job`.`client_id` = `Client`.`id`)
LEFT JOIN `ar_flooring`.`sectors` AS `Sector` ON (`Job`.`sector_id` = `Sector`.`id`)
LEFT JOIN `ar_flooring`.`disciplines_jobs` AS `DisciplinesJobs` ON (`Job`.`id` = `DisciplinesJobs`.`job_id`) LEFT JOIN `ar_flooring`.`disciplines` AS `Discipline` ON (`DisciplinesJobs`.`discipline_id` = `Discipline`.`id`)
LEFT JOIN `ar_flooring`.`client_types` AS `ClientType` ON (`Client`.`type_id` = `ClientType`.`id`)
WHERE `Client`.`id` = 47
I don’t have a discipline model or controller. I don’t have a jobs model or controller because I’m trying to do everything with the clients model and controller – is this correct?
Does anyone know why this is happening?
Hope this makes sense.
Cheers!
It appears that you want to run a
$this->Client->find('all')
at your ClientsController.
In that find all, you want to retrieve a list of Clients, the ClientType each Client belongsTo, the CaseStudy list each Client has, the Job list each Client has, and the Discipline each Job hasAndBelongsTo.
First, as a practitioner of CakePHP, I almost always avoid using the habtm relationship.
The reason is that it is almost always the case that I have extra fields in the join table. In this case, jobs_disciplines is likely to have more than just job_id and discipline_id. Maybe it will also have another field called status.
What I would do is that I will bake the JobsDiscipline model and the Discipline Model.
JobsDiscipline will belong to both Discipline and Job.
Both Discipline and Job will have many JobsDiscipline.
After this, the query to construct is basically just
$this->Client->find('all', array(
'contain' => array('ClientType', 'CaseStudy', 'Job' => array('JobsDiscipline'=>array('Discipline')))
));
This should work even if you set the recursive at your AppModel to be -1.
If this does not work, let me know again.

Categories