Commit 8894c93a4170eaa5022ae68411aa24e20e365ba6
1 parent
28253169
add Importers files AR, make write procedure to Details
Showing
10 changed files
with
337 additions
and
107 deletions
Show diff stats
backend/components/parsers/CustomConverter.php
| @@ -11,15 +11,19 @@ class CustomConverter extends Converter { | @@ -11,15 +11,19 @@ class CustomConverter extends Converter { | ||
| 11 | */ | 11 | */ |
| 12 | public static function convertToAssocArray ($value_arr, $key_array, $key_prefix = '') | 12 | public static function convertToAssocArray ($value_arr, $key_array, $key_prefix = '') |
| 13 | { | 13 | { |
| 14 | + // очистка служебного префикса в массиве заголовков | ||
| 14 | if ($key_prefix) { | 15 | if ($key_prefix) { |
| 15 | - $parametrs_array = array_fill( 0, count($key_array), $key_prefix ); | ||
| 16 | - $key_array = array_map( function ($value, $key_prefix){ return str_replace( $key_prefix, '',$value ); }, $key_array, $parametrs_array ); | 16 | + $params_array = array_fill( 0, count($key_array), $key_prefix ); |
| 17 | + //@todo переписать с использованием array_walk | ||
| 18 | + $key_array = array_map( function ($value, $key_prefix){ return str_replace( $key_prefix, '',$value ); }, $key_array, $params_array ); | ||
| 19 | + //уберем пустые элементы | ||
| 20 | + $key_array = array_filter($key_array, function ($value){ return $value !==''; }); | ||
| 17 | } | 21 | } |
| 18 | 22 | ||
| 19 | // преобразуем массив ключей (обернем в массив), для передачи его в качестве параметра в анонимную функцию для array_map | 23 | // преобразуем массив ключей (обернем в массив), для передачи его в качестве параметра в анонимную функцию для array_map |
| 20 | // для этого увеличим размерность массива, что бы при каждом обходе массива $value_arr , функции был доступен исходный массив ключей | 24 | // для этого увеличим размерность массива, что бы при каждом обходе массива $value_arr , функции был доступен исходный массив ключей |
| 21 | $key_array = array_fill( 0, count($value_arr), $key_array ); | 25 | $key_array = array_fill( 0, count($value_arr), $key_array ); |
| 22 | - //\common\components\CustomVarDamp::dumpAndDie($key_array); | 26 | + // \common\components\CustomVarDamp::dumpAndDie($key_array); |
| 23 | $result = array_map( | 27 | $result = array_map( |
| 24 | function ($value, $key_array) { | 28 | function ($value, $key_array) { |
| 25 | $res = $value; | 29 | $res = $value; |
| @@ -40,4 +44,14 @@ class CustomConverter extends Converter { | @@ -40,4 +44,14 @@ class CustomConverter extends Converter { | ||
| 40 | return $result; | 44 | return $result; |
| 41 | } | 45 | } |
| 42 | 46 | ||
| 47 | + public function addColumn ($value_arr, $add_key, $add_value) | ||
| 48 | + { | ||
| 49 | + $i = 0; | ||
| 50 | + while ($i < count($value_arr)) { | ||
| 51 | + $value_arr[$i][$add_key] = $add_value; | ||
| 52 | + $i++; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + return $value_arr; | ||
| 56 | + } | ||
| 43 | } | 57 | } |
| 44 | \ No newline at end of file | 58 | \ No newline at end of file |
backend/components/parsers/CustomCsvParser.php
| @@ -11,24 +11,32 @@ namespace backend\components\parsers; | @@ -11,24 +11,32 @@ namespace backend\components\parsers; | ||
| 11 | 11 | ||
| 12 | class CustomCsvParser extends \yii\multiparser\CsvParser { | 12 | class CustomCsvParser extends \yii\multiparser\CsvParser { |
| 13 | 13 | ||
| 14 | - public $last_line = 10; | 14 | + public $last_line = 20; |
| 15 | //public $hasHeaderRow = true; | 15 | //public $hasHeaderRow = true; |
| 16 | // public $keys = ['first','second', 'third', 'forth', 'fifth']; | 16 | // public $keys = ['first','second', 'third', 'forth', 'fifth']; |
| 17 | public function setupConverter() | 17 | public function setupConverter() |
| 18 | { | 18 | { |
| 19 | - if ( count($this->converter_conf) ) { | ||
| 20 | - | 19 | + if (!count($this->converter_conf)) { |
| 21 | if ($this->hasHeaderRow) { | 20 | if ($this->hasHeaderRow) { |
| 22 | // если у файла есть заголовок, то в результате имеем ассоциативный массив | 21 | // если у файла есть заголовок, то в результате имеем ассоциативный массив |
| 23 | $this->converter_conf['hasKey'] = 1; | 22 | $this->converter_conf['hasKey'] = 1; |
| 24 | } | 23 | } |
| 25 | 24 | ||
| 26 | - $this->converter = \Yii::createObject($this->converter_conf); | ||
| 27 | - | ||
| 28 | } | 25 | } |
| 29 | 26 | ||
| 30 | - | ||
| 31 | } | 27 | } |
| 32 | 28 | ||
| 29 | + /** | ||
| 30 | + * @param $arr | ||
| 31 | + * @return mixed | ||
| 32 | + * преобразовует значения прочитанного массива в нужные типы, согласно конфигурации конвертера | ||
| 33 | + */ | ||
| 34 | + protected function convert($arr) | ||
| 35 | + { | ||
| 36 | + $result = \Yii::$app->multiparser->convertByConfiguration( $arr, $this->converter_conf ); | ||
| 37 | + | ||
| 38 | + return $result; | ||
| 39 | + | ||
| 40 | + } | ||
| 33 | 41 | ||
| 34 | } | 42 | } |
| 35 | \ No newline at end of file | 43 | \ No newline at end of file |
backend/controllers/ParserController.php
| @@ -10,16 +10,19 @@ use yii\web\UploadedFile; | @@ -10,16 +10,19 @@ use yii\web\UploadedFile; | ||
| 10 | use yii\data\ArrayDataProvider; | 10 | use yii\data\ArrayDataProvider; |
| 11 | use yii\multiparser\DynamicFormHelper; | 11 | use yii\multiparser\DynamicFormHelper; |
| 12 | use backend\components\parsers\CustomParserConfigurator; | 12 | use backend\components\parsers\CustomParserConfigurator; |
| 13 | +use backend\models\Details; | ||
| 14 | +use backend\models\ImporterFiles; | ||
| 15 | +use yii\base\ErrorException; | ||
| 13 | 16 | ||
| 14 | use common\components\CustomVarDamp; | 17 | use common\components\CustomVarDamp; |
| 15 | 18 | ||
| 16 | /** | 19 | /** |
| 17 | * Parser controller | 20 | * Parser controller |
| 18 | */ | 21 | */ |
| 19 | - | ||
| 20 | class ParserController extends BaseController | 22 | class ParserController extends BaseController |
| 21 | { | 23 | { |
| 22 | public $layout = "/column"; | 24 | public $layout = "/column"; |
| 25 | + | ||
| 23 | /** | 26 | /** |
| 24 | * @inheritdoc | 27 | * @inheritdoc |
| 25 | */ | 28 | */ |
| @@ -30,7 +33,7 @@ class ParserController extends BaseController | @@ -30,7 +33,7 @@ class ParserController extends BaseController | ||
| 30 | 'class' => AccessControl::className(), | 33 | 'class' => AccessControl::className(), |
| 31 | 'rules' => [ | 34 | 'rules' => [ |
| 32 | [ | 35 | [ |
| 33 | - 'actions' => ['index','results','write'], | 36 | + 'actions' => ['index', 'results', 'write'], |
| 34 | 'allow' => true, | 37 | 'allow' => true, |
| 35 | 'roles' => ['@'], | 38 | 'roles' => ['@'], |
| 36 | ], | 39 | ], |
| @@ -58,7 +61,6 @@ class ParserController extends BaseController | @@ -58,7 +61,6 @@ class ParserController extends BaseController | ||
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | 63 | ||
| 61 | - | ||
| 62 | public function actionIndex() | 64 | public function actionIndex() |
| 63 | { | 65 | { |
| 64 | $model = new UploadFileParsingForm(); | 66 | $model = new UploadFileParsingForm(); |
| @@ -66,26 +68,31 @@ class ParserController extends BaseController | @@ -66,26 +68,31 @@ class ParserController extends BaseController | ||
| 66 | return $this->render('index', ['model' => $model]); | 68 | return $this->render('index', ['model' => $model]); |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | - public function actionResults(){ | 71 | + public function actionResults() |
| 72 | + { | ||
| 70 | 73 | ||
| 71 | $model = new UploadFileParsingForm(); | 74 | $model = new UploadFileParsingForm(); |
| 72 | $data = []; | 75 | $data = []; |
| 73 | if ($model->load(Yii::$app->request->post())) { | 76 | if ($model->load(Yii::$app->request->post())) { |
| 74 | $model->file = UploadedFile::getInstance($model, 'file'); | 77 | $model->file = UploadedFile::getInstance($model, 'file'); |
| 75 | - | 78 | + // первый проход - валидируем, сохраняем файл, ложим в кеш отпарсенные данные и параметры модели (потом при записи в базу данных они пригодятся) |
| 76 | if ($model->validate()) { | 79 | if ($model->validate()) { |
| 77 | $filePath = Yii::getAlias('@webroot') . '/uploads/' . $model->file->baseName . '.' . $model->file->extension; | 80 | $filePath = Yii::getAlias('@webroot') . '/uploads/' . $model->file->baseName . '.' . $model->file->extension; |
| 78 | 81 | ||
| 79 | - $model->file->saveAs( $filePath ); | 82 | + $model->file->saveAs($filePath); |
| 83 | + //запускаем парсинг | ||
| 80 | $data = $model->readFile($filePath); | 84 | $data = $model->readFile($filePath); |
| 85 | + // сохраняем в кеш отпарсенные даные | ||
| 86 | + Yii::$app->getCache()->set('parser_data', json_encode($data)); | ||
| 87 | + // сохраняем в кеш модель - в ней настройки для дальнейшей обработки данных | ||
| 88 | + Yii::$app->getCache()->set('parser_configuration', serialize($model)); | ||
| 81 | 89 | ||
| 82 | - Yii::$app->getCache()->set( 'parser_data', json_encode($data) ); | ||
| 83 | 90 | ||
| 84 | } | 91 | } |
| 92 | + // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные | ||
| 93 | + } else if (Yii::$app->getCache()->get('parser_data')) { | ||
| 85 | 94 | ||
| 86 | - } else if( Yii::$app->getCache()->get( 'parser_data' )) { | ||
| 87 | - | ||
| 88 | - $data = json_decode( Yii::$app->getCache()->get( 'parser_data' ),true ); | 95 | + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true); |
| 89 | 96 | ||
| 90 | } | 97 | } |
| 91 | 98 | ||
| @@ -96,40 +103,99 @@ class ParserController extends BaseController | @@ -96,40 +103,99 @@ class ParserController extends BaseController | ||
| 96 | ], | 103 | ], |
| 97 | ]); | 104 | ]); |
| 98 | 105 | ||
| 99 | - //CustomVarDamp::dumpAndDie($data); | ||
| 100 | - $header_model = DynamicFormHelper::CreateDynamicModel( count( $data[0] ) ); | 106 | + //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) |
| 107 | + $header_model = DynamicFormHelper::CreateDynamicModel(count($data[0])); | ||
| 101 | 108 | ||
| 102 | - // CustomVarDamp::dumpAndDie(Yii::$app->multiparser->getConfiguration('csv','basic_column')); | ||
| 103 | return $this->render('results', | 109 | return $this->render('results', |
| 104 | ['model' => $data, | 110 | ['model' => $data, |
| 105 | 'header_model' => $header_model, | 111 | 'header_model' => $header_model, |
| 106 | - 'basic_column' => Yii::$app->multiparser->getConfiguration('csv','basic_column'), | 112 | + // список колонок для выбора |
| 113 | + 'basic_column' => Yii::$app->multiparser->getConfiguration('csv', 'basic_column'), | ||
| 107 | 'dataProvider' => $provider]); | 114 | 'dataProvider' => $provider]); |
| 108 | } | 115 | } |
| 109 | 116 | ||
| 110 | -public function actionWrite() | ||
| 111 | -{ | ||
| 112 | - //CustomVarDamp::dumpAndDie(Yii::$app->request->post()); | 117 | + public function actionWrite() |
| 118 | + { | ||
| 113 | 119 | ||
| 114 | - $arr_attributes = Yii::$app->request->post()['DynamicModel']; | ||
| 115 | - $model = DynamicFormHelper::CreateDynamicModel( $arr_attributes ); | ||
| 116 | - foreach ($arr_attributes as $key => $value) { | ||
| 117 | - $model->addRule($key, 'in', ['range' => array_keys( Yii::$app->multiparser->getConfiguration('csv','basic_column') )]); | ||
| 118 | - } | 120 | + //получим колонки которые выбрал пользователь |
| 121 | + $arr_attributes = Yii::$app->request->post()['DynamicModel']; | ||
| 122 | + //соберем модель по полученным данным | ||
| 123 | + $model = DynamicFormHelper::CreateDynamicModel($arr_attributes); | ||
| 124 | + //добавим правила валидации (колонки должны быть те что указаны в конфиге) | ||
| 125 | + foreach ($arr_attributes as $key => $value) { | ||
| 126 | + $model->addRule($key, 'in', ['range' => array_keys(Yii::$app->multiparser->getConfiguration('csv', 'basic_column'))]); | ||
| 127 | + } | ||
| 119 | 128 | ||
| 129 | + // провалидируем выбранные колонки | ||
| 130 | + if ($model->validate()) { | ||
| 120 | 131 | ||
| 121 | - //CustomVarDamp::dumpAndDie($model); | ||
| 122 | - if ($model->validate()) { | ||
| 123 | - $arr = $model->toArray(); | ||
| 124 | - $data = json_decode( Yii::$app->getCache()->get( 'parser_data' ),true ); | 132 | + // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы |
| 133 | + $arr = $model->toArray(); | ||
| 125 | 134 | ||
| 126 | - $data = \Yii::$app->multiparser->convertToAssocArray( $data, $arr, 'attr_' ); | ||
| 127 | - $data[1]['BOX'] = \Yii::$app->multiparser->convertToFloat( $data[1]['BOX'] ); | ||
| 128 | - CustomVarDamp::dumpAndDie($data); | ||
| 129 | - } | 135 | + // получим данные из кеша |
| 136 | + if (Yii::$app->getCache()->get('parser_data') && Yii::$app->getCache()->get('parser_configuration')) { | ||
| 137 | + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true); | ||
| 138 | + $configuration = unserialize(Yii::$app->getCache()->get('parser_configuration')); | ||
| 139 | + } else { | ||
| 140 | + CustomVarDamp::dumpAndDie('Ошибка кеша'); | ||
| 141 | + } | ||
| 130 | 142 | ||
| 143 | + // соотнесем отпарсенные данные с соответсивем полученным от пользователя | ||
| 144 | + // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию | ||
| 145 | + $data = \Yii::$app->multiparser->convertToAssocArray($data, $arr, 'attr_'); | ||
| 146 | + | ||
| 147 | + | ||
| 148 | + // запишем дату старта в таблицу файлов поставщика (ImportersFiles) | ||
| 149 | + $files_model = new ImporterFiles(); | ||
| 150 | + // id поставщика получим из конфигурации | ||
| 151 | + $files_model->load(['ImporterFiles' => $configuration->toArray()]); | ||
| 152 | + if ($files_model->validate()) { | ||
| 153 | + try { | ||
| 154 | + $files_model->save(); | ||
| 155 | + } catch (ErrorException $e) { | ||
| 156 | + CustomVarDamp::dump($e->getMessage()); | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + | ||
| 160 | + // запишем полученные данные в таблицу товаров (Details) | ||
| 161 | + $details_model = new Details('web'); | ||
| 162 | + // проверим все ли обязательные колонки были указаны пользователем | ||
| 163 | + $details_model->load(['Details' => $data[0]]); | ||
| 164 | + if ($details_model->validate()) { | ||
| 165 | + // проставим импортера | ||
| 166 | + $data = $details_model->prepareData($data, $configuration); | ||
| 167 | + | ||
| 168 | + try { | ||
| 169 | + // попытаемся вставить данные в БД с апдейтом по ключам | ||
| 170 | + $details_model->save($data); | ||
| 171 | + | ||
| 172 | + // а также зафиксируем дату конца загрузки | ||
| 173 | + $files_model->time_end = mktime(); // ошибка!!!!!!!!!!!!!!!! | ||
| 174 | + $files_model->save(); | ||
| 175 | + | ||
| 176 | + // все прошло успешно - очищаем кеш | ||
| 177 | + Yii::$app->getCache()->delete('parser_data'); | ||
| 178 | + Yii::$app->getCache()->delete('parser_configuration'); | ||
| 179 | + | ||
| 180 | + CustomVarDamp::dumpAndDie('!!!'); | ||
| 181 | + } catch (ErrorException $e) { | ||
| 182 | + CustomVarDamp::dump($e->getMessage()); | ||
| 183 | + } | ||
| 184 | + } | ||
| 185 | + if ($details_model->hasErrors()) { | ||
| 186 | + $errors_arr = $details_model->getErrors(); | ||
| 187 | + foreach ($errors_arr as $error) { | ||
| 188 | + CustomVarDamp::dump(array_values($error)); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + } | ||
| 131 | 192 | ||
| 132 | 193 | ||
| 133 | -} | 194 | + } |
| 195 | + | ||
| 196 | + | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + } | ||
| 134 | 200 | ||
| 135 | } | 201 | } |
backend/models/Details.php
| @@ -9,11 +9,127 @@ | @@ -9,11 +9,127 @@ | ||
| 9 | namespace backend\models; | 9 | namespace backend\models; |
| 10 | 10 | ||
| 11 | use yii\base\Model; | 11 | use yii\base\Model; |
| 12 | +use Yii; | ||
| 12 | 13 | ||
| 13 | class Details extends Model{ | 14 | class Details extends Model{ |
| 15 | + const KEY_COLUMN = ['IMPORT_ID','BRAND','ARTICLE']; | ||
| 16 | + const BATCH = 500; | ||
| 14 | 17 | ||
| 15 | - public function save ($arr_value) | 18 | + private $mode; |
| 19 | + | ||
| 20 | + // обязательные поля модели | ||
| 21 | + public $BRAND; | ||
| 22 | + public $ARTICLE; | ||
| 23 | + public $PRICE; | ||
| 24 | + public $BOX; | ||
| 25 | + | ||
| 26 | + function __construct($mode) | ||
| 27 | + { | ||
| 28 | + $this->mode = $mode; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + public function rules() | ||
| 32 | + { | ||
| 33 | + return [ | ||
| 34 | + [['BRAND','ARTICLE', 'PRICE', 'BOX'], 'required' ], | ||
| 35 | + ]; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public function formName() | ||
| 39 | + { | ||
| 40 | + return 'Details'; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + public static function tableName() | ||
| 45 | + { | ||
| 46 | + return '{{%details}}'; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + //@todo вероятно этой функции не место здесь | ||
| 50 | + public function prepareData ( $data, $configuration ) | ||
| 51 | + { | ||
| 52 | + if ( isset($configuration['importer_id']) && $configuration['importer_id']) { | ||
| 53 | + $data = \Yii::$app->multiparser->addColumn( $data, 'IMPORT_ID', $configuration['importer_id'] ); | ||
| 54 | + } | ||
| 55 | + // \common\components\CustomVarDamp::dumpAndDie($data); | ||
| 56 | + return $data; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * @param $data - двумерный массив данных для записи в таблицу details | ||
| 61 | + * @throws \yii\db\Exception | ||
| 62 | + * вставляет записи с апдейтом при дубляже ключей | ||
| 63 | + */ | ||
| 64 | + public function save ($data) | ||
| 16 | { | 65 | { |
| 66 | + $table_name = self::tableName(); | ||
| 67 | + $keys_arr = array_keys( $data[0] ); | ||
| 68 | + // найдем те поля которые не являются ключами. Их нужно будет при дубляже апдейтить | ||
| 69 | + $fields_arr_to_update = array_diff( $keys_arr, $this::KEY_COLUMN ); | ||
| 70 | + | ||
| 71 | + $query_update = ' on duplicate key update '; | ||
| 72 | + foreach ($fields_arr_to_update as $field) { | ||
| 73 | + $query_update .= "{$field} = values ({$field}),"; | ||
| 74 | + } | ||
| 75 | + // удалим последнюю запятую | ||
| 76 | + $query_update = substr($query_update, 0, strlen($query_update) - 1); | ||
| 77 | + | ||
| 78 | + // запросы будем выполнять пакетами | ||
| 79 | + // размер пакета установлен в константе | ||
| 80 | + // разобъем массив на пакеты и будем их проходить | ||
| 81 | + $data = array_chunk($data, $this::BATCH ); | ||
| 82 | + foreach( $data as $current_batch_array ){ | ||
| 83 | + | ||
| 84 | + //воспользуемся пакетной вставкой от фреймворка, плюс сразу с экранированием и защитой от инъекций | ||
| 85 | + $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql; | ||
| 86 | + // добавим фрагмент с апдейтом при дубляже | ||
| 87 | + $query = "{$query_insert} {$query_update}"; | ||
| 88 | + | ||
| 89 | + $res = Yii::$app->db->createCommand($query)->execute(); | ||
| 90 | + | ||
| 91 | + } | ||
| 17 | 92 | ||
| 18 | } | 93 | } |
| 19 | -} | ||
| 20 | \ No newline at end of file | 94 | \ No newline at end of file |
| 95 | +} | ||
| 96 | + | ||
| 97 | +// | ||
| 98 | + | ||
| 99 | +//$q = " INSERT INTO {$table_name} ({$keys_string}) VALUES ("; | ||
| 100 | + | ||
| 101 | +//$q .= " on duplicate key update `FULL_ARTICLE` = values (`FULL_ARTICLE`), | ||
| 102 | +// `PRICE` = values (`PRICE`), | ||
| 103 | +// `DESCR` = values(`DESCR`), | ||
| 104 | +// `BOX` = values(`BOX`), | ||
| 105 | +// `ADD_BOX` = values(`ADD_BOX`), | ||
| 106 | +// `GROUP` = values(`GROUP`);"; | ||
| 107 | + | ||
| 108 | +// INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) | ||
| 109 | +// ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b); | ||
| 110 | + | ||
| 111 | + | ||
| 112 | + | ||
| 113 | +//INSERT INTO `books` (`UserId`, `BookId`, `Count`) VALUES (13, 1001, 3) | ||
| 114 | +//ON DUPLICATE KEY UPDATE `Count` = `Count` + VALUES(`Count`); | ||
| 115 | + | ||
| 116 | +//$values_string = ''; | ||
| 117 | +//$keys_arr = array_keys( $data[0] ); | ||
| 118 | +//$keys_string = implode( ',', $keys_arr); | ||
| 119 | +//$table_name = self::tableName(); | ||
| 120 | +//$current_batch = 0; | ||
| 121 | +//for ($i = $current_batch; $i < $this::BATCH AND $i < count($data); $i++) { | ||
| 122 | +// $values_string .= '(' . implode( ',', $data[$i]) . '),'; | ||
| 123 | +//} | ||
| 124 | +// for ($current_batch = $this::BATCH; $current_batch<count($data); $current_batch + $this::BATCH ) | ||
| 125 | +//// удалим последнюю запятую | ||
| 126 | +//$values_string = substr($values_string, 0, strlen($values_string) - 1) . ' '; | ||
| 127 | +////\common\components\CustomVarDamp::dumpAndDie($values_string); | ||
| 128 | +//// $query = "INSERT INTO {$table_name}({$keys_string}) VALUES {$values_string}"; | ||
| 129 | +//// on duplicate key update `PRICE` = values (`PRICE`),`DESCR` = values(`DESCR`),`BOX` = values(`BOX`)"; | ||
| 130 | +//$query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $data)->sql; | ||
| 131 | +//$query = "{$query_insert} on duplicate key update `PRICE` = values (`PRICE`),`DESCR` = values(`DESCR`),`BOX` = values(`BOX`)"; | ||
| 132 | +//$res = Yii::$app->db->createCommand($query)->execute(); | ||
| 133 | + | ||
| 134 | + | ||
| 135 | + | ||
| 136 | +// Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $data)->sql execute(); | ||
| 21 | \ No newline at end of file | 137 | \ No newline at end of file |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace backend\models; | ||
| 4 | + | ||
| 5 | +use Yii; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * This is the model class for table "{{%importer_files}}". | ||
| 9 | + * | ||
| 10 | + * @property integer $id | ||
| 11 | + * @property string $importer_id | ||
| 12 | + * @property string $upload_time | ||
| 13 | + * @property string $time_start | ||
| 14 | + * @property string $time_end | ||
| 15 | + */ | ||
| 16 | +class ImporterFiles extends \yii\db\ActiveRecord | ||
| 17 | +{ | ||
| 18 | + /** | ||
| 19 | + * @inheritdoc | ||
| 20 | + */ | ||
| 21 | + public static function tableName() | ||
| 22 | + { | ||
| 23 | + return '{{%importer_files}}'; | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * @inheritdoc | ||
| 28 | + */ | ||
| 29 | + public function rules() | ||
| 30 | + { | ||
| 31 | + return [ | ||
| 32 | + [['importer_id'], 'required'], | ||
| 33 | + [['importer_id'], 'integer'], | ||
| 34 | + [['upload_time', 'time_start', 'time_end'], 'safe'] | ||
| 35 | + ]; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * @inheritdoc | ||
| 40 | + */ | ||
| 41 | + public function attributeLabels() | ||
| 42 | + { | ||
| 43 | + return [ | ||
| 44 | + 'id' => Yii::t('app', 'ID'), | ||
| 45 | + 'importer_id' => Yii::t('app', 'Importer ID'), | ||
| 46 | + 'upload_time' => Yii::t('app', 'Upload Time'), | ||
| 47 | + 'time_start' => Yii::t('app', 'Time Start'), | ||
| 48 | + 'time_end' => Yii::t('app', 'Time End'), | ||
| 49 | + ]; | ||
| 50 | + } | ||
| 51 | +} |
backend/models/UploadFileParsingForm.php
| @@ -15,7 +15,7 @@ class UploadFileParsingForm extends Model | @@ -15,7 +15,7 @@ class UploadFileParsingForm extends Model | ||
| 15 | * @var UploadedFile file attribute | 15 | * @var UploadedFile file attribute |
| 16 | */ | 16 | */ |
| 17 | public $file; | 17 | public $file; |
| 18 | - public $importer; | 18 | + public $importer_id; |
| 19 | public $action; | 19 | public $action; |
| 20 | public $delimiter; | 20 | public $delimiter; |
| 21 | public $delete_price; | 21 | public $delete_price; |
| @@ -27,12 +27,12 @@ class UploadFileParsingForm extends Model | @@ -27,12 +27,12 @@ class UploadFileParsingForm extends Model | ||
| 27 | public function rules() | 27 | public function rules() |
| 28 | { | 28 | { |
| 29 | return [ | 29 | return [ |
| 30 | - ['importer', 'required', 'message' => 'Не указан поставщик!' ], | 30 | + ['importer_id', 'required', 'message' => 'Не указан поставщик!' ], |
| 31 | ['file', 'required', 'message' => 'Не выбран файл!' ], | 31 | ['file', 'required', 'message' => 'Не выбран файл!' ], |
| 32 | //@todo - not working this file validator!!! - fixed | 32 | //@todo - not working this file validator!!! - fixed |
| 33 | [['file'], 'file'],// 'extensions' => ['csv', 'xml'] ], | 33 | [['file'], 'file'],// 'extensions' => ['csv', 'xml'] ], |
| 34 | // 'wrongMimeType' => 'Указан неподдерживаемый тип файла. Можно выбирать csv, xml файлы.' ], | 34 | // 'wrongMimeType' => 'Указан неподдерживаемый тип файла. Можно выбирать csv, xml файлы.' ], |
| 35 | - ['importer', 'integer','max' => 999999, 'min' => 0 ], | 35 | + ['importer_id', 'integer','max' => 999999, 'min' => 0 ], |
| 36 | [['action','delete_prefix', 'delete_price'], 'boolean'], | 36 | [['action','delete_prefix', 'delete_price'], 'boolean'], |
| 37 | ['delimiter', 'string', 'max' => 1], | 37 | ['delimiter', 'string', 'max' => 1], |
| 38 | ['delimiter', 'default', 'value' => ';'] | 38 | ['delimiter', 'default', 'value' => ';'] |
| @@ -44,7 +44,7 @@ class UploadFileParsingForm extends Model | @@ -44,7 +44,7 @@ class UploadFileParsingForm extends Model | ||
| 44 | { | 44 | { |
| 45 | return [ | 45 | return [ |
| 46 | 'file' => Yii::t('app', 'Источник'), | 46 | 'file' => Yii::t('app', 'Источник'), |
| 47 | - 'importer' => Yii::t('app', 'Поставщик'), | 47 | + 'importer_id' => Yii::t('app', 'Поставщик'), |
| 48 | 'delimiter' => Yii::t('app', 'Разделитель'), | 48 | 'delimiter' => Yii::t('app', 'Разделитель'), |
| 49 | ]; | 49 | ]; |
| 50 | } | 50 | } |
| @@ -55,6 +55,8 @@ class UploadFileParsingForm extends Model | @@ -55,6 +55,8 @@ class UploadFileParsingForm extends Model | ||
| 55 | if( !is_array($data) ){ | 55 | if( !is_array($data) ){ |
| 56 | $data = ['No results']; | 56 | $data = ['No results']; |
| 57 | } | 57 | } |
| 58 | + | ||
| 58 | return $data; | 59 | return $data; |
| 59 | } | 60 | } |
| 61 | + | ||
| 60 | } | 62 | } |
| 61 | \ No newline at end of file | 63 | \ No newline at end of file |
backend/views/parser/index.php
| @@ -15,7 +15,7 @@ use yii\helpers\ArrayHelper; | @@ -15,7 +15,7 @@ use yii\helpers\ArrayHelper; | ||
| 15 | <h3>Загрузка прайсов поставщиков</h3> | 15 | <h3>Загрузка прайсов поставщиков</h3> |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | - <?= $form->field($model, 'importer')->dropDownList(ArrayHelper::map( Importer::find()->all(), 'id','name' )); ?> | 18 | + <?= $form->field($model, 'importer_id')->dropDownList(ArrayHelper::map( Importer::find()->all(), 'id','name' )); ?> |
| 19 | <?= $form->field($model, 'delete_price')->checkbox(['label' => 'Загрузить с удалением старого прайса']) ?> | 19 | <?= $form->field($model, 'delete_price')->checkbox(['label' => 'Загрузить с удалением старого прайса']) ?> |
| 20 | <?= $form->field($model, 'file')->fileInput()->label(false) ?> | 20 | <?= $form->field($model, 'file')->fileInput()->label(false) ?> |
| 21 | <?= $form->field($model, 'action')->radioList([1 => 'Стандартная обработка', 0 => 'С разделителем'])->label(false) ?> | 21 | <?= $form->field($model, 'action')->radioList([1 => 'Стандартная обработка', 0 => 'С разделителем'])->label(false) ?> |
console/migrations/m150915_125129_addDetails.php
| @@ -7,45 +7,27 @@ class m150915_125129_addDetails extends Migration | @@ -7,45 +7,27 @@ class m150915_125129_addDetails extends Migration | ||
| 7 | { | 7 | { |
| 8 | public function up() | 8 | public function up() |
| 9 | { | 9 | { |
| 10 | - $tableOptions = null; | ||
| 11 | - if ($this->db->driverName === 'mysql') { | ||
| 12 | - $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; | ||
| 13 | - } | ||
| 14 | - | ||
| 15 | - $this->createTable('{{%details}}', [ | ||
| 16 | - 'ID' => 'int(10) UNSIGNED NOT NULL', | ||
| 17 | - 'IMPORT_ID' => 'int(6) unsigned NOT NULL', | ||
| 18 | - 'BRAND' => 'varchar(100) NOT NULL', | ||
| 19 | - 'ARTICLE' => 'varchar(100) NOT NULL', | ||
| 20 | - 'FULL_ARTICLE' => 'varchar(150) NOT NULL', | ||
| 21 | - 'PRICE' => 'float(15,2) unsigned NOT NULL', | ||
| 22 | - 'DESCR' => 'varchar(200) NOT NULL', | ||
| 23 | - 'BOX' => 'int(6) unsigned NOT NULL', | ||
| 24 | - 'ADD_BOX' => 'int(6) unsigned NOT NULL DEFAULT 0', | ||
| 25 | - 'GROUP' => 'varchar(200) NOT NULL', | ||
| 26 | - 'timestamp' => 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP',], $tableOptions); | ||
| 27 | - | ||
| 28 | - //$this->dropPrimaryKey('ID','{{%details}}'); | ||
| 29 | - $this->createIndex('ID_delete', '{{%details}}', 'ID', true); | ||
| 30 | - $this->execute('ALTER TABLE details | ||
| 31 | - CHANGE COLUMN ID ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT'); | ||
| 32 | - $this->addPrimaryKey('importer_id', '{{%details}}', 'import_id, brand, ARTICLE'); | ||
| 33 | - $this->createIndex('timestamp', '{{%details}}', 'timestamp', false); | ||
| 34 | - $this->createIndex('ARTICLE', '{{%details}}', 'ARTICLE', 'BRAND', 'ADD_BOX', false); | ||
| 35 | - $this->createIndex('IMPORT_ID', '{{%details}}', 'ARTICLE', false); | ||
| 36 | - $this->createIndex('IMPORT_ID_2', '{{%details}}', 'IMPORT_ID', 'timestamp', false); | ||
| 37 | - | ||
| 38 | - | ||
| 39 | - | ||
| 40 | - | ||
| 41 | -// PRIMARY KEY ('ARTICLE','BRAND','IMPORT_ID'), | ||
| 42 | -// UNIQUE KEY 'ID_delete' ('ID'), | ||
| 43 | -// KEY 'timestamp' ('timestamp'), | ||
| 44 | -// KEY 'ARTICLE' ('ARTICLE','BRAND','BOX'), | ||
| 45 | -// KEY 'BRAND' ('BRAND','ARTICLE'), | ||
| 46 | -// KEY 'ARTICLE_2' ('ARTICLE','BRAND','ADD_BOX'), | ||
| 47 | -// KEY 'IMPORT_ID' ('IMPORT_ID','ARTICLE'), | ||
| 48 | -// KEY 'IMPORT_ID_2' ('IMPORT_ID','timestamp | 10 | + $this->execute('CREATE TABLE `details` ( |
| 11 | + `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||
| 12 | + `IMPORT_ID` int(6) unsigned NOT NULL, | ||
| 13 | + `BRAND` varchar(100) NOT NULL, | ||
| 14 | + `ARTICLE` varchar(100) NOT NULL, | ||
| 15 | + `FULL_ARTICLE` varchar(150) NOT NULL, | ||
| 16 | + `PRICE` float(15,2) unsigned NOT NULL, | ||
| 17 | + `DESCR` varchar(200) NOT NULL, | ||
| 18 | + `BOX` int(6) unsigned NOT NULL, | ||
| 19 | + `ADD_BOX` int(6) unsigned NOT NULL DEFAULT 0, | ||
| 20 | + `GROUP` varchar(200) NOT NULL DEFAULT \'\', | ||
| 21 | + `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| 22 | + PRIMARY KEY (`ARTICLE`,`BRAND`,`IMPORT_ID`), | ||
| 23 | + UNIQUE KEY `ID_delete` (`ID`), | ||
| 24 | + KEY `timestamp` (`timestamp`), | ||
| 25 | + KEY `ARTICLE` (`ARTICLE`,`BRAND`,`BOX`), | ||
| 26 | + KEY `BRAND` (`BRAND`,`ARTICLE`), | ||
| 27 | + KEY `ARTICLE_2` (`ARTICLE`,`BRAND`,`ADD_BOX`), | ||
| 28 | + KEY `IMPORT_ID` (`IMPORT_ID`,`ARTICLE`), | ||
| 29 | + KEY `IMPORT_ID_2` (`IMPORT_ID`,`timestamp`) | ||
| 30 | + ) ENGINE=InnoDB DEFAULT CHARSET=utf8'); | ||
| 49 | 31 | ||
| 50 | } | 32 | } |
| 51 | 33 | ||
| @@ -55,14 +37,4 @@ class m150915_125129_addDetails extends Migration | @@ -55,14 +37,4 @@ class m150915_125129_addDetails extends Migration | ||
| 55 | 37 | ||
| 56 | } | 38 | } |
| 57 | 39 | ||
| 58 | - /* | ||
| 59 | - // Use safeUp/safeDown to run migration code within a transaction | ||
| 60 | - public function safeUp() | ||
| 61 | - { | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | - public function safeDown() | ||
| 65 | - { | ||
| 66 | - } | ||
| 67 | - */ | ||
| 68 | } | 40 | } |
vendor/yiisoft/multiparser/Converter.php
| @@ -15,9 +15,9 @@ class Converter extends Behavior | @@ -15,9 +15,9 @@ class Converter extends Behavior | ||
| 15 | 15 | ||
| 16 | const METHOD_PREFIX = 'convertTo'; | 16 | const METHOD_PREFIX = 'convertTo'; |
| 17 | 17 | ||
| 18 | - public $configuration = []; | 18 | + //public $configuration = []; |
| 19 | 19 | ||
| 20 | - protected static function convertToFloat($value) | 20 | + public static function convertToFloat($value) |
| 21 | { | 21 | { |
| 22 | echo 1; | 22 | echo 1; |
| 23 | if ($value == '') { | 23 | if ($value == '') { |
| @@ -34,7 +34,7 @@ class Converter extends Behavior | @@ -34,7 +34,7 @@ class Converter extends Behavior | ||
| 34 | return $value; | 34 | return $value; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | - protected static function convertToInteger($value) | 37 | + public static function convertToInteger($value) |
| 38 | { | 38 | { |
| 39 | if ($value == '') { | 39 | if ($value == '') { |
| 40 | $value = 0; | 40 | $value = 0; |
| @@ -49,7 +49,7 @@ class Converter extends Behavior | @@ -49,7 +49,7 @@ class Converter extends Behavior | ||
| 49 | return $value; | 49 | return $value; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | - protected static function convertToString($value) | 52 | + public static function convertToString($value) |
| 53 | { | 53 | { |
| 54 | 54 | ||
| 55 | 55 | ||
| @@ -93,16 +93,17 @@ class Converter extends Behavior | @@ -93,16 +93,17 @@ class Converter extends Behavior | ||
| 93 | 93 | ||
| 94 | 94 | ||
| 95 | /** | 95 | /** |
| 96 | - * @param $arr - массив | 96 | + * @param $arr - массив для конвертирования |
| 97 | + * @param $configuration - массив конфигурация конвертирования | ||
| 97 | * @return mixed | 98 | * @return mixed |
| 98 | * конвертирует массив по полученным настройкам, вызывая последовательно функции конвертации (указанные в конфигурации) | 99 | * конвертирует массив по полученным настройкам, вызывая последовательно функции конвертации (указанные в конфигурации) |
| 99 | */ | 100 | */ |
| 100 | - public function convertByConfiguration( $arr ) | 101 | + public static function convertByConfiguration( $arr, $configuration ) |
| 101 | { | 102 | { |
| 102 | $result = $arr; | 103 | $result = $arr; |
| 103 | - | ||
| 104 | - $hasKey = isset( $this->configuration['hasKey'] ); | ||
| 105 | - foreach ( $this->configuration as $key => $value ) { | 104 | + //\common\components\CustomVarDamp::dumpAndDie($configuration); |
| 105 | + $hasKey = isset( $configuration['hasKey'] ); | ||
| 106 | + foreach ( $configuration['configuration'] as $key => $value ) { | ||
| 106 | 107 | ||
| 107 | if ( $hasKey ){ | 108 | if ( $hasKey ){ |
| 108 | // у нас ассоциативный массив, и мы можем конвертировать каждое значение в отдельности | 109 | // у нас ассоциативный массив, и мы можем конвертировать каждое значение в отдельности |
vendor/yiisoft/multiparser/CsvParser.php
| @@ -78,7 +78,7 @@ class CsvParser implements ParserInterface | @@ -78,7 +78,7 @@ class CsvParser implements ParserInterface | ||
| 78 | // если у файла есть заголовок, то в результате имеем ассоциативный массив | 78 | // если у файла есть заголовок, то в результате имеем ассоциативный массив |
| 79 | $this->converter_conf['hasKey'] = 1; | 79 | $this->converter_conf['hasKey'] = 1; |
| 80 | } | 80 | } |
| 81 | - $this->converter->configuration = $this->converter_conf; | 81 | + //$this->converter->configuration = $this->converter_conf; |
| 82 | 82 | ||
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| @@ -198,7 +198,7 @@ class CsvParser implements ParserInterface | @@ -198,7 +198,7 @@ class CsvParser implements ParserInterface | ||
| 198 | 198 | ||
| 199 | if (!is_null($converter)) { | 199 | if (!is_null($converter)) { |
| 200 | 200 | ||
| 201 | - $result = $converter->convertByConfiguration( $arr ); | 201 | + $result = $converter->convertByConfiguration( $arr, $this->converter_conf ); |
| 202 | 202 | ||
| 203 | } | 203 | } |
| 204 | 204 |