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.
++
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 want a simple search feature that can search the current selected results on the model's index page. I have created a model Search which has no actual table:
class Search extends AppModel {
protected $_schema = array(
'search_term' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
'model' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
);
public $useTable = false;
public $validate = array(
'search_term' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Please enter a search term'
),
'between' => array(
'rule' => array('between',3,30),
'message' => 'Please enter a search term greater than 3 characters.'
)
)
);
}
In any index.ctp view I have this with a hidden input field with the model's name:
echo $this->Form->create('Search, array('action' => 'search'));
echo $this->Form->input('search_term', array('label'=> 'Search'));
echo $this->Form->input('model', array('type'=> 'hidden', 'value'=>$this->params['controller']));
echo $this->Form->end(__('Submit'));
In the SearchesController:
public function search() {
$conditions = null;
if( $this->request->is('post') ) {
$searchModel = $this->request->data[$this->modelClass]['model'];
...
$this->{$this->modelClass}->useTable = Inflector::tableize($searchModel);
...
$this->paginate = array('conditions'=>array($groups,'OR' => $conditions));
$this->set($searchModel, $this->paginate());
$this->render("/$searchModel/index");
}
Problem is paginate is returning an array with the model labelled as 'Search' (understandably because of the useTable call) and not say Groups or Users, the model's being searched. Any way to relabel the array returned from paginate to the model being searched ? The alternative is to modify all the index.ctp files or create a results.ctp for each model.
I wouldn’t create another model merely for searching; it’s a hack and not extendable.
In the past, I’ve just used parameters (usually in the query string) to alter the conditions array (whether it’s a normal find operation of a paginate operation). An example:
<?php
class ItemsController extends AppController {
public function index() {
$conditions = array();
if (isset($this->request->query['search'])) {
$conditions['Item.title'] = $this->request->query['search'];
}
$items = $this->Item->find('all', array(
'conditions' => $conditions
));
$this->set(compact('items'));
}
}
Hopefully the above demonstrates this approach.
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..
I have a working example of Auth set up with Users & Groups, based on the cookbook tutorial. I have an additional Locations table, which is associated with my Groups.
Location hasMany Group. Group belongsTo Locations. In 2.2 I think I should be able to get location data back for a User, but am not able to.
// App controller
public function beforeFilter() {
$this->Auth->authenticate = array(
'all' => array (
'scope' => array('User.status' => 1)
),
'Form' => array(
'contain' => array('Group', 'Location'),
'fields' => array('Location.name')
)
);
The above code only works if I create a direct association between User and Location. Is it possible to use contain here with a Group to Location association?
Problem of BaseAuthenticate is how it returns user info: return $result[$model];.
So when I need contains I'm using alternative component placed in app/Controller/Auth:
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class FormAndContainableAuthenticate extends FormAuthenticate {
protected function _findUser($username, $password) {
if (empty($this->settings['contain'])) { //< deafult
$userData = parent::_findUser($username, $password);
} else { //< with contains
$userModel = $this->settings['userModel'];
list($plugin, $model) = pluginSplit($userModel);
$fields = $this->settings['fields'];
$conditions = array(
$model . '.' . $fields['username'] => $username,
$model . '.' . $fields['password'] => $this->_password($password),
);
if (!empty($this->settings['scope'])) {
$conditions = array_merge($conditions, $this->settings['scope']);
}
$modelObj = ClassRegistry::init($userModel);
$modelObj->contain($this->settings['contain']);
$result = $modelObj->find('first', array(
'conditions' => $conditions
));
if (empty($result) || empty($result[$model])) {
return false;
}
foreach($result as $modelName => $modelData) {
if ($modelName !== $model) {
$result[$model][$modelName] = $modelData;
}
}
$userData = $result[$model];
}
// remove dangerous fields like password
unset($userData[$this->settings['fields']['password']]);
if (!empty($this->settings['exclude'])) {
foreach ($this->settings['exclude'] as $fieldName) {
unset($userData[$fieldName]);
}
}
return $userData;
}
}
As you can see - it uses parent Component when no contains provided.
Also some bonus: you can provide a set of fields to remove from resulting array. Just pass field names via 'exclude' key
How to use Component:
public $components = array(
'Auth' => array(
'authenticate' => array(
'FormAndContainable' => array(
'fields' => array(
'username' => 'username',
'password' => 'password',
),
'userModel' => 'Staff',
'contain' => array('StaffPermission'),
'exclude' => array('plain_password')
)
),
),
);
If User is not linked to Location, but Group is, you should try this:
'contain' => array('Group' => array('Location')),
I am using the search plugin on https://github.com/cakedc/search. I am trying to search for records using the ID field only, that is if i type in 1 on my form input it must show a record with user ID 1. The challenge that i am having now is when i specify that the input should be the id field, the input field for the search functionality disappears on my index view, strange thing is when i specify a different field name the input field shows.
Below is my code for my Model
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'id' => array('type' => 'like', 'field' => 'ItSupportRequest.id'),
);
public function findByTags($data = array()) {
$this->Tagged->Behaviors->attach('Containable', array('autoFields' => false));
$this->Tagged->Behaviors->attach('Search.Searchable');
$query = $this->Tagged->getQuery('all', array(
'conditions' => array('Tag.name' => $data['tags']),
'fields' => array('foreign_key'),
'contain' => array('Tag')
));
return $query;
}
public function orConditions($data = array()) {
$filter = $data['filter'];
$cond = array(
'OR' => array(
$this->alias . '.id LIKE' => '%' . $filter . '%',
));
return $cond;
}
and here is my controller code.
public $components = array('Search.Prg');
public $presetVars = true; // using the model configuration
public function find() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->ItSupportRequest->parseCriteria($this->passedArgs);
$this->set('articles', $this->paginate());
}
and in my index.ctp file i have this code.
<?php
echo $this->Form->create('ItSupportRequest', array(
'url' => array_merge(array('action' => 'find'), $this->params['pass'])
));
echo $this->Form->label('Query ID:') . "<br/>";
echo $this->Form->input('name', array('div' => false, 'label' => false));
echo $this->Form->submit(__('Search'), array('div' => false));
echo $this->Form->end();
?>
Thanks in advance.
You should not call it id as id will be hidden (because cake assumes this is a primary key here).
Either name it something else or manually overwrite this behavior using
$this->Form->input('id', array('type' => 'text'));
But I would go with sth like "search" and
$this->Form->input('search', array('placeholder' => 'ID to look for'));
and
public $filterArgs = array(
'search' => array('type' => 'like', 'field' => 'ItSupportRequest.id'),
);