【问题标题】:JSON array as select options and null displaynameJSON 数组作为选择选项和 null 显示名称
【发布时间】:2021-12-15 21:01:23
【问题描述】:

我无法正确填充多选。

  1. 即使我指定了 keyFieldvalueField,我还是将 JSON 作为选项值
  2. name 为空,不应为空

例子:

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

clientsMySQL 表列: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表:

$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);

【问题讨论】:

    标签: php cakephp cakephp-3.0


    【解决方案1】:

    keyFieldvalueField 选项属于 list 查找器,而不是表单控件。

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

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

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

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

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

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

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

    另见

    【讨论】:

    • 感谢您的提示!在我们的例子中,getName 实际上是一个虚拟字段。 IIRC,我的理解是有缺陷的,因为这些不能通过查找器使用,只能在查询后返回,即使它们被暴露。我想我可以通过弄清楚如何为我的排序添加一个字段,同时找到所有字段并进行联合来解决这个问题。
    • 还注意到,我的 getter 正在获取模型属性或字段,具体取决于应用程序中的当前语言...例如 name_en 或 name_fr,它们将存在。
    猜你喜欢
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2015-06-27
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多