Запись в промежуточную таблицу
- onmotion
- Сообщения: 31
- Зарегистрирован: 2015.12.25, 16:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Запись в промежуточную таблицу
Смотрите что происходит в afterSave(). Именно там происходит сохранение вашей реляции. unlinkAll все удаляет, потом link добавляет.
Re: Запись в промежуточную таблицу
Вот такой debug:
приводит к такой ошибке:
а приведенная ниже часть выводится около 800 раз Я где-то не там или как-то не так проверку делаю?
Код: Выделить всё
public function afterSave($insert, $changedAttributes)
{
//обновляем связи с цветами
$this->unlinkAll('colors', true);
foreach($this->colors as $colorId){
$color = Colors::findOne($colorId);
$this->link('colors', $color);
}
debug($this->afterSave($insert, $changedAttributes));
parent::afterSave($insert, $changedAttributes);
}
Код: Выделить всё
Database Exception – yii\db\Exception
PDOStatement::execute(): MySQL server has gone away
The SQL being executed was: DELETE FROM `series_color` WHERE `serie_id`=26
↵
Caused by: yii\base\ErrorException
PDOStatement::execute(): MySQL server has gone away
in D:\OpenServer\domains\site.loc\vendor\yiisoft\yii2\db\Command.php at line 846
Код: Выделить всё
1. in D:\OpenServer\domains\site.loc\vendor\yiisoft\yii2\db\Schema.php at line 636
$exceptionClass = '\yii\db\Exception';
foreach ($this->exceptionMap as $error => $class) {
if (strpos($e->getMessage(), $error) !== false) {
$exceptionClass = $class;
}
}
$message = $e->getMessage() . "\nThe SQL being executed was: $rawSql";
$errorInfo = $e instanceof \PDOException ? $e->errorInfo : null;
return new $exceptionClass($message, $errorInfo, (int) $e->getCode(), $e); // - Здесь ругается
}
/**
* Returns a value indicating whether a SQL statement is for read purpose.
* @param string $sql the SQL statement
* @return bool whether a SQL statement is for read purpose.
*/
public function isReadQuery($sql)
{
2. in D:\OpenServer\domains\site.loc\vendor\yiisoft\yii2\db\Command.php at line 856 – yii\db\Schema::convertException(yii\base\ErrorException, 'DELETE FROM `series_color` WHERE...')
3. in D:\OpenServer\domains\site.loc\vendor\yiisoft\yii2\db\ActiveRecord.php at line 296 – yii\db\Command::execute()
4. in D:\OpenServer\domains\site.loc\vendor\yiisoft\yii2\db\BaseActiveRecord.php at line 1452 – yii\db\ActiveRecord::deleteAll(['serie_id' => 26])
5. in D:\OpenServer\domains\site.loc\modules\secret\models\Series.php at line 63 – yii\db\BaseActiveRecord::unlinkAll('colors', true)
57585960616263646566676869
public function afterSave($insert, $changedAttributes)
{
//обновляем связи с цветами
$this->unlinkAll('colors', true); // - Здесь ругается
foreach($this->colors as $colorId){
$color = Colors::findOne($colorId);
$this->link('colors', $color);
}
6. in D:\OpenServer\domains\site.loc\modules\secret\models\Series.php at line 70 – app\modules\secret\models\Series::afterSave(false, ['category_id' => 11, 'category_price' => 2, 'style' => 1, 'countries' => 1])
64656667686970717273747576
foreach($this->colors as $colorId){
$color = Colors::findOne($colorId);
$this->link('colors', $color);
}
debug($this->afterSave($insert, $changedAttributes)); // - Здесь ругается
parent::afterSave($insert, $changedAttributes);
}
public static function tableName()
Последний раз редактировалось Igor346 2017.04.30, 20:06, всего редактировалось 1 раз.
- onmotion
- Сообщения: 31
- Зарегистрирован: 2015.12.25, 16:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Запись в промежуточную таблицу
Поздравляю, только что вы узнали что такое рекурсия.
Re: Запись в промежуточную таблицу
Спасибо, порекомендуйте как распорядится новыми знаниями. Или еще лучше как все-таки довести обсуждаемый здесь вопрос до логического завершения. Вообще конечно огромное Вам спасибо за то, что возитесь здесь с моим вопросом, я верю, что у нас все получится.
- onmotion
- Сообщения: 31
- Зарегистрирован: 2015.12.25, 16:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Запись в промежуточную таблицу
Уберите этот рекурсивный debug и выясните по какой причине не происходит сохранение в БД. Посмотрите как описана схема в БД и что вы туда пытаетесь записать.
Re: Запись в промежуточную таблицу
Дебаг убрал. Про схему не совсем понял, но работает вообще так:
Поле id в таблице series и поле serie_id в таблице series_color связаны как hasMany; поле id в colors связано с полем color_id в таблице series_color так же hasMany. Руками когда данные вношу в series_color все работает. То, что прописал я можно увидеть в начале топика, то что посоветовали Вы я попробовал (сам не совсем понял, но в общих чертах понимаю, вроде все правильно там, color везде на colors заменил). Ну еще никакая связь с Series и Colors в модели SeriesColor не описана, я дописал но не знаю надо ли. Еще раз просмотрел имена полей в таблицах series, colors и series_color вроде правильно все.
Связь в моделях просмотрел:
Series
Colors
SeriesColor
В модели Colors нашел ошибку(вместо color_id было serie_id), но что удивительно работало все правильно. В остальном ошибок не увидел. Подскажите как посмотреть схему в БД и, что я пытаюсь туда записать?
Также выяснил, что unlink срабатывает, т.е. при обновлении серии где связь руками прописывал, связь из таблицы исчезла. Подозреваю, что в $this->colors что-то не то попадает или скорее ничего не попадает.
Дало:
Хотя результат debug(Yii::$app->request->post()); приходит с выбранными цветами.
Поле id в таблице series и поле serie_id в таблице series_color связаны как hasMany; поле id в colors связано с полем color_id в таблице series_color так же hasMany. Руками когда данные вношу в series_color все работает. То, что прописал я можно увидеть в начале топика, то что посоветовали Вы я попробовал (сам не совсем понял, но в общих чертах понимаю, вроде все правильно там, color везде на colors заменил). Ну еще никакая связь с Series и Colors в модели SeriesColor не описана, я дописал но не знаю надо ли. Еще раз просмотрел имена полей в таблицах series, colors и series_color вроде правильно все.
Связь в моделях просмотрел:
Series
Код: Выделить всё
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Series extends ActiveRecord
{
public function behaviors()
{
return [
'image' => [
'class' => 'rico\yii2images\behaviors\ImageBehave',
]
];
}
static function tableName()
{
return 'series';
}
public function getSeriesColor()
{
return $this->hasMany(SeriesColor::className(), ['serie_id' => 'id']);
}
public function getColors()
{
return $this->hasMany(Colors::className(), ['id' => 'color_id'])->via('seriesColor');
}
Код: Выделить всё
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Colors extends ActiveRecord
{
public function behaviors()
{
return [
'image' => [
'class' => 'rico\yii2images\behaviors\ImageBehave',
]
];
}
public static function tableName()
{
return 'colors';
}
public function getSeriesColor()
{
return $this->hasMany(SeriesColor::className(), ['color_id' => 'id']); // Здесь вместо color_id было serie_id
}
public function getSeries()
{
return $this->hasMany(Series::className(), ['id' => 'serie_id'])->via('seriesColor');
}
}
Код: Выделить всё
<?php
namespace app\models;
use yii\db\ActiveRecord;
class SeriesColor extends ActiveRecord
{
public static function tableName()
{
return 'series_color';
}
public function getSeries()
{
return $this->hasMany(Series::className(), ['id' => 'serie_id']);
}
public function getColors()
{
return $this->hasMany(Colors::className(), ['id' => 'color_id']);
}
}
Также выяснил, что unlink срабатывает, т.е. при обновлении серии где связь руками прописывал, связь из таблицы исчезла. Подозреваю, что в $this->colors что-то не то попадает или скорее ничего не попадает.
Код: Выделить всё
public function afterSave($insert, $changedAttributes)
{
debug($this->colors);
//обновляем связи с цветами
$this->unlinkAll('colors', true);
foreach($this->colors as $colorId){
$color = Colors::findOne($colorId);
$this->link('colors', $color);
}
parent::afterSave($insert, $changedAttributes);
}
Код: Выделить всё
Array
(
)
- onmotion
- Сообщения: 31
- Зарегистрирован: 2015.12.25, 16:03
- Откуда: Санкт-Петербург
- Контактная информация:
Re: Запись в промежуточную таблицу
В валидатор добавьте [['colors'], 'safe']
Re: Запись в промежуточную таблицу
Вы не поверите! Заработало! Почти все, только во view в админской части, не выводится. Над этим подумаю еще. А в остальном все супер, цель достигнута, цвета добавляются и изменяются. СПАСИБО!
Re: Запись в промежуточную таблицу
Если не затруднит подскажите где почитать как правильно выводить прилетевшие массивом цвета в DetailView и вообще как правильно в таком случае поступить? foreach'ем по model->colors внутри открытого php не получается пройтись, какое решение есть и в виде ли нужно это делать или необходимо подготовить данные в модели или контроллере и только вывести их в виде?
-
- Сообщения: 1
- Зарегистрирован: 2020.03.11, 19:32
Re: Запись в промежуточную таблицу
верните свойство $colors , удалите сеттер, или переименнуйте его и добавьте в правила ['colors','safe'],я так понял что косяк в том что в модель не попадает значение
Re: Запись в промежуточную таблицу
Для сохранения в БД нужно (вначале не промежуточная таблица)
Во-1 чтобы была таблица с полями
Во-2 чтобы поля были определены в rules()
Чтобы сохранять в промежуточную через основную.
Во-1 повторяем условия выше
Во-2 должна быть связь в основной таблице к промежуточной, если табуляром сохраняешь, тогда используешь Behavior, где используешь связь с таблицей и название для атрибута
В-3 поле my_tabular должно быть указано в rules как safe
Связь выглядит примерно так в модели
В твоем проекте связь может выглядеть попроще
Для табуляра можешь посмотреть unclead
Можно через список сохранять
ManyToManyBehavior by voskobovich
В модели
Так же в модели
MyModel - это модель, например, с цветами
RelationWithIntermediateTable - это модель, где соединяется цвет с записью в виде строки БД (my_intermediate_id = 1, my_id = 2 (твой цвет), id = 1 (идентификатор какой-то основной таблицы) )
В представлении используется Select2 от kartik-v
И не забываем
Для сохранения информации можно пользоваться разными средствами. Чтобы не заниматься ерундой в afterSave и beforeSave можно использовать Behavior (очень упрощают разработку во многих случаях).
Если же обновление какого-то определенного поля по какой-либо связи, то проще будет через afterSave и beforeSave. Учитывай скорость разработки/доработки, простоту чтения кода и возможности масштабирования твоего кода.
Надеюсь будет полезна информация
Во-1 чтобы была таблица с полями
Во-2 чтобы поля были определены в rules()
Чтобы сохранять в промежуточную через основную.
Во-1 повторяем условия выше
Во-2 должна быть связь в основной таблице к промежуточной, если табуляром сохраняешь, тогда используешь Behavior, где используешь связь с таблицей и название для атрибута
Код: Выделить всё
public function behaviors()
{
return [
'tabularInputBehavior' => [
'class' => TabularInputBehavior::className(),
'fields' => [
'my_tabular' => [
'myRelation',
],
],
],
];
}
Код: Выделить всё
public function rules()
{
return [
[['my_tabular', ], 'safe'],
];
}
Код: Выделить всё
public function getMyRelation(){
return $this->hasMany(MyTable::className(), ['mytable_id' => 'mytable_id'])->from([MyTable::TABLE_ALIAS => MyTable::tableName()]);
}
Код: Выделить всё
public function getMyRelation(){
return $this->hasMany(MyTable::className(), ['mytable_id' => 'mytable_id']);
}
Можно через список сохранять
ManyToManyBehavior by voskobovich
В модели
Код: Выделить всё
public function behaviors()
{
return [
'manyToManyBehavior' => [
'class' => ManyToManyBehavior::className(),
'relations' => [
'my_list' => [
'myRelationList',
],
],
],
];
}
Код: Выделить всё
public function getMyRelationList(){
return $this->hasMany(MyModel::className(), ['my_id' => 'my_id'])->from([MyModel::TABLE_ALIAS => MyModel::tableName()])
->viaTable(RelationWithIntermediateTable::tableName(), ['my_intermediate_id' => 'my_intermediate_id']);
}
RelationWithIntermediateTable - это модель, где соединяется цвет с записью в виде строки БД (my_intermediate_id = 1, my_id = 2 (твой цвет), id = 1 (идентификатор какой-то основной таблицы) )
В представлении используется Select2 от kartik-v
Код: Выделить всё
<?= $form->field($model, 'my_list')->widget(Select2::classname(), [
'theme' => Select2::THEME_KRAJEE,
'model' => $model,
'data' => ArrayHelper::map(MyModel::find()->all(), 'my_id', 'my_filed'),
'options' => [
'multiple' => true,
],
'pluginOptions' => [
'allowClear' => true,
'closeOnSelect' => false,
'placeholder' => \Yii::t('main', 'button.select') . ' ' . \Yii::t('main', 'MyModel'),
],
]) ?>
Код: Выделить всё
public function rules()
{
return [
[['my_list', ], 'safe'],
];
}
Если же обновление какого-то определенного поля по какой-либо связи, то проще будет через afterSave и beforeSave. Учитывай скорость разработки/доработки, простоту чтения кода и возможности масштабирования твоего кода.
Надеюсь будет полезна информация
Re: Запись в промежуточную таблицу
Зачем тратить столько сил для ответа на некропост?