JSON 数组作为 select 选项和空显示名称

JSON array as select options and null displayname

我无法正确填充多个 select。

  1. 即使我指定了 keyFieldvalueField,我得到的选项值是 JSON
  2. name 为空,不应为

示例:

<option value="0">{
    "id": 8263,
    "name": null,
    "sort": "1"
}</option>

clients MySQL table 列:id, name_en, name_fr...

Client实体:

protected $_virtual = [
            'name',
        ];

protected function _getName()
{
    if (Configure::read('wetkit.lang') == 'fr'){
        return $this->get('name_fr');
    } else {
        return $this->get('name_en');
    }
}

ClientsTable table:

$this->setDisplayField('name');

控制器:

//build query to highlight selected clients
$selected_clients = $this->Clients->find()
->select(['id' => 'id','name' => 'name_'.$this->lang,'sort'=>1])
->where(['id in' => $user_clients]);

$clients = $this->Clients->find()
->select(['id' => 'id','name' => 'name_'.$this->lang,'sort'=>2])
->where(['id not in' => $user_clients]);

$clients->unionAll($selected_clients)->epilog('order by sort asc, name asc');

SQL:

(
  SELECT 
    id AS `id`, 
    name_en AS `name`, 
    2 AS `sort` 
  FROM 
    clients Clients 
  WHERE 
    id not in (8263)
) 
UNION ALL 
  (
    SELECT 
      id AS `id`, 
      name_en AS `name`, 
      1 AS `sort` 
    FROM 
      clients Clients 
    WHERE 
      id in (8263)
  ) 
order by 
  sort asc, 
  name asc

在视图中:

<?= $this->Form->control('clients._ids', 
                ['options' => $clients, 
                'label'=>__('Client'), 
                'keyField' => 'id', 
                'valueField' => 'name',
                'values' => $user_clients]) ?>

解决方案:

这似乎有效。我确实必须找出合适的排序来反映 ORM 的字段名称(即 Client__name_en)。我还将其包装在一个组件中,并且可以使用其他模型在应用程序范围内使用。

//build query to highlight selected clients
$selected_clients = $this->Clients->find()
->select(['id','name_en','name_fr','sort'=>1])
->where(['id in' => $user_clients]);

$clients = $this->Clients->find()
->select(['id','name_en','name_fr','sort'=>2])
->where(['id not in' => $user_clients]);

$clients->unionAll($selected_clients)
->epilog('order by sort, Clients__name_'.$this->lang);

$clients = $clients->combine('id','name_'.$this->lang);

keyFieldvalueField选项属于list查找器,不构成控件。

$clients
    ->unionAll($selected_clients)
    ->find('list', [
        'keyField' => 'id', 
        'valueField' => 'name',
    ])
    // ...

看起来有点奇怪,但可以说是可以链接查找器。或者,您可以直接使用 Collection::combine(),这是使用 list 查找器时自动应用的内容:

'options' => $clients->combine('id', 'name'),
// ...

namenull,因为您没有 select 您的实体尝试查找的 name_enname_fr 字段。选择一个值作为 name 不会规避实体的访问器方法,当您尝试访问实体上的 name 字段时,它总是 运行,无论该字段的值是否存在.

访问器方法将接收可能存在的字段的值作为其第一个参数,因此您可以使用它,类似于:

protected function _getName($name)
{
    if ($name !== null) {
        return $name;
    }

    // ...
}

然而,这一切都有些挑剔且容易出错,最终实体行为绑定到应用程序状态对未来来说并不是一个好兆头。也许您应该试试 CakePHP 的内置翻译功能。

另见