CakePHP: разбиение на страницы с помощью логики поиска в модели

У меня возникли проблемы с разбивкой по страницам результатов поиска. Моя настройка такова.

У меня есть форма поиска на myapp.com/searches/products с представлением (с формой поиска) .../app/views/searches/products.ctp search .../app/views/searches/products.ctp . Я использую контроллер Searches который использует модель Product для этого поискового запроса. Product имеет search() действий search() с логикой поиска ( $this->find(...) ). Результат поиска отображается ниже формы в представлении.

Как мне сделать что-то похожее на $this->paginate() , которое обычно выполняется в контроллере? Кроме того, я хотел бы знать, что что-то не так с моей настройкой, особенно с представлением, которое включает как форму, так и результат поиска.

Один из способов сохранить логику поиска в модели и по-прежнему разбивать на страницы в контроллере:

Объяснение:

Вместо того, чтобы возвращать фактические результаты из модели, просто верните все / все параметры поиска, затем выполните разбивку на страницы, как обычно. Для некоторых примеров, как этот простой ниже, это может показаться излишним, но оно оставляет место для добавления намного большего количества вариантов для вашего find() например, contain , order , group , joins , conditions … и т. Д. И т. Д. И остается больше в -лайн с мантрой «Жирные модели, тощие контроллеры».

Также приятно настроить вашу find() с такими вариантами, чтобы она была легко повторно использована на вашем сайте – просто передайте ей разные варианты, и вам хорошо идти.

Код:

 /* CONTROLLER */ $opts = array('paginate' => true, 'limit'=>20); $paginateOptions = $this->Event->getEvents($opts); $this->paginate = $paginateOptions; $data = $this->paginate('Event'); /* MODEL */ public function getProducts($opts = null) { $params = array(); //limit $params['limit'] = 50; //default if(!empty($opts['limit'])) $params['limit'] = $opts['limit']; //paginate option $paginate = false; if(isset($opts['paginate'])) { if($opts['paginate']) $paginate = true; } //either return the options just created (paginate) if($paginate) { return $qOpts; //or return the events data } else { $data = $this->find('all', $qOpts); return $data; } } 

Есть способы написать это немного стройнее / меньше строк кода, но мне нравится писать его так, чтобы это было понятно.

(В вашей общей структуре нет ничего плохого).

Обычно я использую, чтобы хранить параметры поиска в сеансе и обрабатывать все внутри действия контроллера.

 function indexbystatus() { $this->set('title_for_layout','List Assets by Status'); $this->Session->write('sender',array('controller'=>'assets','action'=>'indexbystatus')); $searchkey=$this->Session->read('Searchkey.status'); $conditions=''; if($searchkey) { $conditions=array('Asset.status_id'=>$searchkey); } if(!empty($this->data)) { // if user has sent anything by the searchform set conditions and // store it to the session but if it is empty we delete the stored // searchkey (this way we can reset the search) if($this->data['Asset']['status_id']!='') { $conditions=array('Asset.status_id'=>$this->data['Asset']['status_id']); $this->Session->write('Searchkey.status',$this->data['Asset']['status_id']); } else { $this->Session->delete('Searchkey.status'); $conditions=null; } } else if($searchkey) { // if no data from the searchform we set the stored one // from the session if any $this->data['Asset']['status_id']=$searchkey; } $this->paginate=array( 'limit'=>25, 'order'=>array('Asset.status_id'=>'asc'), 'conditions'=>$conditions, ); $this->set('assets',$this->paginate()); $statuses=$this->Asset->Status->find('list'); $this->set('statuses',$statuses); } по function indexbystatus() { $this->set('title_for_layout','List Assets by Status'); $this->Session->write('sender',array('controller'=>'assets','action'=>'indexbystatus')); $searchkey=$this->Session->read('Searchkey.status'); $conditions=''; if($searchkey) { $conditions=array('Asset.status_id'=>$searchkey); } if(!empty($this->data)) { // if user has sent anything by the searchform set conditions and // store it to the session but if it is empty we delete the stored // searchkey (this way we can reset the search) if($this->data['Asset']['status_id']!='') { $conditions=array('Asset.status_id'=>$this->data['Asset']['status_id']); $this->Session->write('Searchkey.status',$this->data['Asset']['status_id']); } else { $this->Session->delete('Searchkey.status'); $conditions=null; } } else if($searchkey) { // if no data from the searchform we set the stored one // from the session if any $this->data['Asset']['status_id']=$searchkey; } $this->paginate=array( 'limit'=>25, 'order'=>array('Asset.status_id'=>'asc'), 'conditions'=>$conditions, ); $this->set('assets',$this->paginate()); $statuses=$this->Asset->Status->find('list'); $this->set('statuses',$statuses); } обеспеченному function indexbystatus() { $this->set('title_for_layout','List Assets by Status'); $this->Session->write('sender',array('controller'=>'assets','action'=>'indexbystatus')); $searchkey=$this->Session->read('Searchkey.status'); $conditions=''; if($searchkey) { $conditions=array('Asset.status_id'=>$searchkey); } if(!empty($this->data)) { // if user has sent anything by the searchform set conditions and // store it to the session but if it is empty we delete the stored // searchkey (this way we can reset the search) if($this->data['Asset']['status_id']!='') { $conditions=array('Asset.status_id'=>$this->data['Asset']['status_id']); $this->Session->write('Searchkey.status',$this->data['Asset']['status_id']); } else { $this->Session->delete('Searchkey.status'); $conditions=null; } } else if($searchkey) { // if no data from the searchform we set the stored one // from the session if any $this->data['Asset']['status_id']=$searchkey; } $this->paginate=array( 'limit'=>25, 'order'=>array('Asset.status_id'=>'asc'), 'conditions'=>$conditions, ); $this->set('assets',$this->paginate()); $statuses=$this->Asset->Status->find('list'); $this->set('statuses',$statuses); } 

Мне просто больше нравится обрабатывать его в действии контроллера не в модели, поэтому я могу иметь разные решения и логику действий.