Laravel 5 Хорошие практики в Laravel

 Laravel 5

laravel

Хорошие практики в Laravel

Источник: https://github.com/alexeymezenin/laravel-best-practices

Это не пересказ лучших практик вроде SOLID, паттернов и пр. с адаптацией под Laravel. Здесь собраны именно практики, которые игнорируются в реальных Laravel проектах. Также, рекомендую ознакомитсья с хорошими практиками в контексте PHP. Смотрите также обсуждение хороших практик Laravel.

Принцип единственной ответственности (Single responsibility principle)

Каждый класс и метод должны выполнять лишь одну функцию.

Плохо:

Хорошо:

Тонкие контроллеры, толстые модели

По своей сути, это лишь один из частных случаев принципа единой ответственности. Выносите работу с данными в модели при работе с Eloquent или в репозитории при работе с Query Builder или "сырыми" SQL запросами.

Плохо:

Хорошо:

 

Валидация

Следуя принципам тонкого контроллера и SRP, выносите валидацию из контроллера в Request классы.

Плохо:

Хорошо:

 

Бизнес логика в сервис-классах

Контроллер должен выполнять только свои прямые обязанности, поэтому выносите всю бизнес логику в отдельные классы и сервис классы.

Плохо:

Хорошо:

 

Не повторяйся (DRY)

Этот принцип призывает вас переиспользовать код везде, где это возможно. Если вы следуете принципу SRP, вы уже избегаете повторений, но Laravel позволяет вам также переиспользовать представления, части Eloquent запросов и т.д.

Плохо:

Хорошо:

 

Предпочитайте Eloquent конструктору запросов (query builder) и сырым запросам в БД. Предпочитайте работу с коллекциями работе с массивами

Eloquent позволяет писать максимально читаемый код, а изменять функционал приложения несоизмеримо легче. У Eloquent также есть ряд удобных и мощных инструментов.

Плохо:

Хорошо:

 

Используйте массовое заполнение (mass assignment)

Плохо:

Хорошо:

 

Не выполняйте запросы в представлениях и используйте нетерпеливую загрузку (проблема N + 1)

Плохо (будет выполнен 101 запрос в БД для 100 пользователей):

Хорошо (будет выполнено 2 запроса в БД для 100 пользователей):

 

Комментируйте код, предпочитайте читаемые имена методов комментариям

Плохо:

Лучше:

Хорошо:

 

Выносите JS и CSS из шаблонов Blade и HTML из PHP кода

Плохо:

Лучше:

В Javascript файле:

Еще лучше использовать специализированный пакет для передачи данных из бэкенда во фронтенд.

 

Конфиги, языковые файлы и константы вместо текста в коде

Непосредственно в коде не должно быть никакого текста.

Плохо:

Хорошо:

 

Используйте инструменты и практики принятые сообществом

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

Задача Стандартные инструмент Нестандартные инструмент
Авторизация Политики Entrust, Sentinel и др. пакеты, собственное решение
Работа с JS, CSS и пр. Laravel Mix Grunt, Gulp, сторонние пакеты
Среда разработки Homestead Docker
Разворачивание приложений Laravel Forge Deployer и многие другие
Тестирование Phpunit, Mockery Phpspec
e2e тестирование Laravel Dusk Codeception
Работа с БД Eloquent SQL, построитель запросов, Doctrine
Шаблоны Blade Twig
Работа с данными Коллекции Laravel Массивы
Валидация форм Request классы Сторонние пакеты, валидация в контроллере
Аутентификация Встроенный функционал Сторонние пакеты, собственное решение
Аутентификация API Laravel Passport Сторонние пакеты, использующие JWT, OAuth
Создание API Встроенный функционал Dingo API и другие пакеты
Работа со структурой БД Миграции Работа с БД напрямую
Локализация Встроенный функционал Сторонние пакеты
Обмен данными в реальном времени Laravel Echo, Pusher Пакеты и работа с веб сокетами напрямую
Генерация тестовых данных Seeder классы, фабрики моделей, Faker Ручное заполнение и пакеты
Планирование задач Планировщик задач Laravel Скрипты и сторонние пакеты
БД MySQL, PostgreSQL, SQLite, SQL Server MongoDb

 

Соблюдайте соглашения сообщества об именовании

Следуйте стандартам PSR при написании кода.

Также, соблюдайте другие cоглашения об именовании:

Что Правило Принято Не принято
Контроллер ед. ч. ArticleController ArticlesController
Маршруты мн. ч. articles/1 article/1
Имена маршрутов snake_case users.show_active users.show-active, show-active-users
Модель ед. ч. User Users
Отношения hasOne и belongsTo ед. ч. articleComment articleComments, article_comment
Все остальные отношения мн. ч. articleComments articleComment, article_comments
Таблица мн. ч. article_comments article_comment, articleComments
Pivot таблица имена моделей в алфавитном порядке в ед. ч. article_user user_article, articles_users
Столбец в таблице snake_case без имени модели meta_title MetaTitle; article_meta_title
Внешний ключ имя модели ед. ч. и _id article_id ArticleId, id_article, articles_id
Первичный ключ - id custom_id
Миграция - 2017_01_01_000000_create_articles_table 2017_01_01_000000_articles
Метод camelCase getAll get_all
Метод в контроллере ресурсов таблица store saveArticle
Метод в тесте camelCase testGuestCannotSeeArticle test_guest_cannot_see_article
Переменные camelCase $articlesWithAuthor $articles_with_author
Коллекция описательное, мн. ч. $activeUsers = User::active()->get() $active, $data
Объект описательное, ед. ч. $activeUser = User::active()->first() $users, $obj
Индексы в конфиге и языковых файлах snake_case articles_enabled ArticlesEnabled; articles-enabled
Представление snake_case show_filtered.blade.php showFiltered.blade.php, show-filtered.blade.php
Конфигурационный файл snake_case google_calendar.php googleCalendar.php, google-calendar.php
Контракт (интерфейс) прилагательное или существительное Authenticatable AuthenticationInterface, IAuthentication
Трейт прилагательное Notifiable NotificationTrait

 

Короткий и читаемый синтаксис там, где это возможно

Плохо:

Хорошо:

Еще примеры:

Часто используемый синтаксис Более короткий и читаемый синтаксис
Session::get('cart') session('cart')
$request->session()->get('cart') session('cart')
Session::put('cart', $data) session(['cart' => $data])
$request->input('name') $request->name
Request::get('name') request('name')
return Redirect::back() return back()
return view('index')->with('title', $title)->with('client', $client) return view('index', compact('title', 'client'))

 

Используйте IoC или фасады вместо new Class

Внедрение классов через синтаксис new Class создает сильное сопряжение между частями приложения и усложняет тестирование. Используйте контейнер или фасады.

Плохо:

Хорошо:

 

Другие советы и практики

Не размещайте логику в маршрутах.

Старайтесь не использовать сырой PHP в шаблонах Blade.

все материалы по Laravel 5