gpt4 book ai didi

mongodb - MongoDB 和 Yii2 中的子文档

转载 作者:可可西里 更新时间:2023-11-01 10:43:13 25 4
gpt4 key购买 nike

如果我愿意使用子文档,我应该如何声明从 ActiveRecord 扩展的类(模型)的 attributes 公共(public)函数?

以这个简单的 MongoDB 结构为例:

_id: 'a34tfsert89w734y0tas9dgtuwn034t3',
name: 'Bob',
surnames: {
'first': 'Foo',
'second': 'Bar'
},
age: 27,
preferences: {
lang: 'en',
currency: 'EUR'
}

我的 attributes 函数应该是什么样子的?

public function attributes() {
return [
'_id',
'name',
'surnames',
'surnames.first', <--- like this?
.....
]
}

最佳答案

Yii 2 的 MongoDb 扩展 does not provide any special way to work with embedded documents (sub-documents) 。为此,您需要首先处理自定义验证。您可以尝试以下方法:一般模式是首先构建一个 custom validator ,比如\common\validators\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');
}
}

}

和嵌入文档\common\models\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 在顶层模型中在 common\models\User.php 中:

public function rules()
{
return [
[['preferences', 'name'], 'required'],
['preferences', 'common\validators\EmbedDocValidator', 'scenario' => 'user','model'=>'\common\models\Preferences'],
];
}

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'
}

然后您可以通过扩展 yii\mongodb\ActiveRecord 并实现 collectionName' 属性将其声明为 ActiveRecord 类' 方法:

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'];
}
}

关于mongodb - MongoDB 和 Yii2 中的子文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29462002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com