首页 > 解决方案 > CakePHP 3.x 具有 11 种不同模型的搜索表单

问题描述

我在 CakePHP 3.5.13 中有一个应用程序。该应用程序连接到一个遗留数据库——也就是说,它没有根据 Cake 的命名约定编写。

我已经烘焙了生成一些类的应用Table程序Entity

应用程序的一部分允许用户执行搜索。我想使用表单助手,但不确定如何命名/配置事物:

搜索表单所在的模板文件有 11 个文本输入。这些中的每一个都与存储在数据库中的数据有关。为简洁起见,我将考虑前 3 个字段。这些与Table类相关联:

打开表单标签时,我做了以下事情:

<?php echo $this->Form->create(null, [
'url' => ['controller' => 'Front', 'action' => 'search'] ]); ?>

我作为第一个参数传递的原因null是因为我不知道我是否应该使用 an 的实例Entity(如docs中所述),但不确定是哪一个,因为有 11 个输入它们与不同的Table类相关联。所以我相信null在这里是正确的-请有人澄清一下吗?

我也不确定如何命名我的输入。例如输入搜索“CAS Number”需要在数据库字段上进行搜索cas.value。那么我会这样命名输入吗?

echo $this->Form->control('cas.value' ... );

我希望能够根据适当模型中的规则验证每个字段。因为有 11 个不同的字段,并且表单既不是“添加”(SQL INSERT)也不是“编辑”(SQL UPDATE)函数,我无法按照 Cake 文档来理解我应该如何编写代码。

总之,我要做的是构造一个 HTML 表单——使用 Cake 的表单助手语法——有 11 个字段,所有这些字段都与适当的模型相关联。我希望能够根据这些模型的规则验证字段。我怎样才能做到这一点?我已经对其进行了研究,但看不到任何这样做的示例-大多数集中在插入/更新数据上。我还查看了无模式表单,但认为这是不对的,因为在这种情况下,我确实有用于搜索数据的模型。

目前,我只是将表单编写为普通 HTML,并且可以访问FrontController::search()通过$this->request->data(). 虽然这可行,但我认为这是一个坏主意,因为我必须以某种方式运行验证方法,并且可能会导致重新填充表单或稍后使用 ORM 出现问题。我在这里可能错了,但我正在寻找一个使用 Cake 约定的解决方案,特别关注在这种情况下正确使用 Form Helper。

标签: cakephpcakephp-3.0

解决方案


我实际上不明白为什么你必须验证搜索(我认为如果由于某种原因搜索输入之一不正确,那么查询将简单地返回零记录)但我想你有你的理由所以这里是如何做。无论如何,这甚至适用于保存实体,所以:

使用命名约定

首先,按照此处此处的说明,为您的控件使用 g cake 命名约定

即使您的数据库命名不遵循蛋糕标准,它也可以工作。

创建验证规则

然后在每个表中创建验证集。您可以为不同的用途(保存、更新、搜索)创建不同的验证(参见此处)。在您的情况下,您想为搜索创建一个集合。

因此,在您的表中(在每个表中!)您可以创建一个名为validationSearch

public function validationSearch($validator)
{
    $validator
        ->add('title', 'notEmpty', [
            'rule' => 'notEmpty',
            'message' => __('You need to provide a title'),
        ]);
    return $validator;
}

修补实体

那么在你FrontController身上你可以做到

$this->loadModel('Substances');
$substance = $this->Substances->newEntity(
    $this->request->getData(),
    [
        'validate' => 'search', // tells cake to use validateSearch
                                // for Substances Table
        'associated' => [
            'Cas' => [
                'validate' => 'search', // you want to use validateSearch
                                        // even for this table
            ],
            'Ecs'=> [
                'validate' => 'search', // and for this table, too
            ],
            // list of other related tables here
            // you can nest the array if you have
            // nested relationships
        ]
    ]
);

这将创建一个包含您的数据的实体,但最重要的是它将检查验证问题并将错误存储在$substance实体中。

$this->set('substance', $substance );

以上将您新创建的实体传递给表单

创建表单

最后在视图中

<?php echo $this->Form->create($substance , [ /*... */ ]); ?>

所以表单知道实体、要应用的验证规则和要显示的验证错误

创建控件

假设您有一个“主”表,这意味着所有其他表都与此相关。假设它是物质。所以遵守约定。

<?= $this->Form->control('name', ['label' => 'Substance name') ?> 
//                        ^ No need to prepend the table here
<?= $this->Form->control('cas.number', ['label' => 'Cas number') ?>
<?= $this->Form->control('ecs.number', ['label' => 'Ecs number') ?>

使用插件

并考虑使用 FriendsOfCake/search 插件。有这么多需要检查的领域,它将简化您的生活


推荐阅读