Организация Detail View в Yii2

26 июл. 2019 г.

Всем привет! Сегодня речь пойдет о Yii2, а конкретно о Detail View Widget. Этот widget позволяет выводить информацию на странице. В общем-то все, кто работал с Yii наверняка о нем знают. Чаще всего виджет используется в разных админках и т.д.

В этой заметке хочу описать некоторые довольно простые идеи по организации кода Detail view. Документация по Detail View. В коде выглядит примерно так:

<?= echo DetailView::widget([
    'model' => $model,
    'attributes' => [
        'title',               // title attribute (in plain text)
        'description:html',    // description attribute in HTML
        [                      // the owner name of the model
            'label' => 'Owner',
            'value' => $model->owner->name,
        ],
        'created_at:datetime', // creation date formatted as datetime
    ],
]); ?>

При этом довольно часто нужно вывести не просто значение атрибута, а кнопку, атрибут связанной сущности, или что-нибудь не совсем обычное. Также, возможно, что нам нужно вывести такое значение в нескольких DetailView. В результате получаем, например, такой код, повторяющийся в разных view:

<?= DetailView::widget([
    'model' => $client,
    'attributes' => [
        [
            'label' => $client->clientMobileApp->getAttributeLabel('link_ios'),
            'value' => $client->clientMobileApp->link_ios
        ]
    ],
]) ?>

В этом случае хотелось бы инкапсулировать и вынести в отдельный класс повторяющийся код. Для этого добавим класс components/detailView/attributes/ModelAttribute, получающий на вход модель и название атрибута, возвращающий массив для отображения в DetailView. В Detail View Widget используются массивы вывода атрибутов. Соответственно, наш атрибут тоже на выходе должен представлять собой массив.

Класс ModelAttribute имеет один публичный метод toArray. Также имеет смысл добавить интерфейс AttributeInterface.

<?= DetailView::widget([
    'model' => $client,
    'attributes' => [
        (new ModelAttribute($client->clientMobileApp, 'link_ios'))->toArray(),
    ],
]) ?>
<?php

namespace app\components\detailView\attributes;

use yii\base\Model;

/**
 * Class ModelAppAttribute
 * @package app\modules\admin\components\detailView\attributes
 */
class ModelAttribute implements AttributeInterface
{
    private $model;
    private $attribute;
    private $format;

    /**
     * ModelAttribute constructor.
     * @param Model $model
     * @param $attribute
     * @param string $format
     */
    public function __construct(Model $model, $attribute, $format = 'text')
    {
        $this->model = $model;
        $this->attribute = $attribute;
        $this->format = $format;
    }

    /**
     * @param array $fields
     * @param array $expand
     * @param bool $recursive
     * @return array
     */
    public function toArray(array $fields = [], array $expand = [], $recursive = true)
    {
        $attribute = $this->attribute;

        return [
            'label' => $this->model->getAttributeLabel($attribute),
            'value' => $this->model->$attribute,
            'format' => $this->format
        ];
    }
}
<?php

namespace app\components\detailView\attributes;

/**
 * Interface AttributeInterface
 * @package app\modules\admin\components\detailView\attributes
 */
interface AttributeInterface
{
    /**
     * @return mixed
     */
    public function toArray();
}

ModelAttribute здесь взят лишь для примера. Кастомный атрибут можно использовать и для других целей. Например, для вывода графика, вывода кнопок, отображения списка файлов, более наглядного отображения чекбоксов(Yes/No), отображения списка связанных сущностей, подключения html шаблонов и др. В конечном итоге, делает Detail View Widget менее перегруженным и более упрядоченным.

На этом пока все, спасибо за внимание!

Теги: PHP, Yii2