Цепочка связей в поведении

Всё что касается построения API
Ответить
Аватара пользователя
webplus
Сообщения: 299
Зарегистрирован: 2012.02.24, 22:05

Цепочка связей в поведении

Сообщение webplus » 2018.03.22, 18:46

Здравствуйте!
Написал поведение для построения цепочек вложенностей, для метода POST работает, а для метода PATCH не точно работает. Для метода PATCH если не заполнены поля связей, то они же и остаются (- и это правильно для патча), но если вводится новое ИД связей то поля должны заново собираться, и в тех у которых нет значений должны быть равны NULL , но метод ПАТЧ null оставляет старым значением.
вот как выглядят связи:

Код: Выделить всё

  "data": {
    "code": "23ddf5527t1111411",
    "locality__id": null,
    "district__id": "d39c47e9-aef6-4acb-9122-bced6afde4d5",
    "region__id": null,
    "country__id": "7189a63c-d36f-4b81-8721-0b10d9392f0a",
    "parts_of_world__id": "85ef4763-5e79-42e7-b13b-03f7cc34b62b",
    "name": "fddf",
    "language": "en",
    "id": "5d96d46c-8aa5-4f0a-b127-6f970d4d5e6e"
  }
вот перечень полей связей

Код: Выделить всё

    "locality__id": null,
    "district__id": "d39c47e9-aef6-4acb-9122-bced6afde4d5",
    "region__id": null,
    "country__id": "7189a63c-d36f-4b81-8721-0b10d9392f0a",
    "parts_of_world__id": "85ef4763-5e79-42e7-b13b-03f7cc34b62b",
вот мое поведение:

Код: Выделить всё

class GeoAttributesBehavior extends Behavior
{
    public $rules;
    public $tableName;

    private $treeModels = [];
    private $treeModelsAttributes = [];
    private $__attr;


    public function init()
    {
        $this->treeModels = [
            1 => PartsOfWorld::className(),
            2 => Country::className(),
            3 => Region::className(),
            4 => District::className(),
            5 => Locality::className(),
            6 => Section::className()
        ];

        $this->treeModelsAttributes = [
            1 => 'parts_of_world__id',
            2 => 'country__id',
            3 => 'region__id',
            4 => 'district__id',
            5 => 'locality__id',
            6 => 'section__id'
        ];

        parent::init();
    }

    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate',
            ActiveRecord::EVENT_AFTER_UPDATE  => 'afterUpdate',
            ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert',
        ];
    }

    public function afterUpdate($event)
    {

    }

    public function beforeUpdate($event)
    {
        $params = Yii::$app->request->post();
        if (!empty($params['geo_level']) && !empty($params['geo_level__id'])) {
            if(UuidHelper::isValid($params['geo_level__id'])) {
                $this->clearAttributes($event);
                //$event = ($this->owner)::findOne($event->sender->id);
            }
        }
        $attributes = [];
        $valid_attribute = null;
        $count_values = 0;
        foreach ($this->rules[0] as $geoAttribute) {
            if (!empty($event->sender->{$geoAttribute})) {
                $count_values++;
                $valid_attribute = $geoAttribute;
            } else {
                $this->__attr[] = $geoAttribute;
                $attributes[$geoAttribute] = null;
            }
        }

        if ($count_values > 0) {
            $this->fieldsAttribute($event, $valid_attribute);
        }
    }

    public function beforeInsert($event)
    {
        $valid_attribute = null;
        foreach ($this->rules[0] as $geoAttribute) {
            if (!empty($event->sender->{$geoAttribute})) {
                $valid_attribute = $geoAttribute;
            } else {
                $this->__attr[] = $geoAttribute;
            }
        }
        $this->fieldsAttribute($event, $valid_attribute);
    }

    public function fieldsAttribute($event, $attribute)
    {
        if (!$attribute) {
            return false;
        }

        $level = array_search($attribute, $this->treeModelsAttributes);
        $findValue = $event->sender->{$this->treeModelsAttributes[$level]};

        if (!empty($findValue)) {
            $__model = $this->treeModels[$level]::findOne($findValue);
            foreach ($this->__attr as $attr) {
                $event->sender->{$attr} = (!empty($__model->{$attr})) ? $__model->{$attr} : null;
            }
            $event->sender->{$attribute} = $findValue;

        }
    }

    private function clearAttributes($event)
    {
        $Obj = $this->owner;
        //$level = array_search(($Obj::className()), $this->treeModels);
        $model = ($this->owner)::findOne($event->sender->id);
        $attributes = [];
        foreach ($this->treeModelsAttributes as $key => $att) {
            if (!empty($model->{$att})) {
                $attributes[$att] = null;
            }
        }
        //echo "\n<pre>" . print_r($attributes,1) . "</pre>";
        if (count($attributes)) {
            Yii::$app->db->createCommand()
                ->update($this->tableName, $attributes, ['id' => $event->sender->id])
                ->execute();
           // $event = ($this->owner)::findOne($event->sender->id);
        }
    }
}
Очистку свойств для ПАТЧА я делаю в методе clearAttributes()

Аватара пользователя
webplus
Сообщения: 299
Зарегистрирован: 2012.02.24, 22:05

Re: Цепочка связей в поведении

Сообщение webplus » 2018.03.23, 17:31

Проблему решил так:
в методе beforeUpdate

Код: Выделить всё

                $this->clearAttributes($event);
                $event->sender->refresh();
                $event->sender->{$geo_var} = $params['geo_level__id'];
помогло

Код: Выделить всё

$event->sender->refresh();

Ответить