I am working on view which displays all reservations(I am making reservations app) and has form to search. I am using CakeDC Plugin, but it doesn't work.
Here is my action:
public function index() {
if (!App::import('Component', 'Search.Prg')) {
throw new MissingPluginException(array('plugin' => 'Search'));
}
$this->Prg->commonProcess();
//$this->Paginator->settings['conditions'] = $this->Reservation->parseCriteria(/*$this->Prg->parsedParams()*/);
//$this->set('users', $this->Paginator->paginate());
$searchTerm = '';
//$this->Prg->commonProcess($this->modelClass, $this->modelClass, 'search', false);
$by = null;
if (!empty($this->request->params['named']['searchTerm'])) {
$searchTerm = $this->request->params['named']['searchTerm'];
$by = 'any';
}
$this->request->data[$this->modelClass]['searchTerm'] = $searchTerm;
$this->set('reservation_mode', Configure::read('webakis.reservation_type'));
$this->Reservation->recursive = 0;
$this->paginate = array(
'fields' => array('Reservation.id', 'Reservation.start', 'Reservation.ucode', 'Reservation.ticket_nr', 'Location.name', 'User.username', 'User.id', 'Opmenu.name', 'Queue.name'),
'conditions' => array(
// 'ucode <>' => 0,
'user_id <>' => 0,
'deleted' => 0,
// 'start >=NOW() '
),
'order' => array(
'Reservation.start' => 'asc'
),
//'search',
'limit' => 12,
'by' => $by,
'search' => $searchTerm,
);
$this->set('reservations', $this->paginate($this->modelClass));
$this->set('searchTerm', $searchTerm);
$this->set('model', $this->modelClass);
}
My form in view:
<?php
echo $this->Form->create($model, array(
'action' => 'index'));
echo $this->Form->input('searchTerm', array(
'label' => false, 'style' => 'float:left;', 'class' => 'offset1'));
echo $this->Form->submit(__('Search'), array('class' => 'btn', 'style' => ''));
echo $this->Form->end();
?>
My code in Model:
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
array('name' => 'searchTerm', 'type' => 'like', 'fields'=>array(/*'Reservation.start', 'Reservation.ucode', 'Reservation.ticket_nr', 'Location.name',*/ 'User.username'/*, 'Opmenu.name', 'Queue.name'*/)));
UPDATE:
I included this to make it work, but it's probably not best way:
$conditions = array();
$conditions[] = array("Reservation.start LIKE '%{$searchTerm}%'");
$conditions[] = array("Reservation.ucode LIKE '%{$searchTerm}%'");
$conditions[] = array("Reservation.ticket_nr LIKE '%{$searchTerm}%'");
$conditions[] = array("Location.name LIKE '%{$searchTerm}%'");
$conditions[] = array("User.username LIKE '%{$searchTerm}%'");
$conditions[] = array("Opmenu.name LIKE '%{$searchTerm}%'");
$conditions[] = array("Queue.name LIKE '%{$searchTerm}%'");
Ok, so after reading readme of my Plugin, I got it working.
Here is my Model code:
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'searchTerm' => array(
'type' => 'like',
'field'=>array('Reservation.start', 'Reservation.ucode', 'Reservation.ticket_nr', 'Location.name', 'User.username', 'Opmenu.name', 'Queue.name')),
'filter' => array('type' => 'query', 'method' => 'orConditions'));
public function orConditions($data = array()) {
$filter = $data['filter'];
$cond = array(
'OR' => array(
'Reservation.start LIKE' => '%' . $filter . '%',
'Reservation.ucode LIKE' => '%' . $filter . '%',
'Reservation.ticket_nr LIKE' => '%' . $filter . '%',
'Location.name LIKE' => '%' . $filter . '%',
'User.username LIKE' => '%' . $filter . '%',
'Opmenu.name LIKE' => '%' . $filter . '%',
'Queue.name LIKE' => '%' . $filter . '%'
));
return $cond;
}
Controller:
public $components = array('Search.Prg');
public $presetVars = true;
public function index() {
$this->Prg->commonProcess();
$this->paginate = array();
$conditions = $this->Reservation->parseCriteria($this->passedArgs);
$searchTerm = '';
$this->set('reservation_mode', Configure::read('webakis.reservation_type'));
$this->Reservation->recursive = 0;
$this->paginate = array(
'fields' => array('Reservation.id', 'Reservation.start', 'Reservation.ucode', 'Reservation.ticket_nr', 'Location.name', 'User.username', 'User.id', 'Opmenu.name', 'Queue.name'),
'conditions' => array(
// 'ucode <>' => 0,
'user_id <>' => 0,
'deleted' => 0,
// 'start >=NOW() '
),
'order' => array(
'Reservation.start' => 'asc'
),
'limit' => 12,
);
$this->set('reservations', $this->paginate($this->modelClass, $conditions));
$this->set('searchTerm', $searchTerm);
$this->set('model', $this->modelClass);
}
Related
I hope you can help me. I've done all steps like here "cakephp basic help to use cakedc search plugin" but the searcher doesn't anything.
My project is about one User's List and I want to filter for the fields 'apellidos' or 'dni'.
In my Controller I've the component declared and this:
public function index() {
$this->Prg->commonProcess();
$this->paginate = array(
'conditions' => $this->User->parseCriteria($this->passedArgs));
$this->set('users', $this->paginate());
$this->User->recursive = 0;
$this->User->order = 'User.cod_cliente';
$this->User->conditions = 'User.nombre';
if($this->Session->read('Auth.User.group_id')==5)
{
//$this->set('categorias', $this->User->find('all',array('fields'=>array('group_id','cod_cliente','nombre','apellidos','dni','id'))));
}else
{
$this->User->conditions = array('User.cod_centro'=>$this->Session->read('Auth.User.cod_centro'));
//$this->set('categorias', $this->User->find('all',array('fields'=>array('group_id','cod_cliente','nombre','apellidos','dni','id'),'conditions'=>array('User.cod_centro'=>$this->Session->read('Auth.User.cod_centro')))));
}
$this->set('categorias', $this->Paginator->paginate());
$this->set('title_for_layout', __('Listado de usuarios')." - ".__('Administración'));
}
public $presetVars = array(
array('field' => 'apellidos', 'type' => 'value'),
array('field' => 'dni', 'type' => 'value'),);
public $actsAs = array('Containable','Search.Searchable','Acl' => array('type' => 'requester'));
public $filterArgs = array(
array('name' => 'apellidos', 'type' => 'query', 'method' => 'filterApellidos'),
array('name' => 'dni', 'type' => 'query', 'method' => 'filterDni'),
);
and here are also the functions:
public function filterApellidos($data, $field = null) {
if (empty($data['apellidos'])) {
return array();
}
$apellidosField = '%' . $data['apellidos'] . '%';
return array(
'OR' => array(
$this->alias . '.apellidos LIKE' => $apellidosField,
));
}
public function filterDni($data, $field = null) {
if (empty($data['dni'])) {
return array();
}
$dniField = '%' . $data['dni'] . '%';
return array(
'OR' => array(
$this->alias . '.dni LIKE' => $dniField,
));
}
// Built a list of search options (unless you have this list somewhere else)
public function __construct($id = false, $table = null, $ds = null) {
$this->statuses = array(
'' => __('All', true),
0 => __('Bid', true),
1 => __('Cancelled', true),
2 => __('Approved', true),
3 => __('On Setup', true),
4 => __('Field', true),
5 => __('Closed', true),
6 => __('Other', true));
parent::__construct($id, $table, $ds);
}
Finally, in the View I have this:
<div><?php
echo $this->Form->create('Usuario', array(
'url' => array_merge(array('action' => 'index'), $this->params['pass'])
));
echo $this->Form->input('apellidos', array('div' => false, 'empty' => true)); // empty creates blank option.
echo $this->Form->input('dni', array('div' => false, 'empty' => true));
echo $this->Form->submit(__('Search', true), array('div' => false));
echo $this->Form->end();
?>
</div>
Could you tell me what I'm doing wrong, please? Thanks a lot!!
Belén
I've got the following models:
Run->hasMany ActualResult
ActualResult belongs to Status
When I view an ActualResult, Cake gets the corresponding Status without straight out of the box.
When I view a Run, I want to paginate the ActualResults. I have managed to get this to almost work with the following code in RunsController::view():
public function view($id = null) {
if (!$this->Run->exists($id)) {
throw new NotFoundException(__('Invalid run'));
}
$this->Run->contain ( 'Pack', 'User', 'Status');
$options = array('conditions' => array('Run.' . $this->Run->primaryKey => $id));
$run = $this->Run->find('first', $options);
$this->set('run', $run);
// Paginate the ActualResults
$this->paginate = array(
'contain' => array('Status'),
'order' => 'ActualResult.format',
'limit'=>5 ,
'conditions' => array('ActualResult.run_id' => $id)
);
$actualResults = $this->Paginator->paginate('ActualResult');
$this->set('actualResults',$actualResults);
}
The problem is that I get a warning:
Warning (512): Model "ActualResult" is not associated with model "Status" [CORE\Cake\Model\Behavior\ContainableBehavior.php, line 343
Something v. similar works for me in another model association, and as mentioned view() in ActualResultController works fine, so I am stumped.
Can anyone help?
Here are the model assocations:
In Run.php:
public $hasMany = array(
'ActualResult' => array(
'className' => 'actual_result',
'foreignKey' => 'run_id',
'dependent' => true,
'finderQuery' => 'SELECT ActualResult.*, Txn.name, Status.name FROM actual_results AS ActualResult, txns as Txn, codes AS Status WHERE ActualResult.run_id = {$__cakeID__$} and Txn.id = ActualResult.txn_id and (Status.code = ActualResult.status and Status.code_type = "ARS");'
)
);
In ActualResult.php
public $belongsTo = array(
'Run' => array(
'className' => 'Run',
'foreignKey' => 'run_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Status' => array(
'class`enter code here`Name' => 'Code',
'foreignKey' => 'status',
'conditions' => 'code_type = "ARS"',
'fields' => '',
'order' => ''
)
);
I've tried every simple cakedc search setup, and followed code samples from previous posts on this but it just won't seem to cooperate for me. I'm not sure, but there doesn't seem to be any search query generated with the search string, judging from a query log I have running on my database.
When I try to search, from /books/search, I get no results on a title I know is in the database and the URL changes to /books/index/title:sweet (I'm not sure if that is relevant).
Any help would be much appreciated.
Model
public $actsAs = array('Search.Searchable');
public $primaryKey = 'isbn13';
public $hasMany = array(
'Contributor' => array (
'className' => 'Contributor',
'foreignKey' => 'isbn13'
),
'Override' => array (
'className' => 'Override',
'foreignKey' => 'isbn13'
)
);
public $filterArgs = array(
'title' => array('type' => 'query', 'method' => 'filterTitle'),
'main_desc' => array('type' => 'value')
);
public function filterTitle($data, $field = null) {
if (empty($data['title'])) {
return array();
}
$titleField = '%' . $data['title'] . '%';
return array(
'OR' => array(
$this->alias . '.title LIKE' => $titleField,
));
}
Controller
class BooksController extends AppController {
public $helpers = array ('Html', 'Form');
public $paginate = array();
public $components = array('Search.Prg');
public $presetVars = true;
public function index() {
//get books
$this->set('books', $this->Book->find('all'));
//search
/* $this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Book->parseCriteria($this->Prg->parsedParams());
$this->set('books');
*/
}
public function search($books = NULL) {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Book->parseCriteria($this->passedArgs);
$this->set('books', $this->paginate());
}
View
<h1>Search Results</h1>
<?php
echo $this->Form->create('Book' , array(
'url' => array_merge(array('action' => 'search'), $this->params['pass'])
));
echo $this->Form->input('title', array('div' => false, 'empty' => true)); // empty creates blank option.
echo $this->Form->submit(__('Search', true), array('div' => false));
echo $this->Form->end();
Routes
Router::connect('/', array('controller' => 'books', 'action' => 'index'));
Router::connect('/index/*', array('controller' => 'books', 'action' => 'search'
));
Router::connect('/view/:url', array('controller' => 'books', 'action' => 'view', array('url' => '[\w\W]*')
));
Router::connect('/edit/:url', array('controller' => 'books', 'action' => 'edit', array('url' => '[\w\W]*')
));
Router::connect('/whatsnew/*', array('controller' => 'books', 'action' => 'whatsnew'
));
Router::connect('/search/*', array('controller' => 'books', 'action' => 'search'
));
I've renamed the search-master folder to Search and put it in my plugins directory and In my bootstrap.php I've loaded the plugin
CakePlugin::load('Search');
Fixed! Needed
$this->set('books', $this->paginate($this->Book->parseCriteria($this->passedArgs)));'
instead of
$this->set('books', $this->paginate());'
in the controller. Not sure why though..
How can I keep the same checkboxes checked after submit? All the other input fields on the form automatically keeps the values. I thought this would also go for checkboxes, but nope.
echo $this->Form->input('type_id', array(
'multiple' => 'checkbox',
'options' => array(
'1' => 'Til salgs',
'2' => 'Ønskes kjøpt',
'3' => 'Gis bort'
),
'div' => false,
'label' => false
));
I believe this can be done in the controller, but how?
Edit:
Since I posted this question I've changed to CakeDcs Search plugin, because I've gotten this to work with that before. Still... I can't get it to work this time.
Adding model and controller code:
AppController
public $components = array('DebugKit.Toolbar',
'Session',
'Auth' => array(
'loginAction' => '/',
'loginRedirect' => '/login',
'logoutRedirect' => '/',
'authError' => 'Du må logge inn for å vise denne siden.',
'authorize' => array('Controller'),
),
'Search.Prg'
);
public $presetVars = true; //Same as in model filterArgs(). For Search-plugin.
AdsController
public function view() {
$this->set('title_for_layout', 'Localtrade Norway');
$this->set('show_searchbar', true); //Shows searchbar div in view
$this->log($this->request->data, 'debug');
//Setting users home commune as default filter when the form is not submitted.
$default_filter = array(
'Ad.commune_id' => $this->Auth->user('User.commune_id')
);
$this->Prg->commonProcess(); //Search-plugin
$this->paginate = array(
'conditions' => array_merge($default_filter, $this->Ad->parseCriteria($this->passedArgs)), //If Ad.commune_id is empty in second array, then the first will be used.
'fields' => $this->Ad->setFields(),
'limit' => 3
);
$this->set('res', $this->paginate());
}
Model
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'search_field' => array('type' => 'query', 'method' => 'filterSearchField'),
'commune_id' => array('type' => 'value'),
'type_id' => array('type' => 'int')
);
public function filterSearchField($data) {
if (empty($data['search_field'])) {
return array();
}
$str_filter = '%' . $data['search_field'] . '%';
return array(
'OR' => array(
$this->alias . '.title LIKE' => $str_filter,
$this->alias . '.description LIKE' => $str_filter,
)
);
}
/**
* Sets the fields which will be returned by the search.
*
* #access public
* #return array Database table fields
* #author Morten Flydahl
*
*/
public function setFields() {
return array(
'Ad.id',
'Ad.title',
'Ad.description',
'Ad.price',
'Ad.modified',
'User.id',
'User.first_name',
'User.middle_name',
'User.last_name',
'User.link',
'User.picture_url',
'Commune.name',
'Type.id',
'Type.name'
);
}
You have to set manually the selected option of the input, as an array with "keys = values = intval(checkbox id)"
I cannot explain why this format, but this is the only way I get it to work.
Here is my code:
echo $this->Form->create('User');
// Read the submitted value
$selected = $this->Form->value('User.Albums');
// Formats the value
if (empty($selected)) {
$selected = array(); // avoid mess
} else {
$selected = array_map('intval', $selected);
$selected = array_combine ($selected, $selected);
}
// Renders the checkboxes
echo $this->Form->input('Albums',array(
'type' => 'select',
'multiple' => 'checkbox',
'options' => $albums, // array ( (int)id => string(label), ... )
'selected' => $selected, // array ( (int)id => (int)id, ... )
));
Hope this helps.
++
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 :)
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
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, ));
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'));
}
}