MongoDb расширения для Yii 2 does not provide any special way to work with embedded documents (sub-documents). Для этого вам нужно сначала обработать пользовательские проверки. Вы можете попробовать следующий подход: Общая картина является первым построить custom validator, скажем, \ Common \ валидаторы \ EmbedDocValidator.php
namespace common\validators;
use yii\validators\Validator;
class EmbedDocValidator extends Validator
{
public $scenario;
public $model;
/**
* Validates a single attribute.
* Child classes must implement this method to provide the actual validation logic.
*
* @param \yii\mongodb\ActiveRecord $object the data object to be validated
* @param string $attribute the name of the attribute to be validated.
*/
public function validateAttribute($object, $attribute)
{
$attr = $object->{$attribute};
if (is_array($attr)) {
$model = new $this->model;
if($this->scenario){
$model->scenario = $this->scenario;
}
$model->attributes = $attr;
if (!$model->validate()) {
foreach ($model->getErrors() as $errorAttr) {
foreach ($errorAttr as $value) {
$this->addError($object, $attribute, $value);
}
}
}
} else {
$this->addError($object, $attribute, 'should be an array');
}
}
}
и модель для встроенного документа \ общие \ модели \ Preferences.php
namespace common\models;
use yii\base\Model;
class Preferences extends Model
{
/**
* @var string $lang
*/
public $lang;
/**
* @var string $currency
*/
public $currency;
public function rules()
{
return [
[['lang', 'currency'], 'required'],
];
}
}
И setup the validator в модели верхнего уровня в общих \ модели \ User.php:
public function rules()
{
return [
[['preferences', 'name'], 'required'],
['preferences', 'common\validators\EmbedDocValidator', 'scenario' => 'user','model'=>'\common\models\Preferences'],
];
}
The general recommendation является avoiding use of embedded documents перемещая их атрибуты на верхнем уровне документа. Например: вместо
{
name: 'Bob',
surnames: {
'first': 'Foo',
'second': 'Bar'
},
age: 27,
preferences: {
lang: 'en',
currency: 'EUR'
}
}
использование следующей структуры:
{
name: 'Bob',
surnames_first: 'Foo',
surnames_second: 'Bar'
age: 27,
preferences_lang: 'en',
preferences_currency: 'EUR'
}
который затем можно объявить как ActiveRecord
класса путем расширения YII \ MongoDB \ ActiveRecord и реализации методов collectionName
и 'attributes'
:
use yii\mongodb\ActiveRecord;
class User extends ActiveRecord
{
/**
* @return string the name of the index associated with this ActiveRecord class.
*/
public static function collectionName()
{
return 'user';
}
/**
* @return array list of attribute names.
*/
public function attributes()
{
return ['_id', 'name', 'surnames_first', 'surnames_second', 'age', 'preferences_lang', 'preferences_currency'];
}
}
Извините, что не ответив здесь. С вашего ответа я связался с Yii разработчиками по этому вопросу, давайте посмотрим, к чему это приведет нас: https://github.com/yiisoft/yii2/issues/4899 – alexandernst