Eloquent: за и против

Eloquent: за и против

CodeWay | https://t.me/code_way

Как и в любом серьёзном фреймворке, в Laravel есть встроенная ORM — она называется Eloquent. Предполагается, что разработчик будет использовать именно её. Но хороший специалист всегда знает границы применимости своих инструментов. Потому давайте разберёмся, какие за и против есть у этой ORM. 

За

  1. Не требуются никакие дополнительные пакеты. Не нужно ничего искать, выбирать, подключать, разбираться. Если у вас Laravel, то и Eloquent уже в комплекте, и, скорее всего, вы изучили, как работать с этой ORM, когда изучали сам фреймворк.
  2. На выходе — типизированные объекты. В этом смысле Eloquent (как и любая ORM) удобнее, чем построитель запросов, возвращающий сырые данные в виде коллекции stdClass-ов.
  3. Лёгкое создание моделей. В простейшем случае достаточно консольной команды php artisan make:model {название модели}, максимум понадобится уточнить имя базовой таблицы, и с ней уже можно работать.
  4. Простое получение актуальных моделей в маршрутах. Фреймворк даёт возможность получать нужную модель за счёт внедрения зависимостей. Например, в маршруте написано /article/{id}, в обработчике достаточно чего-то такого: public function show(Article $article). Laravel сам найдёт нужную модель и передаст в метод.
  5. Наличие удобного функционала в самих моделях. Можно назвать целый ряд полезных возможностей, вроде автоматического преобразования данных из БД в нужный тип или вычисляемых полей. 

Против 

  1. Модель — обёртка для таблицы. Eloquent исходит из принципа Active Record — работа над моделью = работа над записью в таблице. В результате ORM не знает даже точных имён полей и просто пробрасывает обращения к свойствам в соответствующую таблицу. Из этого два негативных следствия: 1) при разработке никаких подсказок по полям, изволь сверяться с БД; 2) если нужно поменять имя поля, придётся перерыть весь код, где теоретически могут быть обращения к этой модели.
  2. ORM поощряет работу с виртуальными полями. Как вы понимаете, все поля модели, приходящие из БД — виртуальные, они нигде не описываются и получаются магически. Вы даже можете записать в модель свои собственные виртуальные поля — но сохранить вам её не удастся: ORM радостно попытается всё записать в таблицу (как мы помним, списка полей таблицы у неё нет), а та уже выдаст ошибку из серии “Поле не найдено”.
  3. Eloquent слишком полагается на типовые механизмы. Если у вас типовые названия таблиц, ключевых полей и тому подобное, то всё остальное ORM додумает сама. Но если нет, то большой боли вам не избежать, например, при настройке связей. Причём никаких ошибок не будет выдаваться, просто будете получать пустую коллекцию, ломая голову на тему “Что не так-то?”. В документации нетиповые случаи обычно не описаны, приходится прибегать к методу научного тыка, тратя время и нервы.
  4. Неоптимальная работа со связанными данными. Пробовали когда-нибудь получать данные связанных моделей через with()? Если нет, поверьте, происходит это очень медленно. Если же нужна связь третьего уровня из серии user->posts->comments(такое бывает), то чувство печали становится невыносимым.
  5. Нарушение SOLID. Если специфичная для сущности логика как-то абстрагируется в проекте, она обычно помещается в модель за неимением лучшего. Если, допустим, связи и скоупы напрямую связаны с непосредственным предназначением модели (работа с БД), то вот бизнес-логика — уже не совсем её профиль. Для примера возьмём ту же модель Article (статья). Нужно где-то проверять, может ли данный пользователь редактировать данную статью. Пишется метод Article::canBeEditedBy(User $user) или User::canEdit(Article $article) и помещается в соответствующую модель. Этого нарушения можно избежать путём использования отдельных классов-сущностей, содержащих только бизнес-логику, а модели Eloquent оставить для связи с БД. 

Итоги 

Eloquent оптимизирована для лёгкого начала работы с фреймворком и для простых проектов, в этом ей нет равных. Если же планируется мало-мальски сложная бизнес-логика, подумайте, нужно ли оно вам, и если да — как нивелировать перечисленные недостатки. Варианты есть, будь то другая ORM, чистый построитель запросов, добавление классов-сущностей — главное, исходить из применимости инструментов. Это как раз то, с чего я начал пост

Report Page