Архитектура баз данных EAV(Enity-Attribute-Value, Сущность-Атрибут-Значение)
При помощи композера устанавливаем расширение
php composer.phar require --prefer-dist "mirocow/yii2-eav" "*"
далее выполняем миграции
php ./yii migrate/up -p=@mirocow/eav/migrations
добавляем настройки сообщений расширения в основной конфиг
'i18n' => [
'translations' => [
'app*' => [
'class' => 'yii\i18n\PhpMessageSource',
//'basePath' => '@app/messages',
//'sourceLanguage' => 'en-US',
'fileMap' => [
'app' => 'app.php',
'app/error' => 'error.php',
],
],
'eav' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@mirocow/eav/messages',
],
],
]
добавляем в конфиг модуль
$modules = [
...,
'eav' => [
'class' => 'mirocow\eav\Module',
],
];
Добавляем в модель поведение, которое расширяет ее возможности методами данного расширения
.........
/**
* create_time, update_time to now()
* crate_user_id, update_user_id to current login user id
*/
public function behaviors()
{
return [
'eav' => [
'class' => \mirocow\eav\EavBehavior::className(),
// это модель для таблицы object_attribute_value
'valueClass' => \mirocow\eav\models\EavAttributeValue::className(),
]
];
}
.........
в эту же модель добавляем
/**
* @return \yii\db\ActiveQuery
*/
public function getEavAttributes()
{
return \mirocow\eav\models\EavAttribute::find()
->joinWith('entity')
->where([
//'categoryId' => $this->categories[0]->id,
'entityModel' => $this::className()
]);
}
C моделью закончили.
$attr = new mirocow\eav\models\EavAttribute();
$attr->attributes = [
'entityId' => 1, // Category ID
'typeId' => 1, // ID type from eav_attribute_type
'name' => 'packing', // service name field
'label' => 'Packing', // label text for form
'defaultValue' => '10 kg', // default value
'entityModel' => Product::className(), // work model
'required' => false // add rule "required field"
];
$attr->save();
$attr->attributes = [
'entityId' => 1, // Category ID
'typeId' => 1, // ID type from eav_attribute_type
'name' => 'color', // service name field
'label' => 'Color', // label text for form
'defaultValue' => 'white', // default value
'entityModel' => Product::className(), // work model
'required' => false // add rule "required field"
];
$attr->save();
Для использования админки достаточно будет добавить в представление следующий код
<?= \mirocow\eav\admin\widgets\Fields::widget([
'model' => $model,
'categoryId' => $model->id,
'entityName' => 'Продукт',
'entityModel' => 'app\models\Product', // ваша модель для которой подключено расширение
])?>
При рендере представления должна отобразиться админка в которой можно добавлять атрибуты и редактировать их. Добавляем несколько атрибутов в админке, они уже будут присутствовать в вашей модели и нужно прописать правила валидации для них
public function rules()
{
return [
[['name'], 'string', 'max' => 255], // Product field
[['c1'], 'required'], // Attribute field
[['c1'], 'string', 'max' => 255], // Attribute field
[['c2'], 'required'], // Attribute field
[['c2'], 'string', 'max' => 255], // Attribute field
];
}
тут c1 и c2 - поля добавленные через EAV, данные поля можно изменять так
$model = Product::find()->where(['id' => 1])->one();
$model->c1 = "blue";
$model->c2 = "red";
$model->save();
для редактирования этих полей в расширении присутствует специальный виджет
<?php
foreach($model->getEavAttributes()->all() as $attr){
echo $form->field($model, $attr->name, ['class' => '\mirocow\eav\widgets\ActiveField'])->eavInput();
}
?>
<?php
<?=$form->field($model,'с1', ['class' => '\mirocow\eav\widgets\ActiveField'])->eavInput(); ?>
?>
Для вывода этих атрибутов на карточке (товара/модуля/вашей модели) можно использовать следующий код
<table class="table">
<?php
foreach ($model->getEavAttributes()->all() as $attr) {
?>
<tr>
<td><?= $attr->type; ?></td>
<td>
<ul>
<?php
$attrValue = $model->renderEavAttr($attr, $model);
if ($attrValue[0]['value']) {
foreach ($attrValue as $attrValueItem) {
echo '<li>';
echo $attrValueItem['value'];
echo '</li>';
}
} else echo '---';
?>
</ul>
</td>
</tr>
<?php
}
?>
</table>
Для использования этого кода, добавьте в вашу модель следующий метод, он возвращает массив с EAV атрибутами
/**
* @param $attr
* @param null $model
* @return array
*
* Создает массив с EAV атрибутами
*/
function renderEavAttr($attr, $model = NULL)
{
$optionValues = $model[$attr->name]->value; // Список выбранных значений
$allOptionValues = $attr->getEavOptions()->asArray()->all(); // Список всех возможных значений
// Если массив - все возможные значения
unset($out);
if (is_array($allOptionValues)) {
$out = [];
foreach ($allOptionValues as $allOtionValuesItem) {
// Если список доступных значений - массив
if (is_array($optionValues)) {
foreach ($optionValues as $optionValuesItem) {
if ($optionValuesItem == $allOtionValuesItem["id"]) {
$out[] = $allOtionValuesItem;
}
}
} else {
if ($optionValues == $allOtionValuesItem["id"]) {
$out[] = $allOtionValuesItem;
}
}
}
}
if ($out) {
return $out;
} else return [0 => [
'id' => 0,
'attributeId' => 0,
'value' => $model[$attr->name]['value'],
'defaultOptionId' => 0,
'order' => 0,
]];
}
Тут описаны основные шаги для начала работы с модулем, если что-то не получается велком в icq 124011, постараюсь помочь.