Сохранение данных при комбинации TabularInput + MultipleInput

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
oughtem2
Сообщения: 34
Зарегистрирован: 2019.10.26, 20:50

Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение oughtem2 »

моя задача сделать табличное редактирование параметров товаров. Параметры находятся в связанной таблице и с помощью функции заполняют свойство params объекта Product вот таким образом:

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

common\models\Product Object
        (
            [imagesFiles] => Array
                (
                )

            [params] => Array
                (
                    [0] => Array
                        (
                            [key] =>33333333
                            [value] => 33
                        )

                    [1] => Array
                        (
                            [key] => 444444444
                            [value] => 44
                        )

                    [2] => Array
                        (
                            [key] => 55555555
                            [value] => 55
                        )

                )

            [landings] => Array
                (
                )

            [_attributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id] => 128165
                    [user_id] => 442
                    [name] => 1051AC-12 Карандаши пластик. "Butterfly" 12 цв., в картоне, европ. J. Otten
                    [category_id] => 340
                    [alias] => 1051ac-12-karandasi-plastik-butterfly-12-cv-v-kartone-evrop-j-otten
                    [status] => 1
                    [description] => уп.-12;ящ.-240;
                    [meta_title] => 
                    [meta_keywords] => 
                    [meta_description] => 
                    [h1] => 
                    [available] => 0
                    [keywords] => 
                    [price] => 0.33
                    [old_price] => 0
                    [hasImage] => 0
                    [image] => 
                    [vendor] => Josef Otten
                    [vendorCode] => 1051AC-12
                    [barCode] => 736159
                    [country_of_origin] => 
                    [created_at] => 1550780796
                    [updated_at] => 1571912976
                    [cart_count] => 1
                    [min_quantity] => 12
                    [step_quantity] => 12
                    [picture_available] => 0
                    [visible] => 0
                    [provider_product_id] => 
                )
.......
я в экшен "edit-params" предаю массив таких объектов и связкой TabularInput и MultipleInput получаю этот массив в таком виде http://joxi.ru/D2P5LDOTqL1eLA. Пока всё хорошо.

Вопрос возникает при сохранении. Если не изменять параметров и сохраниться с таким набором параметров, который показан на http://joxi.ru/D2P5LDOTqL1eLA, то получаю такой вот массив POST, в котором не правильно формируется блок `params`

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

Array
(
    [_csrf-backend] => m-EPJlfRfr4P7h23DSadgxqz7fvjw6fbIN2h1Hz7597Zhmx0ZZ8H7WOdUG0-fvDXKcKLjtKt7LZNrviQGaqRjw==
    [Product] => Array
        (
            [128165] => Array
                (
                    [id] => 128165
                    [name] => 1051AC-12 Карандаши пластик. "Butterfly" 12 цв., в картоне, европ. J. Otten
                )

            [params] => Array
                (
                    [0] => Array
                        (
                            [key] => 11111111
                            [value] => 11
                        )

                    [1] => Array
                        (
                            [key] => 22222222
                            [value] => 22
                        )

                )

            [157653] => Array
                (
                    [id] => 157653
                    [name] => Календарь отрывной "Зцілюючі сили" на украинском языке
                )

        )

)
а именно:

1. пары "ключ-значение" от второго товара передались первому товару,
2. второму товару ничего не передалось.

В ходе экспериментов выяснилось, что всегда передаётся массив `params` от последнего в списке товара первому в списке товару, а все остальные товары остаются без массива `params`. При этом `id` и `name` передаются правильно. Сохранение `params` в контроллере ещё не описано, но по массиву POST очевидно, что данные для сохранения сформированы не правильно

Вот код в контроллере:

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

public function actionEditParams()
    {
        $ids = Yii::$app->request->get('id');
        $arr = explode(',', $ids);
        
        $post = Yii::$app->request->post('Product');
        
        $dataProvider = new ActiveDataProvider([
            'query' => Product::find()->where(['id' => $arr])->indexBy('id'),
        ]);
        
        $models = $dataProvider->getModels();

        foreach ($models as $model){
            $params = ProductsParams::find()->select([Params::tableName().'.name',Params::tableName().'.value'])
                ->leftJoin(Params::tableName(),ProductsParams::tableName().'.param_id = '.Params::tableName().'.id')
                ->where([ProductsParams::tableName().'.product_id' => $model->id])->asArray()->all();

            if(!empty($params)){
                foreach ($params as $index=>$param){
                    $model->params[$index]['key'] = $param['name'];
                    $model->params[$index]['value'] = $param['value'];
                }
            }
        }
        
//        if (Model::loadMultiple($models, Yii::$app->request->post()) && Model::validateMultiple($models)) {
//            $count = 0;
//            foreach ($models as $index => $model) {
//                // populate and save records for each model
//                if ($model->save()) {
//                    $count++;
//                }
//            }
//            Yii::$app->session->setFlash('success', "Processed {$count} records successfully.");
//            return $this->redirect(Yii::$app->request->referrer);
//        } 

        return $this->render('edit-params', ['post' => $post, 'models' => $models]);
        
    }
вот код вьюхи

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

<?php
use yii\bootstrap\ActiveForm;
use yii\helpers\Html;
use yii\helpers\ArrayHelper;

use unclead\multipleinput\MultipleInput;
use unclead\multipleinput\TabularInput;

//https://github.com/unclead/yii2-multiple-input/wiki/

echo '<pre>';
print_r($_POST);
echo '</pre>';

$form = ActiveForm::begin();

echo TabularInput::widget([
    'models' => $models,
    'attributeOptions' => [
        'enableAjaxValidation'      => false,
        'enableClientValidation'    => true,
        'validateOnChange'          => true,
        'validateOnSubmit'          => true,
        'validateOnBlur'            => true,
    ],
    'columns' => [
        [
            'name'  => 'id',
        ],
        [
            'name'  => 'name',
        ],
        [
            'name' => 'params',
            'type' => MultipleInput::className(),
            'options' => [
                'enableError' => true,
                'sortable' => true,
                'cloneButton' => true,
                'columns' => [
                    [
                        'title' => 'Название параметра',
                        'name'  => 'key',
                    ],
                    [
                        'title' => 'Значение',
                        'name'  => 'value',
                    ],
                ],
            ],
        ],
    ],
]);
echo Html::submitButton('Update', ['class' => 'btn btn-success']);
ActiveForm::end();
?>
Соответственно я не понимаю куда копать: если массив `params` распознался виджетом MultipleInput и корректно отображается, значит модель и настройки 'columns' переданы верно. Это означает, что либо я не использую какие-то нужные в данном случае настройки виджетов либо в такой связке виджетов есть косяк. Помогите, пожалуйста, разобраться.
oughtem2
Сообщения: 34
Зарегистрирован: 2019.10.26, 20:50

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение oughtem2 »

народ, тут есть кто живой?) помогите, пожалуйста. Если необходимо, я оплачу помощь
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение yiiliveext »

Вы что, не видите, что params не принадлежит товару? Откройте код сформированной страницы и посмотрите как назначаются индексы.
oughtem2
Сообщения: 34
Зарегистрирован: 2019.10.26, 20:50

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение oughtem2 »

Замечание очевидное, но в коде страницы я не вижу ничего странного. Смотрим:

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

<td class="list-cell__params">
	<div class="field-product-91900-params form-group">
		<input type="hidden" name="Product[params]">
		<div id="product-91900-params" class="multiple-input">
			<table class="multiple-input-list table table-condensed table-renderer">
				<thead>
					<tr>
						<th class="list-cell__drag" style="width: 20px;"></th>
						<th class="list-cell__key">Название параметра</th>
						<th class="list-cell__value">Значение</th>
						<th class="list-cell__button"></th>
						<th class="list-cell__button"></th>
					</tr>
				</thead>
				<tbody>
					<tr class="multiple-input-list__item">
						<td class="list-cell__drag">
							<div class="field-product-params-0-drag form-group">
								<span class="glyphicon glyphicon-menu-hamburger drag-handle"></span>
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__key">
							<div class="field-product-params-0-key form-group">
								<input type="text" id="product-params-0-key" class="form-control" name="Product[params][0][key]" value="6666666666" tabindex="1">
								<div class="help-block help-block-error">
								</div>
							</div>
						</td>
						<td class="list-cell__value">
							<div class="field-product-params-0-value form-group"><input type="text" id="product-params-0-value" class="form-control" name="Product[params][0][value]" value="66" tabindex="1">
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-clone btn btn-info">
								<i class="glyphicon glyphicon-duplicate"></i>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-plus btn btn-default">
								<i class="glyphicon glyphicon-plus"></i>
							</div>
						</td>
					</tr>
					<tr class="multiple-input-list__item">
						<td class="list-cell__drag">
							<div class="field-product-params-1-drag form-group">
								<span class="glyphicon glyphicon-menu-hamburger drag-handle"></span>
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__key">
							<div class="field-product-params-1-key form-group">
								<input type="text" id="product-params-1-key" class="form-control" name="Product[params][1][key]" value="777777777" tabindex="1">
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__value">
							<div class="field-product-params-1-value form-group">
								<input type="text" id="product-params-1-value" class="form-control" name="Product[params][1][value]" value="77" tabindex="1">
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-clone btn btn-info">
								<i class="glyphicon glyphicon-duplicate"></i>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-remove btn btn-danger">
								<i class="glyphicon glyphicon-remove"></i>
							</div>
						</td>
					</tr>
					<tr class="multiple-input-list__item">
						<td class="list-cell__drag">
							<div class="field-product-params-2-drag form-group">
								<span class="glyphicon glyphicon-menu-hamburger drag-handle"></span>
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__key">
							<div class="field-product-params-2-key form-group">
								<input type="text" id="product-params-2-key" class="form-control" name="Product[params][2][key]" value="88888888" tabindex="1">
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__value">
							<div class="field-product-params-2-value form-group">
								<input type="text" id="product-params-2-value" class="form-control" name="Product[params][2][value]" value="88" tabindex="1">
								<div class="help-block help-block-error"></div>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-clone btn btn-info">
								<i class="glyphicon glyphicon-duplicate"></i>
							</div>
						</td>
						<td class="list-cell__button">
							<div class="multiple-input-list__btn js-input-remove btn btn-danger">
								<i class="glyphicon glyphicon-remove"></i>
							</div>
						</td>
					</tr>
				</tbody>
			</table>
		</div>
	</div>
</td>
Видно, что сформирован <div class="field-product-91900-params form-group"> , а нём <div id="product-91900-params" class="multiple-input">. Каждый из параметров конкретизирован <div class="field-product-params-1-key form-group">

Да и если бы парамс не принадлежало продукту, то TabularInput и MultipleInput не распознали бы параметры по отдельным продуктам при построении страницы.

Ещё варианты, пожалуйста.
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение yiiliveext »

oughtem2 писал(а): 2019.11.02, 02:35 Замечание очевидное, но в коде страницы я не вижу ничего странного. Смотрим:
Видно, что сформирован <div class="field-product-91900-params form-group"> , а нём <div id="product-91900-params" class="multiple-input">. Каждый из параметров конкретизирован <div class="field-product-params-1-key form-group">

Да и если бы парамс не принадлежало продукту, то TabularInput и MultipleInput не распознали бы параметры по отдельным продуктам при построении страницы.
Вы не туда смотрите.
Это

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

<input type="hidden" name="Product[params]">
должно выглядеть так

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

<input type="hidden" name="Product[128165][params]">
oughtem2
Сообщения: 34
Зарегистрирован: 2019.10.26, 20:50

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение oughtem2 »

рассуждаю логически: если <div class="field-product-91900-params form-group"> содержит айдишник товара, а этот код формируется виджетом MultipleInput, то это значит, что TabularInput своё дело сделал и передал в MultipleInput объект конкретного товара, а вот этот строкой

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

'name' => 'params',
указал, что данные брать из свойства объекта - 'params'. Также успешную передачу из TabularInput в MultipleInput объекта товара подтверждает тот факт, что параметры распознаются виджетом MultipleInput. Соответственно понимаю, что ковырять надо настройки именно MultipleInput.

Учитывая то, что сейчас неверно формируется инпут, касающийся всех параметров одного товара, то понимаю, что искать надо в Base options https://github.com/unclead/yii2-multipl ... se-options. Из всего, что там есть, больше всего конечно для работы подходит rowOptions. Надо покрутить это свойство.

Кроме того, замечу, что инпут должен выглядеть не так

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

<input type="hidden" name="Product[128165][params]">
Моделирование ситуации показало, что если три инпута настроить указанным образом, то $_POST получается такой:

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

Array
(
    [_csrf-backend] => DdVKwq2cm1UUTatTA1nlY2PQ_PUgIYM4h_caWV2YBWZfojit7-7fHk0i-WFiBrYgObLEn2sX6VrxsS4YOLV1Ew==
    [Product] => Array
        (
            [91899] => Array
                (
                    [id] => 91899
                    [name] => Бальзам для губ масляный 10 мл
                    [params] => 
                )

            [params] => Array
                (
                    [0] => Array
                        (
                            [key] => 33333333
                            [value] => 33
                        )

                    [1] => Array
                        (
                            [key] => 444444444
                            [value] => 44
                        )

                    [2] => Array
                        (
                            [key] => 55555555
                            [value] => 55
                        )

                    [3] => Array
                        (
                            [key] => 13
                            [value] => 1313131313
                        )

                    [4] => Array
                        (
                            [key] => 
                            [value] => 
                        )

                )

            [91900] => Array
                (
                    [id] => 91900
                    [name] => ВВ-крем натуральный беж 30 мл
                    [params] => 
                )

            [128165] => Array
                (
                    [id] => 128165
                    [name] => 1051AC-12 Карандаши пластик. "Butterfly" 12 цв., в картоне, европ. J. Otten
                    [params] => 
                )

        )

)
Т.е. все ошибки из первого поста сохранятся, но уже передаётся хоть и не туда, хоть и не 'params'. Себе понял, что надо а) понять, как правильно должен выглядеть этот инпут и разобраться только ли этот инпут влияет на формирование POST, б) под полученный в "а)" результат поэкспериментировать с rowOptions.

Если у кого есть соображения, которые могут мне помочь, то прошу не полениться и их озвучить :)
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение yiiliveext »

oughtem2 писал(а): 2019.11.02, 20:37 Моделирование ситуации показало, что если три инпута настроить указанным образом, то $_POST получается такой:
Потому что это

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

<input type="text" id="product-params-1-key" class="form-control" name="Product[params][1][key]" value="777777777" tabindex="1">
<input type="text" id="product-params-1-value" class="form-control" name="Product[params][1][value]" value="77" tabindex="1">
должно выглядеть так

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

<input type="text" id="product-params-1-key" class="form-control" name="Product[128165][params][1][key]" value="777777777" tabindex="1">
<input type="text" id="product-params-1-value" class="form-control" name="Product[128165][params][1][value]" value="77" tabindex="1">
oughtem2
Сообщения: 34
Зарегистрирован: 2019.10.26, 20:50

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение oughtem2 »

Я проверил и убедился, что если заменить

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

<input type="hidden" name="Product[params]">
на

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

<input type="hidden" name="Product[128165][params]">
и

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

<input type="text" id="product-params-1-key" class="form-control" name="Product[params][1][key]" value="777777777" tabindex="1">
на

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

<input type="text" id="product-params-1-key" class="form-control" name="Product[128165][params][1][key]" value="777777777" tabindex="1">
то генерируется правильный POST, который потом можно будет обработать и сохранить. Стал разбираться и понял, что используя атрибуты MultipleInput я не смогу изменить name по своему желанию. Нужно каким-то образом передать айдишник товара. Помимо собственно вопроса "Как передать?" возникает вопрос "Почему не передаётся?", ведь если посмотреть на массив моделей, то видно, что

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

Array
(
    [91899] => common\models\Product Object
        (
            [imagesFiles] => Array
                (
                )

            [params] => Array
                (
                    [0] => Array
                        (
                            [key] => 11111111
                            [value] => 11
                        )

                    [1] => Array
                        (
                            [key] => 22222222
                            [value] => 22
                        )

                )

            [landings] => Array
                (
                )

            [_attributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id] => 91899
                    [user_id] => 166
                    [name] => Бальзам для губ масляный 10 мл
                    [category_id] => 555
                    [alias] => balzam-dla-gub-maslanyj-10-ml
                    [status] => 1
                    [description] => 
                    [meta_title] => 
                    [meta_keywords] => 
                    [meta_description] => 
                    [h1] => 
                    [available] => -129
                    [keywords] => 
                    [price] => 31
                    [old_price] => 0
                    ...........................
                    
что айдишник - это ключ массива, а значение - объект. Кроме того обращает на себя внимание то, что код генерируется правильно и неправильно вперемешку, т.е. генерируется частично верно.
Изображение

Вобщем в голове каша по этому вопросу.

Вот тут https://stackoverflow.com/questions/518 ... 7#51849747 я нашёл ответ на схожий вопрос, где отвечающий рекомендует создать столбец в основной таблице (у меня Product) и в запихнуть туда связаныне данные (у меня Params) в JSON. Соответственно достать и декодировать. Я не могу по условию создать такой столбец. Смежные данные у меня хранятся в публичном свойстве модели Product.

Прошу помочь разобраться куда мне копать, а соответственно дать подсказки на следующие вопросы:
1. Почему код генерируется частично верно и частично не верно?
2. Понимает ли в данном случае MultipleInput, что TabularInput получив массив $models при формировании строки с товаром передаёт в MultipleInput $model или где-то какой-то настройки не хватает? Если да, то передаётся ли айдишник, связанный с этой конкретной $model и как его выцепить в MultipleInput ?
3. В каком направлении мне двигаться, чтоб верно сформировать name?
yiiliveext
Сообщения: 910
Зарегистрирован: 2019.08.13, 01:49

Re: Сохранение данных при комбинации TabularInput + MultipleInput

Сообщение yiiliveext »

oughtem2 писал(а): 2019.11.09, 17:21 Прошу помочь разобраться куда мне копать, а соответственно дать подсказки на следующие вопросы:
1. Почему код генерируется частично верно и частично не верно?
2. Понимает ли в данном случае MultipleInput, что TabularInput получив массив $models при формировании строки с товаром передаёт в MultipleInput $model или где-то какой-то настройки не хватает? Если да, то передаётся ли айдишник, связанный с этой конкретной $model и как его выцепить в MultipleInput ?
3. В каком направлении мне двигаться, чтоб верно сформировать name?
1. Потому что MultipleInput не знает о существовании TabularInput
2. Не понимает
3. Использовать событие beforeAddEvent для добавления индекса товара
Ответить