cakephp find list
Asked Answered
U

6

13

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.

Usage answered 24/9, 2010 at 9:34 Comment(1)
P
24

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.

Petrel answered 24/9, 2010 at 9:41 Comment(0)
G
16

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

Genro answered 24/9, 2010 at 23:9 Comment(3)
virtualFields as said below is the way it should be done. keeps that controller skinny.Eakin
VirtualFields may not necessarily be the solution. The question is, do you want to change the structure of the returned data globally to accomodate one controller/action? If not, using Set::combine is probably a better solution. If you need full_name globally, add the virtual field.Genro
Please note that virtual fields can be defined on-the-fly.Irradiant
L
1

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

Latifundium answered 23/12, 2013 at 6:1 Comment(1)
It is OK to assign full_name to $displayField and do a find('list'), although, your solution also gives the same output.Forerun
S
0

+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/

Salvatoresalvay answered 25/9, 2010 at 17:38 Comment(1)
The link is broken and the answer doesn't quote anything from the article.Irradiant
C
0

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);
Cresol answered 7/12, 2015 at 23:37 Comment(0)
M
0

Update for CakePHP 4x.

// 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.

Marden answered 15/6, 2023 at 20:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.