Введение
Да, вместо того, чтобы ручками писать все эти скрипты миграций и в особенности классы моделей их лучше просто генерить в одно мгновение, а ни сидеть, копипастить туда-сюда названия полей и т.п. Называется всё это термином database reverse engineering, который, как и технология судя по всему не очень то прижился, а совершенно напрасно. Под reverse engineering’ом обычно понимается генерация моделей/сущностей на основе таблиц БД. Но для Laravel есть ещё и кодогенераторы миграций.
Вообще, насколько я помню, и у Doctrine когда-то был подобный функционал, но судя по этой записи либо его уже нет, либо он куда-то мигрировал в Symfony. Если вы что-то знаете о судьбе этой фичи в Doctrine напишите пожалуйста в комментариях. Так же напишите как обстоят дела с кодогенераций в других фреймворках и языках программирования, посмотрим на реалии.
Инструменты
Для своих проектов на Laravel я использую следующие инструменты:
-
kitloong/laravel-migrations-generator для генерации миграций
-
reliese/laravel для генерации моделей
Не потому что они лучшие или худшие, просто они делают то, что мне нужно, но возможно есть и другие. Рассмотрим оба подробнее.
kitloong/laravel-migrations-generator
Основное назначение инструмента — это нагенерить миграций по уже существующей БД. Если у вас нет таблиц в БД, по которым нет миграций, то соответственно инструмент вам и не нужен. А нужен он может быть, например, когда:
-
Вы разрабатываете новый проект и создаёте таблицы непосредственно в БД при помощи DDL-запросов а-ля CREATE TABLE… И в какой-то момент обнаруживаете, что у вас уже там N таблиц и писать под них миграции как-то уже совсем не хочется.
-
Вы опять разрабатываете новый проект, почти такой, как тот. Вот действительно на днях была задача просто скопипастить часть микросервиса в другой микросервис. Т.к. таблицы эволюционируют то получается, что в коде копируемого проекта просто нет миграции, описывающей какую-либо таблицу в её нынешнем состоянии, а есть миграция с CREATE TABLE… и куча миграций с ALTER’ами. В таком случае проще перетащить таблицы в виде DDL-запросов в новую БД и опять же нагенерить по ним миграций.
-
Ваш вариант…
Инструмент работает прямо из коробки, никакой дополнительной конфигурации не требуется.
Устанавливаете:
composer require --dev kitloong/laravel-migrations-generator
Запускаете согласно документации:
php artisan migrate:generate
И обнаруживаете в папке database/migrations
маленький презент. Всё.
reliese/laravel
Этот инструмент про классический database reverse engineering — генерацию сущностей БД, которыми в Laravel являются классы-модели. И в Laravel есть инструмент, который генерит модели, но он генерит пустышки, которые вам предстоит заполнить вручную. Это не по-пацански, нужно генерить готовый код, пачками.
Устновка:
composer require --dev reliese/laravel
После установки пакета нужно затащить в проект его конфиг:
php artisan vendor:publish --tag=reliese-models
После этого в папке config
обнаружится файл models.php
. Это конфиг пакета. Далее рекомендуется почистить кэш:
php artisan config:clear
И если я не ошибаюсь, после этого можно запускать генератор так:
php artisan code:models
После этого он перезатрёт вам все ваши уже имеющиеся на данный момент модели. Ха-ха-ха. Конечно, если таковые были. И это будет происходить каждый раз, когда вы будете запускать кодогенерацию. Выглядит как несусветная тупость. И эту проблему можно легко обойти, если в конфиге указать true
для опции base_files
. Тогда на каждую таблицу будет генериться по два файла:
-
Обычный класс модели в
app/Models
. Например для таблицыusers
БД будет создан классapp/Models/User.php
. Если такой файл уже есть, то кодогенератор его не перезатрёт. Таким образом решается проблема описанная выше. -
Родительский класс
app/Models/Base/User.php
классаapp/Models/User.php
. Вы будете писать свой код вapp/Models/User.php
, а кодогенератор будет писать вapp/Models/Base/User.php
. Таким образом вы никогда не перетрёте изменения друг друга.
Можно фильтровать таблицы т.е. генерировать модели не для всех. Можно даже указать другую папку, куда будут писаться новые классы. Т. о. инструмент можно внедрить в уже существующий проект и забыть про ручное написание моделей. Поменялось что-то в БД — перегенерили модели за 0.5 секунды и едем дальше.
Ещё одна интересная опция — with_property_constants
. Если указано true
, то в классы будут добавлены одноимённые колонкам таблицы константы, вот пример:
<?php /** * Created by Reliese Model. */ namespace App\Models\Base; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; /** * Class ContactMessage * * @property int $id * @property string|null $name * @property string $email * @property string $message * @property int|null $ip_address * @property Carbon|null $created_at * * @package App\Models\Base */ class ContactMessage extends Model { const ID = 'id'; const NAME = 'name'; const EMAIL = 'email'; const MESSAGE = 'message'; const IP_ADDRESS = 'ip_address'; const CREATED_AT = 'created_at'; protected $table = 'contact_messages'; public $timestamps = false; public static $snakeAttributes = false; protected $columns = [ 'id', 'name', 'email', 'message', 'ip_address', 'created_at' ]; protected $casts = [ self::ID => 'int', self::IP_ADDRESS => 'int', self::CREATED_AT => 'datetime' ]; protected $fillable = [ self::NAME, self::EMAIL, self::MESSAGE, self::IP_ADDRESS ]; }
Вот с 26 по 31 строки они. А вот так, к слову, выглядит «ваш» свежеиспечённый класс, куда вы будете писать свой код:
<?php namespace App\Models; use App\Models\Base\ContactMessage as BaseContactMessage; class ContactMessage extends BaseContactMessage { }
Вы можете спросить, зачем нужны эти константы? Для чистоты кода, чтобы ссылаться на константы классов, не плодить магические числа, типа:
$array['name'] = $data['name'];
С константами будет ясен контекст, про какой/чей name
идёт речь. И здесь следует упомянуть ещё такой PHP’ый инструмент как PHP Magic Number Detector (PHPMND) — это собственно детектор магических чисел. По дефолту он ищет только именно числа, вот пример работы:
Но если запустить его с опцией --strings
, то детектор будет искать не только свободно плавающие по коду числа, но и строки (узнаёте код своего проекта?):
Пример выше к сожалению не про константы из класса-модели, но суть я думаю ясна. Спасибо за внимание. Так же предлагаю вам пройти простой опрос и выиграть мощную тачку от Тимати.
P.S. Тут мне вспомнилось, что есть ещё другая фича c кодогенерацией в ORM — это генерация таблиц по уже существующим классам моделей. Не помню где видел такое, но кажется и никогда не пользовался. Знаете ли вы что-нибудь об этом? Напишите в комментариях, если вдруг.
ссылка на оригинал статьи https://habr.com/ru/articles/861584/
Добавить комментарий