Reputation: 38432
Hi I want to be able to generate a list using find so that I can use in select helper. but there is a problem. i want too fetch id,name(first + last). so how can I achieve it. I want first_name and last_name to be joined as name . How can I achieve it.
$this->User->find('all',array('fields' => array('first_name','last_name','id')));
I can't use model filters and callback Please suggest me how can I do it in controllers itself.
Upvotes: 13
Views: 17153
Reputation: 673
// Model/Entity/{entityName}.php
// "fname, lname, email" are my DB field names
protected function _getFullName()
{
return $this->_fields['fname'] . ' ' . $this->_fields['lname'];
}
protected function _getLabelDropdown()
{
return $this->_fields['fname'] . ' ' . $this->_fields['lname'] . ' (' . $this->_fields['email'] . ')';
}
...
// Model/Table/{tableName}.php
public function getUserList()
{
return $this->find('list', [
'keyField' => 'uuid',
'valueField' => function ($user) {
return $user->get('full_name'); // It's _getFullName()
// or
// return $user->get('label_dropdown'); // It's _getLabelDropdown()
}
])->where([
'is_delete' => 0,
'is_active' => 1,
]);
}
// Controller/{ControllerName}.php
public function add()
{
...
$this->set('user_list', $this->Users->getUserList());
...
}
// View
<?= $this->Form->control('role_uuid', [
'options' => $user_list,
'class' => 'form-select',
'id' => 'user_uuid',
'label' => __('Choose User'),
'default' => DEFAULT_USER
]); ?>
Read more: https://book.cakephp.org/4/en/orm/retrieving-data-and-resultsets.html#customize-key-value-output
Hope it help.
Upvotes: 0
Reputation: 5943
I think this can be done using the virtualFields
and displayField
properties in your model.
In your model, define a virtual field for the full name like this:
public $virtualFields = array(
'full_name' => 'CONCAT(User.first_name, " ", User.last_name)'
);
If you now set displayField to full_name you should be able to get a list of your users with the $this->User->find('list')
method which you can use without problems with the Form-helper.
public $displayField = 'full_name';
... or:
public $displayField = 'User.full_name';
The id is fetched automatically.
Upvotes: 24
Reputation: 103
In my case, Set::combine was the way to go, since I had to deal with concatenation of fields in associated models, like:
$bancos_enteros = $this->Financiacion->Banco->find('all', array(
'fields' => array('Empresa.codigo_contable','Empresa.nombre_corto', 'Banco.id'),
'order' => array('Empresa.codigo_contable' => 'asc'),
'recursive' => 1
));
$bancos = Set::combine(
$bancos_enteros,
'{n}.Banco.id',
array(
'{0} {1}',
'{n}.Empresa.codigo_contable',
'{n}.Empresa.nombre_corto'
)
);
returning
array(
(int) 14 => '57200002 Caixa',
(int) 15 => '57200003 Sabadell',
(int) 3 => '57200005 BBVA',
(int) 16 => '57200006 Deutsche Bank',
(int) 17 => '57200007 Popular',
(int) 18 => '57200009 March',
(int) 26 => '57200010 Bankinter',
(int) 4 => '57200011 Santander'
)
While
$this->Financiacion->Banco->Empresa->virtualFields = array(
'codigo_nombre' => 'CONCAT(Empresa.codigo_contable,Empresa.nombre_corto)'
);
$this->Financiacion->Banco->virtualFields['codigo_nombre'] = $this->Financiacion->Banco->Empresa->virtualFields['codigo_nombre'];
$bancos = $this->Financiacion->Banco->find('list', array(
'fields' => array('Banco.id','Banco.codigo_nombre'),
'order' => array('Banco.codigo_nombre' => 'asc'),
'recursive' => 1
)
);
returns a SQL error in a following query if I don't delete the virtual fields first:
unset($this->Financiacion->Banco->Empresa->virtualFields);
unset($this->Financiacion->Banco->virtualFields);
Upvotes: 0
Reputation: 2463
Another solution is to use Cake's Set::combine to build what you need...
$users = $this->User->find('all',array('fields' => array('first_name','last_name','id')));
$user_list = Set::combine($users, '{n}.User.id', array('{0} {1}', '{n}.User.first_name', '{n}.User.last_name'));
Result will look something like:
array(
[2] => 'First Last',
[5] => 'Bob Jones'
)
Here's the documentation link:
http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::combine
Upvotes: 16
Reputation: 350
To achieve this first go to the model and add this line
public $virtualFields = array('full_name' => 'CONCAT(first_name, " ", last_name)');
and then go to controller file just use the name "full_name" which you put in virtual fields
$this->User->find('all',array('fields' => array('full_name','id')));
It returns name with combined fields
Upvotes: 1
Reputation: 6721
+1 on Tim's answer, however, if you need an alternative, teknoid wrote a nice article about this a long time ago:
http://nuts-and-bolts-of-cakephp.com/2008/09/04/findlist-with-three-or-combined-fields/
Upvotes: 0