Pagination issue when search result - cakephp

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.

Related

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'
));

How to get choices of each item in a table in cakephp?

This is my choices table
id | question_id | content
1 1 bee
2 1 fly
3 1 dog
4 2 cat
5 2 bat
6 2 wasp
and this is my questions table
id | content
1 question1
2 item2
This is what i did.With this I could display the question with its choices..what I want to do now, is to paginate it,more like 1 question per page.How to do this?Your help will be greatly appreciated.Thanks
$options['fields'] = array('questions.id','questions.content');
$options['joins'] = array(
array(
'table' => 'generated_exam_items',
'alias' => 'GenExamItems',
'type' => 'inner',
'conditions' => array(
'GenExamItems.generated_examination_id' => 25
)
),
array(
'table' => 'questions',
'alias' => 'Questions',
'type' => 'inner',
'conditions' => array(
'Questions.id = GenExamItems.questions_id'
)
),
);
$options['conditions']=array('GenExamItems.generated_examination_id' => 25,'Question.id=GenExamItems.questions_id');
$question_detail = $this->Question->find('all',$options);
$this->set('questions',$question_detail);
Someone please help me.!!I dont how to do it and im stuck in this for almos a week..
you can get using relation ship with each other model
as here i am just adding skeleton code you need to verify it to you actual code with real classname
In Question model write this relation
class Question extends AppModel {
public $hasMany = array(
'Choice' => array(
'className' => 'Choice',
)
);
And in Choice model you can define like
class Choice extends AppModel {
public $belongsTo = 'Question';
}
And in controller if you want to fetch for speacific Question with its choices you can write query like below
$question_detail = $this->Question->find('first', array(
'conditions' => array('Question.id' => $question_id)
));
let me know if i can help you more
Let's assume you have the correct associations on both models.
I'll show the code for just one question in the view.
If you use the automagic way cake provides (read the "Creating form elements" part)
In your controller, you have to get the choices
$this->set('choices', $this->Question->Choice->find('list',
array('conditions'=>
array('question_id'=>$your_question_id))));
And in your view, you have to do
echo $this->Form->input('choice_id', array('type'=>'radio'));
That should automatically display the choices as radios (not really sure what type of input you wanted)
If by some reason the automagic way doesn't work (be sure to check your model's associations if that happens), then you can pass the array of choices (get them as showed before on the controller) and pass it as a parameter
echo $this->Form->input('choice_id', array('type'=>'radio',
'options'=>$choices));
Note: If the radio labels are showing the ids instead of the content, you'll have to change the displayField of choices.
This what i did.It returns the question and corresponding choices.I hope I will be able to someone with this.Thank you.
public function take($id=null) {
$this->request->params['named']['page'] = (isset($this->request->params['page'])) ? $this->request->params['page'] : 1;
$options['fields'] = array('questions.id','questions.content');
$options['joins'] = array(
array(
'table' => 'generated_exam_items',
'alias' => 'GenExamItems',
'type' => 'inner',
'conditions' => array(
'GenExamItems.generated_examination_id' => 40
)
),
array(
'table' => 'questions',
'alias' => 'Questions',
'type' => 'inner',
'conditions' => array(
'Questions.id = GenExamItems.questions_id'
)
),
);
//$options['contains']='Choice';
$options['conditions']=array('Question.id = GenExamItems.questions_id');
$options['order']=array('rand(Question.id)');
$options['limit']=1;
$this->paginate=$options;
$data = $this->paginate('Question');
$this->set('questions',$data);
}

Trying to get "City" data from Event->Venue->City using 'contain' in CakePHP

I'm trying to return a list of events, and include the city where it's taking place. The city is only associated through the Event's Venue though.
Below is the code I'm using. It returns all the correct data, but it doesn't return ANY city data (other than the city_id field in Venue - which I'm not sure why it's returning).
Associations:
Event belongsTo Venue
Venue hasMany Event
Venue belongsTo City
City hasMany Venue
Code:
$this->Event->Behaviors->attach('Containable');
$events = $this->Event->find('all', array(
'limit' => 5,
'order' => 'Event.created DESC',
'fields' => array(
'name',
'description',
'phone',
'price_general',
'price_child',
'price_adult',
'price_child',
'tickets_url'
),
'contain' => array(
'Venue' => array(
'fields' => array(
'name',
'address',
'city_id',
),
'City' => array(
'fields' => array(
'City.name',
'state'
),
'conditions' => array(
'City.id' => 'Venue.city_id'
)
)
),
'Schedule' => array(
'fields'=>array(),
'Date' => array(
'conditions'=>array(
'Date.start >=' => $start_date,
'Date.start <=' => $end_date,
)
)
)
),
));
Bonus answer: (that I have currently asked in another StackOverflow question) - The Date conditions are supposed to filter which events show up, but instead, they're only filtering which Date data to show.
WORKING ANSWER: (thanks bancer)
$this->Event->recursive = -1;
$options['joins'] = array(
array('table' => 'schedules',
'alias' => 'Schedule',
'type' => 'LEFT',
'conditions' => array(
'Event.id = Schedule.event_id',
)
),
array('table' => 'dates',
'alias' => 'Date',
'type' => 'LEFT',
'conditions' => array(
'Date.schedule_id = Schedule.id',
)
)
);
$options['fields'] = array(
'Event.name',
'Schedule.start_date',
'Date.start',
);
$options['limit'] = 5;
$events = $this->Event->find('all', $options);
I would recommend to avoid using Containable. It generates too many queries in some cases. A better way for complex queries is to join tables "manually".
Another option I would consider at the first place is to search through 'Venue' model without using Containable like this: $this->Event->Venues->find('all', ...). As Venues directly associated with Cities and Events there should be possible to get what you want without extra complexities.
Update: take a look at the question How to change the sequence of 'joins' in CakePHP?
instead of containable, did you try including the city data in fields itself by fields=> array('','','City.name)

cakephp paginate multiple habtm

i have multiple habtm like these :
// User model
var $hasMany = array('Post');
// Post model
var $hasAndBelongsToMany = array('Category', 'Tag');
// Category model
var $hasAndBelongsToMany = array('Post');
// Tag model
var $hasAndBelongsToMany = array('Post');
I tried to fetch all post along with its user and tags (within a certain category), somehow if i fetch tags, the result was wrong.
$this->paginate = array
(
'Post' => array
(
'limit' => 2,
'fields' => array(
'Post.title', 'Post.content', 'Post.slug', 'Post.created',
'Tag.name',
'User.username', 'User.created', 'User.post_count', 'User.avatar_file_name'),
'joins' => array
(
array(
'table' => 'categories_posts',
'alias' => 'CategoriesPost',
'type' => 'inner',
'conditions'=> array('CategoriesPost.post_id = Post.id')
),
// FETCH USER
array(
'table' => 'users',
'alias' => 'User',
'type' => 'inner',
'conditions'=> array('Post.user_id = User.id')
),
// FETCH TAGS
array(
'table' => 'posts_tags',
'alias' => 'PostsTag',
'type' => 'inner',
'conditions'=> array('PostsTag.post_id = Post.id')
),
array(
'table' => 'tags',
'alias' => 'Tag',
'type' => 'inner',
'conditions'=> array('Tag.id = PostsTag.tag_id')
),
array(
'table' => 'categories',
'alias' => 'Category',
'type' => 'inner',
'conditions'=> array('Category.id = CategoriesPost.category_id', 'Category.slug' => $slug)
)
)
)
);
$posts = $this->paginate();
could anyone gimme a solution since i'm a newbie?
many thanks...
I've run into a similar problem, when trying to paginate a resultset using an associated model. I ended up having to manually bind my models together, run the query, and then unbind them in order to get Cake to contain the right data together. ( http://book.cakephp.org/view/86/Creating-and-Destroying-Associations-on-the-Fly )
You could also try the containable behaviour which will allow you to specify which models you want to include in your result set. Containable is core in 1.2+ ( http://book.cakephp.org/view/474/Containable ), otherwise you'll need to grab it yourself.
I'm not too sure on why you have such a gargantuan query there though. I would be more inclined to do something similar to the following.
$this->Model->recursive = 2;
$this->Model->paginate();
And let Cake get all the related data for me through my associations. Then I would adjust the return using a conditions array ( http://api.cakephp.org/class/controller#method-Controllerpaginate ) to specify the category.
Sorry it's not a defacto solution, but I'm a CakePHP amateur myself! You might find it easier to view the queries, results etc, using DebugKit, http://github.com/cakephp/debug_kit

Resources