Yii2 - 验证嵌套对象
Yii2 - Validating nested objects
这是一个关于我思考了一段时间的话题的问题。
在Yii2中,一般建议为你的请求创建Form Models。将规则添加到这些模型以验证输入。一个例子是 Yii2 指南中的 EntryForm
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class EntryForm extends Model
{
public $name;
public $email;
public function rules()
{
return [
[['name', 'email'], 'required'],
['email', 'email'],
];
}
}
我的问题是,当我们有嵌套对象时。一个示例是用于创建具有多个 Branches 的 Customer 的表单。如果 Customer 和 Branch 是两个独立的模型,但都以一种形式提交,那么从这种嵌套形式验证输入的最佳选择是什么.请记住,这里的输入是嵌套的。示例:
{
"name": "customer",
"vat_no": "12345678",
"time_zone": 277,
"category": 1,
"email": "customer@mycustomer.com",
"stores":[
{
"name": "store1",
"phone": 1234567
},
{
"name": "store2",
"phone": 2345678
}
]
}
对于简单的情况,您可以在表单模型中使用一个模型和自定义验证器:
public function rules() {
return [
// ...
['stores', 'validateStores'],
];
}
public function validateStores() {
$phoneValidator = new StringValidator(); // use real validators
$nameValidator = new StringValidator(); // use real validators
foreach ($this->stores as $store) {
if (!$phoneValidator->validate($store['phone'], $error)) {
$this->addError('stores', $error);
return; // stop on first error
}
if (!$nameValidator->validate($store['name'], $error)) {
$this->addError('stores', $error);
return; // end on first error
}
}
}
validateStores()
可能会被提取到单独的验证器 class,那么你也可以使用 EachValidator
而不是 foreach
.
对于更复杂的嵌套模型,您可能应该为商店创建单独的 StoreForm
模型(因此您将拥有嵌套表单模型),并在子项上调用 validate()
。
/**
* @var StoreForm[]
*/
public $stores;
public function rules() {
return [
// ...
['stores', 'validateStores'],
];
}
public function validateStores() {
foreach ($this->stores as $store) {
if (!$store->validate()) {
$this->addError('stores', 'Stores config is incorrect.');
return;
}
}
}
这是一个关于我思考了一段时间的话题的问题。
在Yii2中,一般建议为你的请求创建Form Models。将规则添加到这些模型以验证输入。一个例子是 Yii2 指南中的 EntryForm
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class EntryForm extends Model
{
public $name;
public $email;
public function rules()
{
return [
[['name', 'email'], 'required'],
['email', 'email'],
];
}
}
我的问题是,当我们有嵌套对象时。一个示例是用于创建具有多个 Branches 的 Customer 的表单。如果 Customer 和 Branch 是两个独立的模型,但都以一种形式提交,那么从这种嵌套形式验证输入的最佳选择是什么.请记住,这里的输入是嵌套的。示例:
{
"name": "customer",
"vat_no": "12345678",
"time_zone": 277,
"category": 1,
"email": "customer@mycustomer.com",
"stores":[
{
"name": "store1",
"phone": 1234567
},
{
"name": "store2",
"phone": 2345678
}
]
}
对于简单的情况,您可以在表单模型中使用一个模型和自定义验证器:
public function rules() {
return [
// ...
['stores', 'validateStores'],
];
}
public function validateStores() {
$phoneValidator = new StringValidator(); // use real validators
$nameValidator = new StringValidator(); // use real validators
foreach ($this->stores as $store) {
if (!$phoneValidator->validate($store['phone'], $error)) {
$this->addError('stores', $error);
return; // stop on first error
}
if (!$nameValidator->validate($store['name'], $error)) {
$this->addError('stores', $error);
return; // end on first error
}
}
}
validateStores()
可能会被提取到单独的验证器 class,那么你也可以使用 EachValidator
而不是 foreach
.
对于更复杂的嵌套模型,您可能应该为商店创建单独的 StoreForm
模型(因此您将拥有嵌套表单模型),并在子项上调用 validate()
。
/**
* @var StoreForm[]
*/
public $stores;
public function rules() {
return [
// ...
['stores', 'validateStores'],
];
}
public function validateStores() {
foreach ($this->stores as $store) {
if (!$store->validate()) {
$this->addError('stores', 'Stores config is incorrect.');
return;
}
}
}