CakePHP4-如何验证需要将数据保存到多个表中的表单
如果以前有人问过,我会道歉。我能找到的所有示例都是旧的或适用于CakePHP的旧版本,例如7年前 我在CakePHP4.1.6中有一个应用程序。数据库中的两个表分别称为CakePHP4-如何验证需要将数据保存到多个表中的表单,php,cakephp,cakephp-4.x,Php,Cakephp,Cakephp 4.x,如果以前有人问过,我会道歉。我能找到的所有示例都是旧的或适用于CakePHP的旧版本,例如7年前 我在CakePHP4.1.6中有一个应用程序。数据库中的两个表分别称为tbl_users和tbl_orgs(“orgs”在本例中表示“组织”) 当我添加一个组织时,我还希望创建一个用户,该用户是组织内的主要联系人。这涉及在提交表单时保存到tbl_组织和tbl_用户表 我遇到的问题是如何让表单在提交时运行tbl_用户和tbl_组织的验证规则 这就是我们的应用程序当前的结构: 在src/Controll
tbl_users
和tbl_orgs
(“orgs”在本例中表示“组织”)
当我添加一个组织时,我还希望创建一个用户,该用户是组织内的主要联系人。这涉及在提交表单时保存到tbl_组织
和tbl_用户
表
我遇到的问题是如何让表单在提交时运行tbl_用户
和tbl_组织
的验证规则
这就是我们的应用程序当前的结构:
在src/Controller/TblOrgsController.php
中有一个名为add()
的控制器方法。这是由bake
生成的,最初用于将新组织插入tbl_orgs
表中。在这一点上,它在tbl_用户方面没有做任何事情
,但它在保存新组织和运行适当的验证规则方面起了作用
一个验证规则是tbl_orgs
中的每个companyname
记录必须是唯一的。如果您尝试插入多个名称为“My company Limited”的公司,则会出现验证错误“此公司名称已存在”:
虽然上述适用于TblOrgs
我们在TblUsers
中还有一个buildRules()
,它在电子邮件
字段上应用类似的逻辑,以确保每个用户的所有电子邮件地址都是唯一的
在add()
控制器方法中,我们首先为TblOrgs
指定一个新的空实体:
// src/Controller/TblOrgsController.php
public function add()
{
$org = $this->TblOrgs->newEmptyEntity();
// ...
$this->set(compact('org'));
}
创建表单时,我们传递$org
:
// templates/TblOrgs/add.php
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->end() ?>
它还根据buildRules
中为TblOrgs
指定的规则工作。例如,如果我两次输入相同的公司名称,则会在行中显示相应的错误:
然后我尝试为TblUsers
引入字段。我在表单字段前面加了点符号,例如,这是为了对应tbl_用户。电子邮件输入字段:
<?= $this->Form->control('TblUser.email') ?>
在这种情况下,Tags
与Comments
是不同的模型,但是newEmtpyEntity()
对两者都适用。考虑到这一点,我将我的add()
方法改编为:
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
但这现在为TblUsers
提供了一个实体。看起来你可以有一个或另一个,但不能两者都有
这对我的用例不起作用的原因是,我可以运行TblOrgs
(但不能运行TblUsers
)的验证规则,反之亦然
您如何将其设置为运行两个模型的验证规则?表单可能需要将数据保存到多个表中,并且希望每个表的验证规则都能运行,这似乎不是一个不合理的要求。我从文档中得到的印象是这是可能的,但不清楚如何实现
作为参考,两个表之间存在适当的关系:
// src/Model/Table/TblOrgsTable.php
public function initialize(array $config): void
{
$this->hasMany('TblUsers', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
及
好的,这里有很多困惑需要澄清。:-)根据您所写的内容,我在这里的假设是,您试图使用一个表单来添加一个新组织,以及其中的第一个用户,然后可能稍后您将向该组织添加更多用户
首先,$this->TblOrgs->TblUsers
是您的用户表对象,因此当您使用
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
您正在做的是创建一个新的用户实体。事实上,您通过orgs表访问该表对象,并将其称为$org
,这并没有改变这一点。它不会神奇地创建一个包含空白用户实体的空白组织实体。但这里根本不需要实体结构,只需要空的组织实体。简单地回到:
$org = $this->TblOrgs->newEmptyEntity();
现在,在您的表单中,您将需要以下内容:
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->control('tbl_users.0.email') ?>
<?= $this->Form->end() ?>
该字段称为tbl_users.0。电子邮件,因为:
表名转换为小写下划线格式
这是一个从组织到用户的关系,所以它需要一个用户数组;我们必须为该数组提供一个数字索引,0是一个很好的起点。如果要同时添加第二个用户,则该字段应为tbl_users.1.电子邮件
注意:了解表单助手希望您使用何种格式创建字段名的一个好方法是从数据库(在本例中为组织及其用户)中读取一组现有记录,然后使用类似于debug($org)的方法转储该数据代码>。您将看到,$org
有一个名为tbl_users
的属性,它是一个数组,直接指向我上面描述的这个结构
通过这样设置字段,您应该能够将生成的数据直接修补到控制器中的$org
实体中,并将其保存,而无需任何其他工作。修补程序将创建整个结构,其中包含一个类为TblOrg
的实体,以及一个tbl\u users
属性,该属性是一个数组,其中包含一个类为TblUser
的实体,并且将对这两个实体进行验证。(至少应该是这样;您可以使用上面提到的debug($org);
进行确认。)当您保存此实体时,它将首先保存TblOrg
实体,然后在保存之前将新ID添加到TblUser
实体中,以及检查两者的规则,并确保如果不能全部保存,则不会将任何内容保存到数据库中。只需一次save
呼叫,所有这些都会自动发生
如果您的关联是hasOne或belongsTo关系(例如,如果您正在添加新的
// src/Model/Table/TblUsersTable.php
public function initialize(array $config): void
{
$this->belongsTo('TblOrgs', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
$org = $this->TblOrgs->newEmptyEntity();
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->control('tbl_users.0.email') ?>
<?= $this->Form->end() ?>