Как создать пару keyValue (поле отображения) путем объединения/наличия двух полей в CakePHP 3?

Мне нужна помощь в получении двух значений (для удобного для человека раскрывающегося списка) в паре ключ-значение, используя find или получить или что-то еще. Мне нужна помощь с простейшим способом сделать это в CakePHP.

Здесь моя попытка:

  • в моем контроллере

      $users = $this->LocationsUser->Users->find('list', [
        'limit' => 1,
        'keyField' => 'id',
        'valueField' => ['first_name', 'last_name']
      ])->where(['id' => $id]);
    
  • На мой взгляд

      echo $this->Form->input('user_id', [
            'options' => $users,
            'type' => 'select',
            'multiple' => false,
          ]);
    
  • Результат в моем раскрывающемся списке:

    <option value="10">Fabian;Pankiers</option>
    

См. Мне нужен результат без точки с запятой ";" . Теперь я могу использовать javascript для удаления точки с запятой, но затем это излишне. Есть ли простой способ достичь этого в CakePHP 3?

Ответ 1

Существуют различные способы решения этой проблемы, здесь три из них:

Используйте обратный вызов для valueField

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

$query = $this->LocationsUser->Users
    ->find('list', [
        'valueField' => function ($row) {
            return $row['first_name'] . ' ' . $row['last_name'];
        }
    ])
    ->where(['id' => $id]);

См. также

Форматирование результатов

Использовать форматировщик результатов, который сшивает значения вместе, что и искатель list делает внутренне тоже, и в основном то же, что и в приведенном выше примере, только сложнее.

$query = $this->LocationsUser->Users
    ->find()
    ->select(['id', 'first_name', 'last_name'])
    ->formatResults(function($results) {
        /* @var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
        return $results->combine(
            'id',
            function($row) {
                return $row['first_name'] . ' ' . $row['last_name'];
            }
        );
    })
    ->where(['id' => $id]);

В сочетании с виртуальными свойствами

Вы также можете использовать (повторно) использовать виртуальные свойства здесь, например, имя свойства full_name, определенное в классе сущности User:

protected function _getFullName()
{
    return $this->_properties['first_name'] . ' ' . $this->_properties['last_name'];
}

Вы можете просто вернуть это в форматтере вместо того, чтобы вручную комбинировать два поля снова:

function($row) {
    return $row['full_name'];
}

То же самое можно сделать в примере valueField.

См. также

Вычисляемые поля

Добавьте вычисленное поле и используйте его для опции valueField

$query = $this->LocationsUser->Users
    ->find('list', [
        'keyField' => 'id',
        'valueField' => 'concatenated'
    ]);
$query
    ->select([
        'id',
        'concatenated' => $query->func()->concat([
            'first_name' => 'literal',
            ' ',
            'last_name' => 'literal'
        ])
    ])
    ->where(['id' => $id]);

См. также

Переопределить поиск списка

Если вы хотите, чтобы ваш пользовательский список всегда применялся, вы можете переопределить finder list в классе таблиц Users.

use Cake\ORM\Query;

// ...

public function findList(Query $query, array $options)
{
    return $query
        ->find()
        ->select(['id', 'first_name', 'last_name'])
        // etc ...
        ;
}

Таким образом, вы можете продолжать использовать find('list').

См. также

Ответ 2

Простое и быстрое решение, работало как шарм (CakePHP 3.2.6):

$users = $this->LocationsUser->Users->find('list', [
    'limit' => 1,
    'keyField' => 'id',
    'valueField' => function ($e) {
            return $e->get('first_name'). ' ' . $e->get('last_name');
        }
])->where(['id' => $id]);