Axiol
Axiol

Reputation: 5962

Paginate a search result in CakePHP

I've set a simple search engine on my CakePHP project which looks like that :

<?php 
    echo $this->Form->create("Post", array(
        "action" => "search", 
        "id" => "searchForm"
    ));
    echo $this->Form->input("keyword", array(
        "label" => "",
        "type" => "search",
        "placeholder" => "Recherche..."
    ));
    echo $this->Form->end(); 
?>

Here is the controller :

function search() {
    $keyword = $this->request->data;
    $keyword = $keyword["Post"]["keyword"];
    $cond = array("OR" => array(
        "Post.title LIKE '%$keyword%'",
        "Post.description LIKE '%$keyword%'"
    ));
    $posts = $this->Post->find("all", array("conditions" => $cond));
    $this->set(compact("posts", "keyword"));
}

And it works great. The only problem is when I want to paginate the results. I simply add :

$posts = $this->paginate();

And here is the problem. When I add this, CakePHP give me all the posts and not only the ones that match the keyword.

So, if you would have a solution, it would be nice :)

Upvotes: 6

Views: 15743

Answers (3)

Quy Le
Quy Le

Reputation: 2379

you can use Session for storing conditions
the first, when you submit form you store conditions into Session
and then(paginate) you can read conditions from Session

example i want to search the products:
Products/search.ctp
<?php
    echo $this->Form->create('Product');
    echo $this->Form->input('keyword');
    echo $this->Form->end(__('Search'));
?>
ProductsController.php
<?php 
class ProductsController extends AppController{

public function search() {
        if ($this->request->is('post')) {
            $keyword = $this->request->data['Product']['keyword'];
            $this->paginate = array(
                'fields' => array('Product.name', 'Product.price', 'Product.created'),
                'order' => array('Product.created' => 'DESC', 'Product.price' => 'DESC'),
                'limit' => 30,
                'conditions' => array('Product.name LIKE' => '%' . $keyword . '%')
            );
            // store array $this->paginate into Session
            $this->Session->write('paginate', $this->paginate);
        }
        $this->paginate = $this->Session->read('paginate');
        $this->set('products', $this->paginate('Product'));
    }
}

Upvotes: 0

Eoin Murphy
Eoin Murphy

Reputation: 813

According to the CakePHP book you should be able to do

$this->paginate('Post', array(
    'OR' => array(
        'Post.title LIKE' => "%$keyword%",
        'Post.description LIKE' => "%$keyword%"
    )

));

Or you can do it like this ( from the cakephp site ).

public function list_recipes() {
    $this->paginate = array(
        'conditions' => array('Recipe.title LIKE' => 'a%'),
        'limit' => 10
    );
    $data = $this->paginate('Recipe');
    $this->set(compact('data'));
);

Source: http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html

Upvotes: 14

Grambot
Grambot

Reputation: 4524

Paginate does its own lookup on the data I believe. The find you are calling previously has no effect on the paginate.

Try this:

$this->paginate = array( 'conditions' => $cond, ));

Upvotes: 0

Related Questions