Details.php 5.26 KB
<?php

namespace backend\models;

use common\components\CustomVarDamp;
use Yii;
use backend\components\base\BaseActiveRecord;

/**
 * This is the model class for table "{{%details}}".
 *
 * @property string $ID
 * @property string $IMPORT_ID
 * @property string $BRAND
 * @property string $ARTICLE
 * @property string $FULL_ARTICLE
 * @property double $PRICE
 * @property string $DESCR
 * @property string $BOX
 * @property string $ADD_BOX
 * @property string $GROUP
 * @property string $timestamp
 */
class Details extends BaseActiveRecord
{
    /**
     *обязательные колонки
     */
    const KEY_COLUMN = ['IMPORT_ID', 'BRAND', 'ARTICLE'];

    /**
     * int - размер пакета запроса
     */
    const BATCH = 500;

    /**
     * @var bool - признак необходимости удалить префикс Артикула перед вставкой
     */
    public $delete_price = false;

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%details}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['BRAND', 'ARTICLE', 'PRICE', 'DESCR', 'BOX'], 'required'],
            //  [['IMPORT_ID', 'BOX', 'ADD_BOX'], 'integer'],
            [['PRICE'], 'number'],
            [['BOX'], 'integer'],
            [['timestamp'], 'safe'],
            [['BRAND', 'ARTICLE'], 'string', 'max' => 100],
            [['FULL_ARTICLE'], 'string', 'max' => 150],
            [['DESCR', 'GROUP'], 'string', 'max' => 200]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'ID' => Yii::t('app', 'ID'),
            'IMPORT_ID' => Yii::t('app', 'Import  ID'),
            'BRAND' => Yii::t('app', 'Brand'),
            'ARTICLE' => Yii::t('app', 'Article'),
            'FULL_ARTICLE' => Yii::t('app', 'Full  Article'),
            'PRICE' => Yii::t('app', 'Price'),
            'DESCR' => Yii::t('app', 'Descr'),
            'BOX' => Yii::t('app', 'Box'),
            'ADD_BOX' => Yii::t('app', 'Add  Box'),
            'GROUP' => Yii::t('app', 'Group'),
            'timestamp' => Yii::t('app', 'Timestamp'),
        ];
    }

    /**
     *удаление (если $delete_price установлен)б а затем вставка данных с апдейтом прямымыми запросоми SQL
     * @param $data - массив вставляемых данных, вставка будет прозводится пакетами размером указанным в константе BATCH
     * @param $importer_id - (int) - идентификатор поставщика у которого будет сперва удалены прайсы а потом вставлены из массива $data
     * @throws \yii\db\Exception
     */
    public function  ManualInsert($data, $importer_id)
    {
        if ($this->delete_price) {
            // запустим пакетное удаление всех прайсов поставщика
            do {
                $query = Yii::$app->db->createCommand()->delete(self::tableName(), "IMPORT_ID = {$importer_id}")->sql . ' Limit ' . $this::BATCH;
                $res = Yii::$app->db->createCommand($query)->execute();
            } while ($res);

        }

        $this->ManualInsertWithUpdate($data);
    }

    /**
     * вставка данных с апдейтом прямым запросом SQL
     * @param $data - массив вставляемых данный, вставка будет прозводится пакетами размером указанным в константе BATCH
     * @throws \yii\db\Exception
     */
    private function ManualInsertWithUpdate($data)
    {
        // \common\components\CustomVarDamp::dumpAndDie($data);
        $table_name = self::tableName();
        $keys_arr = array_keys($data[0]);
        // найдем те поля которые не являются ключами. Их нужно будет при дубляже апдейтить
        $fields_arr_to_update = array_diff($keys_arr, $this::KEY_COLUMN);

        $query_update = ' on duplicate key update ';
        foreach ($fields_arr_to_update as $field) {
            $query_update .= "[[{$field}]] = values([[{$field}]]),";
        }
        // удалим последнюю запятую
        $query_update = substr($query_update, 0, strlen($query_update) - 1);

        // запросы будем выполнять пакетами
        // размер пакета установлен в константе
        // разобъем массив на пакеты и будем их проходить
        $data = array_chunk($data, $this::BATCH);
        foreach ($data as $current_batch_array) {

            //воспользуемся пакетной вставкой от фреймворка
            $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql;
            // добавим фрагмент с апдейтом при дубляже
            $query = "{$query_insert} {$query_update}";
            // \common\components\CustomVarDamp::dumpAndDie($query);
            Yii::$app->db->createCommand($query)->execute();

        }
    }
}