Yii2 - Проверка вложенных объектов
Вот вопрос о теме, о которой я размышлял некоторое время.
В Yii2 рекомендуется, как правило, создавать модели форм для ваших запросов. Правила добавляются к этим моделям для проверки ввода. Примером может служить EntryForm в руководстве Yii2
<?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'],
];
}
}
Моя проблема в том, когда у нас есть вложенные объекты. Примером может служить форма для создания Клиента с несколькими веткими. Если Клиент и филиал являются двумя отдельными моделями, но оба они представлены в одной форме, что является лучшим вариантом для проверки ввода из такой вложенной формы. Имейте в виду, что здесь вход вложен. Пример:
{
"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()
может быть извлечен для разделения класса validateStores()
, тогда вы также можете использовать 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;
}
}
}