Жить без миграций Laravel // Yii2

AmdY

Пью пиво
Команда форума
Ой, база данных в неатомарном состоянии, как же такое могло случиться? В принципе в сообщении об ошибке всё должно быть сказано.
 

StalkerClasses

Новичок
Ой, база данных в неатомарном состоянии, как же такое могло случиться? В принципе в сообщении об ошибке всё должно быть сказано.
Вот моя структура БД:
SQL:
-- Adminer 4.8.1 MySQL 5.5.23 dump

SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

SET NAMES utf8mb4;

DROP TABLE IF EXISTS `technologies`;
CREATE TABLE `technologies` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `_lft` int(10) unsigned NOT NULL DEFAULT '0',
  `_rgt` int(10) unsigned NOT NULL DEFAULT '0',
  `parent_id` int(10) unsigned DEFAULT NULL,
  `branch_type` int(11) NOT NULL DEFAULT '0',
  `branch_stop_flag` int(11) NOT NULL DEFAULT '0',
  `is_page_flag` int(11) NOT NULL DEFAULT '0',
  `is_draft_flag` int(11) NOT NULL DEFAULT '0',
  `user_id` bigint(20) unsigned DEFAULT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `slug` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `description` text COLLATE utf8mb4_unicode_ci,
  `description_tinymce` text COLLATE utf8mb4_unicode_ci,
  `logo_image` text COLLATE utf8mb4_unicode_ci,
  `sorting` int(11) NOT NULL DEFAULT '0',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `table_technologies__lft__rgt_parent_id_index` (`_lft`,`_rgt`,`parent_id`),
  KEY `technology_user_idx` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `technologies` (`id`, `_lft`, `_rgt`, `parent_id`, `branch_type`, `branch_stop_flag`, `is_page_flag`, `is_draft_flag`, `user_id`, `name`, `slug`, `description`, `description_tinymce`, `logo_image`, `sorting`, `created_at`, `updated_at`) VALUES
(100,    108,    109,    10,    0,    0,    0,    1,    1,    'Prof.',    NULL,    'Id est dolorum sed consequatur est fugit. Libero qui laborum officia eum nihil. Amet sunt ratione ipsa numquam incidunt totam est.',    'Expedita pariatur blanditiis sit. Nesciunt deserunt veritatis sit necessitatibus delectus praesentium ea rerum. Et sit enim ut voluptatum et voluptate ut. Qui voluptatem voluptatem ut.',    NULL,    0,    '2022-03-26 16:07:34',    '2022-03-26 16:07:52');

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email_verified_at` timestamp NULL DEFAULT NULL,
  `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `role` smallint(5) unsigned DEFAULT NULL,
  `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `role`, `remember_token`, `created_at`, `updated_at`) VALUES
(1,    'My',    '[email protected]',    NULL,    '$2y$10$tox2a74LvJDRDjHbiJNB4eVuQVM4axnhRvGCGBnucaa9Y5Csty.v6',    1,    NULL,    '2022-03-26 16:07:18',    '2022-03-26 16:07:18');

-- 2022-03-27 07:40:48
Стоило мне это
$table->foreign('user_id', 'technology_user_fk')
->references('id')
->on('users')
;

поменять на это (название индекса FK из таблиц во множественном числе) и все стало работать (связь FK создается)
$table->foreign('user_id', 'technologies_users_fk')
->references('id')
->on('users');


Соответственно и SQL-запрос поменялся:
ALTER TABLE technologies ADD CONSTRAINT technologies_users_fk
FOREIGN KEY (user_id) REFERENCES users (id)

Но я не пойму у меня почему-то после выполнения этого запроса создается +1 таблица (table_technologies).
Это он так рез. копию что ли делает при создании внешний ключей когда в таблице есть данные?
 

StalkerClasses

Новичок
В общем суть проблемы: у меня почему при выполнении миграции создается таблица table_technologies...
Откуда она берется не могу понять.
И из-за этого вылазит вот такая ошибка:

PHP:
PS C:\php\public_html_laravel> php artisan migrate:auto
Nothing to migrate.
Doctrine\DBAL\Query Object
(
    [sql:Doctrine\DBAL\Query:private] => ALTER TABLE technologies ADD CONSTRAINT technologies_users_fk FOREIGN KEY (user_id) REFERENCES users (id)
    [params:Doctrine\DBAL\Query:private] => Array
        (
        )

    [types:Doctrine\DBAL\Query:private] => Array
        (
        )

)

   Doctrine\DBAL\Exception\DriverException

  An exception occurred while executing a query: SQLSTATE[HY000]: General error: 1005 Can't create table 'tech.#sql-1070_356' (errno: 121)

  at C:\php\public_html_laravel\vendor\doctrine\dbal\src\Driver\API\MySQL\ExceptionConverter.php:120
    116▕                 return new NotNullConstraintViolationException($exception, $query);
    117▕         }
    118▕
    119▕         print_r($query);
  ➜ 120▕         return new DriverException($exception, $query);
    121▕     }
    122▕ }
    123▕
�� }
    123▕


  1   C:\php\public_html_laravel\vendor\doctrine\dbal\src\Connection.php:1813
      Doctrine\DBAL\Driver\API\MySQL\ExceptionConverter::convert(Object(Doctrine\DBAL\Driver\PDO\Exception), Object(Doctrine\DBAL\Query))

  2   C:\php\public_html_laravel\vendor\doctrine\dbal\src\Connection.php:1748
      Doctrine\DBAL\Connection::handleDriverException(Object(Doctrine\DBAL\Driver\PDO\Exception), Object(Doctrine\DBAL\Query))

Хотя вот этот запрос он рабочий если его выполнить через тот же phpMyAdmin
[sql:Doctrine\DBAL\Query:private] => ALTER TABLE technologies ADD CONSTRAINT technologies_users_fk FOREIGN KEY (user_id) REFERENCES users (id)

Откуда он берет вот эту таблицу ума не приложу? У меня ее нет. table_technologies
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
А потом у нас выяснится, что имя ключа не уникальное
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Потому, наверное, что ты не прослеживаешь причинно-следственную связь

>>> поменять на это (название индекса FK из таблиц во множественном числе) и все стало работать (связь FK создается)

Это ты писал, или нет?
 

StalkerClasses

Новичок
Не работает это со внешними ключами - судя по всему.

+ какая-то временная таблица создается при создании внешних ключей...
зачем не понятно.
 

StalkerClasses

Новичок
Вся загвоздка в этом коде:

PHP:
    protected function migrateModel(Model $model)
    {
        $modelTable = $model->getTable();
        $tempTable = 'table_' . $modelTable;

        Schema::dropIfExists($tempTable);

        Schema::create($tempTable, function (Blueprint $table) use ($model) {
            $model->migration($table);
        });

        if (Schema::hasTable($modelTable)) {
            $manager = $model->getConnection()->getDoctrineSchemaManager();
            $diff = (new Comparator)->diffTable($manager->listTableDetails($modelTable), $manager->listTableDetails($tempTable));

            if ($diff) {
                $manager->alterTable($diff);

                $this->line('<info>Table updated:</info> ' . $modelTable);
            }

            Schema::drop($tempTable);
        } else {
            Schema::rename($tempTable, $modelTable);

            $this->line('<info>Table created:</info> ' . $modelTable);
        }
    }
Я не могу понять если он создает два одинаковых внешник ключа с одним и тем же именем но для 2 разных таблиц это ошибка?
 

StalkerClasses

Новичок
Не могу понять 1) в 1 базе данных может быть два внешних ключа с одним и тем же именем и 2) есть ли ограничение на число символов в названии внешнего ключа?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Не можешь понять, почитай мануал уже наконец, станет ясно, что 1- нет и 2 - да (64), и не только внешнего
 

StalkerClasses

Новичок
Сори за нубскмк вопросы. С внешними ключами разобрались. Они должны быть уникальными.

А с индексами также? Я никогда не работал с индексами и внешними ключами.

Я все таки решил попробовать сделать свой форк автомиграций. Его разница будет в том, что он будет создавать индексы и внешние ключи после создания и обновления структур таблиц.
 

Тугай

Новичок
Уникальность имени для внешних ключей и индексов зависит от движка базы данных.

В PostgreSQL имя CONSTRANIT уникально на уровне таблицы, в MySQL на уровне бд.
С индесами наоборот в PostgreSQL, Oracle у индексов свой namespace и все индексы должны быть с уникальными именами на уровне схемы, а в MySQL, MS SQL уникальность на уровне таблицы.
 

StalkerClasses

Новичок
Уникальность имени для внешних ключей и индексов зависит от движка базы данных.

В PostgreSQL имя CONSTRANIT уникально на уровне таблицы, в MySQL на уровне бд.
С индесами наоборот в PostgreSQL, Oracle у индексов свой namespace и все индексы должны быть с уникальными именами на уровне схемы, а в MySQL, MS SQL уникальность на уровне таблицы.
Поэтому он и отдаёт телексы без проблем, а внешние ключи не может создать., так как дублируется название.
 

StalkerClasses

Новичок
Плюс насколько я понимаю что бы создать внешние ключи вам нужно создать три миграции

1 миграция создаст таблицу 1
2 миграция создаст таблицу 2
3 миграцмя уже создаст внешние ключи.

По другому никак.
 

StalkerClasses

Новичок
Плюс насколько я понимаю что бы создать внешние ключи вам нужно создать три миграции

1 миграция создаст таблицу 1
2 миграция создаст таблицу 2
3 миграцмя уже создаст внешние ключи.

По другому никак.
Насколько понимаю это так. Если вы в какой то из миграций создаёте fk то эта таблица к которой идёт fk уже должна существовать, а бывает так что Ее ещё не существует, она только будет создана в следующей миграции.
 

AmdY

Пью пиво
Команда форума
Плюс насколько я понимаю что бы создать внешние ключи вам нужно создать три миграции

1 миграция создаст таблицу 1
2 миграция создаст таблицу 2
3 миграцмя уже создаст внешние ключи.

По другому никак.
наоборот, э
то надо делать в одной миграции, чтобы изменения были атомарны. А то будут проблемы как у тебя. Надо понимать проблему яйца и курицы, что на первую таблицу нельзя повесить внешние ключи на вторую таблицу, которая ещё не создана.
 

StalkerClasses

Новичок
Вопрос немного не в тему - но про внешние ключи... Как бы.
Вот для связей есть внешние ключи...

Изображения и файлы можно хранить в полях
например так:

id | name | logo_image
1 | record-1 | image-1.png
2 | record-2 | image-2.png
3 | record-3 | image-3.png

id | name | images
1 | record-1 | image-1.png,image-2.png,image-3.png
2 | record-2 | null
3 | record-3 | null

Есть ли такое понятие в БД как внешние ключи для файлов?
Т.е. если удаляем запись - вместе с ней удаляются и файлы, которые к ней прикреплены...
Где можно вообще про хранение файлов в БД почитать применительно к MySQL?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Нету такого, пишется руками такая связь как строка в бд и физический файлик. Файлы в БД не хранятся, хранятся ссылки на них
 
Сверху