Некорректно работают миграции

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
ДимаК
Сообщения: 33
Зарегистрирован: 2018.02.17, 14:51

Некорректно работают миграции

Сообщение ДимаК »

Почему дублируются записи, в таблице article_tag

Изображение

m180304_112835_create_article_table

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

<?php
 
use yii\db\Migration;
 
/**
* Handles the creation of table `article`.
*/
class m180304_112835_create_article_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function safeUp()
    {
        $this->createTable('article', [
            'id' => $this->primaryKey(),
            'title' => $this->string(),
            'discription' => $this->text(),
            'content' => $this->text(),
            'date' => $this->date(),
            'image' => $this->string(),
            'viewed' => $this->integer(),
            'user_id' => $this->integer(),
            'status' => $this->integer(),
            'category_id' => $this->integer(),
        ]);
    }
 
    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        $this->dropTable('article');
    }
}
m180304_113659_create_category_table

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

<?php
 
use yii\db\Migration;
 
/**
* Handles the creation of table `category`.
*/
class m180304_113659_create_category_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function safeUp()
    {
        $this->createTable('category', [
            'id' => $this->primaryKey(),
            'title' => $this->string()
        ]);
    }
 
    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        $this->dropTable('category');
    }
}
m180304_112914_create_tag_table

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

<?php
 
use yii\db\Migration;
 
/**
* Handles the creation of table `tag`.
*/
class m180304_112914_create_tag_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function safeUp()
    {
        $this->createTable('tag', [
            'id' => $this->primaryKey(),
            'title' => $this->string()
        ]);
    }
 
    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        $this->dropTable('tag');
    }
}
m180304_113052_create_article_tag_table

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

<?php
 
use yii\db\Migration;
 
/**
* Handles the creation of table `article_tag`.
*/
class m180304_113052_create_article_tag_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function safeUp()
    {
        $this->createTable('article_tag', [
            'id' => $this->primaryKey(),
            'article_id'=>$this->integer(),
            'tag_id'=>$this->integer()
        ]);
        // creates index for column `user_id`
        $this->createIndex(
            'tag_article_article_id',
            'article_tag',
            'article_id'
        );
        // add foreign key for table `user`
        $this->addForeignKey(
            'tag_article_article_id',
            'article_tag',
            'article_id',
            'article',
            'id',
            'CASCADE'
        );
        // creates index for column `user_id`
        $this->createIndex(
            'idx_tag_id',
            'article_tag',
            'tag_id'
        );
        // add foreign key for table `user`
        $this->addForeignKey(
            'fk-tag_id',
            'article_tag',
            'tag_id',
            'tag',
            'id',
            'CASCADE'
        );
    }
 
 
    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        $this->dropTable('article_tag');
    }
}
someweb
Сообщения: 552
Зарегистрирован: 2017.03.09, 10:12

Re: Некорректно работают миграции

Сообщение someweb »

А каким боком тут миграции?
Сделайте уникальный ключ на пару

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

            'article_id'=>$this->integer(),
            'tag_id'=>$this->integer()
и не будут дублироваться.
Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа. Роберт Шекли.
ДимаК
Сообщения: 33
Зарегистрирован: 2018.02.17, 14:51

Re: Некорректно работают миграции

Сообщение ДимаК »

someweb писал(а): 2018.03.05, 11:58 А каким боком тут миграции?
Сделайте уникальный ключ на пару

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

            'article_id'=>$this->integer(),
            'tag_id'=>$this->integer()
и не будут дублироваться.
У меня же есть уникальный ключ

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

'id' => $this->primaryKey(),
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

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

'article_id'=>$this->integer()->unique(),
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
lenbord
Сообщения: 49
Зарегистрирован: 2016.01.12, 10:48
Контактная информация:

Re: Некорректно работают миграции

Сообщение lenbord »

Миграции тут не причем, смотрите логику сохранение связей
lenbord
Сообщения: 49
Зарегистрирован: 2016.01.12, 10:48
Контактная информация:

Re: Некорректно работают миграции

Сообщение lenbord »

Dominus писал(а): 2018.03.05, 13:06

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

'article_id'=>$this->integer()->unique(),
так не правильно будет, ибо это таблица связей многие ко многим, нельзя будет создать множество тегов для одной и той же публикации
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

Вообще, правильнее так:

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

$this->createTable('article_tag', [
    'tag_id' => $this->integer()->comment('ID Tag'),
    'article_id' => $this->integer()->comment('ID Article'),    
]);

$this->createIndex('idx_tag_id', 'article_tag', 'tag_id');
$this->createIndex('idx_article_tag', 'article_tag', 'article_id');
// Тут связи
//...
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
lenbord
Сообщения: 49
Зарегистрирован: 2016.01.12, 10:48
Контактная информация:

Re: Некорректно работают миграции

Сообщение lenbord »

Dominus писал(а): 2018.03.05, 13:22 Вообще, правильнее так:

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

$this->createTable('article_tag', [
    'tag_id' => $this->integer()->comment('ID Tag'),
    'article_id' => $this->integer()->comment('ID Article'),    
]);

$this->createIndex('idx_tag_id', 'article_tag', 'tag_id');
$this->createIndex('idx_article_tag', 'article_tag', 'article_id');
// Тут связи
//...
почему это?)
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
lenbord
Сообщения: 49
Зарегистрирован: 2016.01.12, 10:48
Контактная информация:

Re: Некорректно работают миграции

Сообщение lenbord »

Dominus писал(а): 2018.03.05, 13:22 Вообще, правильнее так:

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

$this->createTable('article_tag', [
    'tag_id' => $this->integer()->comment('ID Tag'),
    'article_id' => $this->integer()->comment('ID Article'),    
]);

$this->createIndex('idx_tag_id', 'article_tag', 'tag_id');
$this->createIndex('idx_article_tag', 'article_tag', 'article_id');
// Тут связи
//...
Тут Вы написали, что правильнее сперва индексы создавать, потом внешние ключи
Dominus писал(а): 2018.03.05, 13:30 https://nix-tips.ru/yii2-api-guides/gui ... oj-tablicy
а тут наоборот

в чем заключается "правильность"?
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

Я написал "правильнее", по отношению к предыдущему посту, а не "правильно", не надо к словам придераться. Отражен общий принцип и ссылка на документацию как правильно.

Вообще, у меня так всё работает и не плохо.

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

        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
        }
        //...
       /**
         * Таблица связей Тэг Альбом
         */
        $this->createTable('{{%portfolio_tag_album}}', [
            'tag_id' => $this->integer()->comment('ID Tag'),
            'album_id' => $this->integer()->comment('ID Album'),
        ], $tableOptions);

        $this->createIndex('idx_portfolio_tag', '{{%portfolio_tag_album}}', 'tag_id');
        $this->addForeignKey(
            'FK_portfolio_tag', '{{%portfolio_tag_album}}', 'tag_id', '{{%portfolio_tags}}', 'id'
        );

        $this->createIndex('idx_portfolio_album', '{{%portfolio_tag_album}}', 'album_id');
        $this->addForeignKey(
            'FK_portfolio_album', '{{%portfolio_tag_album}}', 'album_id', '{{%portfolio_albums}}', 'id'
        );
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
lenbord
Сообщения: 49
Зарегистрирован: 2016.01.12, 10:48
Контактная информация:

Re: Некорректно работают миграции

Сообщение lenbord »

Так у автора и так правильно написана миграция, я не пойму зачем Вы подсказываете ему вещи, которые не будут работать так, как ему нужно. У него есть промежуточная таблица и добавление ->unique приведет к тому, что работа приложения будет работать не так, как это задумывалось. Если Вы себя поправили текстом "так будет правильнее", тогда вопросы сняты
chesar
Сообщения: 514
Зарегистрирован: 2013.04.10, 17:49

Re: Некорректно работают миграции

Сообщение chesar »

ДимаК писал(а): 2018.03.05, 11:53 Почему дублируются записи, в таблице article_tag

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

$this->createIndex('uq_article_tag', 'article_tag', ['article_id', 'tag_id'], true);
andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: Некорректно работают миграции

Сообщение andku83 »

не увидел у вас добавления основного ключа в таблицу связей:

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

$this->addPrimaryKey('pk-portfolio_tag_album', '{{%portfolio_tag_album}}', ['tag_id', 'album_id']);
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

shnir писал(а): 2018.03.05, 14:09 не увидел у вас добавления основного ключа в таблицу связей:

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

$this->addPrimaryKey('pk-portfolio_tag_album', '{{%portfolio_tag_album}}', ['tag_id', 'album_id']);
В этом случае значения полей 'tag_id', 'album_id' должны будут быть уникальными, логика приложения требует обратного.
tag_id - это значение ID из таблицы portfolio_tags
album_id - это значение ID из таблицы portfolio_albums

Связь в PortfolioAlbums

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

/**
     * @return \yii\db\ActiveQuery
     */
    public function getPortfolioTagAlbums()
    {
        return $this->hasMany(PortfolioTagAlbum::className(), ['album_id' => 'id']);
    }
Ткая же и в PortfolioTags

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

/**
     * @return \yii\db\ActiveQuery
     */
    public function getPortfolioTagAlbums()
    {
        return $this->hasMany(PortfolioTagAlbum::className(), ['tag_id' => 'id']);
    }
В модели PortfolioAlbums тэги сохраняются в методе afterSave()

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

    /**
     * Список тэгов, закреплённых за альбомом.
     * @var array
     */
    protected $tags = [];
    
    //...
    
public function afterSave($insert, $changedAttributes)
    {
        if (is_array($this->tags) && !empty($this->tags)) {
            PortfolioTagAlbum::deleteAll(['album_id' => $this->id]);
            $values = [];
            foreach ($this->tags as $id) {
                $values[] = [$this->id, $id];
            }
            self::getDb()->createCommand()
                ->batchInsert(PortfolioTagAlbum::tableName(), ['album_id', 'tag_id'], $values)->execute();
        }
        parent::afterSave($insert, $changedAttributes);
    }
Ну и получение самих тэгов

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

/**
     * Устанавлиает тэги.
     * @param $tagsId
     */
    public function setTags($tagsId)
    {
        $this->tags = (array)$tagsId;
    }

    /**
     * Возвращает массив идентификаторов тэгов.
     */
    public function getTags()
    {
        return ArrayHelper::getColumn(
            $this->getPortfolioTagAlbums()->all(), 'tag_id'
        );
    }

    /**
     * Возвращает теги ввиде ссылок
     * @return array
     */
    public function getTagLinks()
    {
        $links = [];
        /** @var  $tag \modules\portfolio\models\PortfolioTagAlbum::getTag() */
        foreach ($this->getPortfolioTagAlbums()->all() as $tag) {
            if ($tag->tag_id !== null) {
                $links[] = Html::a(Html::encode($tag->getTag()->one()->title), Url::to(['/portfolio/default/index', 'tag' => $tag->getTag()->one()->title]));
            }
        }
        return $links;
    }

    /**
     * Возвращает теги ввиде строки
     * @return array
     */
    public function getTagStrings()
    {
        $links = [];
        /** @var  $tag \modules\portfolio\models\PortfolioTagAlbum::getTag() */
        foreach ($this->getPortfolioTagAlbums()->all() as $tag) {
            if ($tag->tag_id !== null) {
                $links[] = $tag->getTag()->one()->title;
            }
        }
        return $links;
    }
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: Некорректно работают миграции

Сообщение andku83 »

Dominus писал(а): 2018.03.05, 14:46 В этом случае значения полей 'tag_id', 'album_id' должны будут быть уникальными, логика приложения требует обратного.
tag_id - это значение ID из таблицы portfolio_tags
album_id - это значение ID из таблицы portfolio_albums
либо вы невнимательны, либо не знаете что такое составной Primary Key
в данном случае уникальность проверяется по комбинации tag_id и album_id
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

shnir писал(а): 2018.03.05, 15:04
Dominus писал(а): 2018.03.05, 14:46 В этом случае значения полей 'tag_id', 'album_id' должны будут быть уникальными, логика приложения требует обратного.
tag_id - это значение ID из таблицы portfolio_tags
album_id - это значение ID из таблицы portfolio_albums
либо вы невнимательны, либо не знаете что такое составной Primary Key
в данном случае уникальность проверяется по комбинации tag_id и album_id
Вопрос в другом, он там нужен?)) Если всё работает и без этого.
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: Некорректно работают миграции

Сообщение andku83 »

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

        foreach ($this->getPortfolioTagAlbums()->all() as $tag) {
            if ($tag->tag_id !== null) {
                $links[] = $tag->getTag()->one()->title;
            }
        }
а вот такой код я бы менял на такое - читабельнее и намного меньше запросов к БД(в предыдущей функции тоже его обновить не помешало бы):

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

        foreach ($this->getPortfolioTagAlbums()->with('tags')->all() as $tag) {
                $links[] = $tag->tag->title;
        }
проверку на существование `if ($tag->tag_id !== null) {` специально убрал, если она вам необходима, значит что-то неправильно у вас организовано, у вас не должно быть записей в связующей таблице для несуществующих тегов
Последний раз редактировалось andku83 2018.03.05, 15:11, всего редактировалось 1 раз.
andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: Некорректно работают миграции

Сообщение andku83 »

Dominus писал(а): 2018.03.05, 15:07 Вопрос в другом, он там нужен?)) Если всё работает и без этого.
если вас устраивает ситуация в которой у вас может оказаться несколько одинаковых тегов и вас не волнует правильность хранения данных...
Аватара пользователя
Dominus
Сообщения: 892
Зарегистрирован: 2013.03.14, 21:27
Откуда: Россия, Иваново
Контактная информация:

Re: Некорректно работают миграции

Сообщение Dominus »

Не окажется, так как теги перед добавлением удаляются в afterSave()
PortfolioTagAlbum::deleteAll(['album_id' => $this->id]);
То есть перезаписываются, но сперва удаляются старые.
Последний раз редактировалось Dominus 2018.03.05, 15:15, всего редактировалось 1 раз.
Не спорь с дураком, иначе окружающие не правильно поймут кто из вас дурак!
Ответить