Перейти к основному содержимому

Руководство по стилю кода: Laravel

Предупреждение:

  • Гайд основан на https://spatie.be/guidelines/laravel-php
  • Соглашения, принятые в уже устоявшейся кодовой базе, имеют приоритет над данным гайдом

Конфигурация

Файлы конфигурации должны использовать стиль kebab-case.

config/
pdf-generator.php

Ключи в конфигурации должны использовать стиль snake_case.

// config/pdf-generator.php
return [
'chrome_path' => env('CHROME_PATH'),
];

Не используйте вызов функции env вне конфигурационных файлов. Задайте значение в соответствующем конфигурационном файле при помощи env, как показано выше

Artisan команды

Названия, данные artisan командам должны быть в стиле kebab-cased

👍 # Хорошо

php artisan delete-old-records

💩 # Плохо

php artisan deleteOldRecords

Маршрутизация

Публичные URL должны использовать стиль kebab-case.

https://project.ru/admin/product-ratings

Используйте массив при описании класса и метода контроллера маршрута

👍 # Хорошо

Route::get('product-ratings', [ProductRatingsController::class, 'index']);

💩 # Плохо

Route::get('product-ratings', 'ProductRatingsController@index');

Названия маршрутов должны использовать стиль camelCase.

👍 # Хорошо

Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('productRatings');

💩 # Плохо

Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('product-ratings');

Мы предпочитаем описывать http метод в начале при указании маршрута. Это позволяет сделать группу маршрутов очень читабельной. Все остальное, что необходимо маршруту, должно описываться после указания http метода.

👍 # Хорошо: все http методы описаны в начале

Route::get('/', [HomeController::class, 'index'])->name('home');

Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('productRatings');

💩 # Плохо: http методы нелегко заметить

Route::name('home')->get('/', [HomeController::class, 'index']);

Route::name('openSource')->get('product-ratings',[ProductRatingsController::class, 'index']);

Параметры маршрутов должны использовать стиль camelCase.

Route::get('news/{newsItem}', [NewsItemsController::class, 'index']);

URL не должен начинаться с '/', кроме случая, когда он является пустой строкой.

👍 # Хорошо

Route::get('/', [HomeController::class, 'index']);

Route::get('open-source', [OpenSourceController::class, 'index']);

💩 # Плохо

Route::get('', [HomeController::class, 'index']);

Route::get('/open-source', [OpenSourceController::class, 'index']);

Валидация

При использовании нескольких правил для одного поля в запросе избегайте использования |, всегда используйте запись в виде массива. Это упростит использование пользовательских классов валидации для поля.

👍 # Хорошо

public function rules()
{
return [
'email' => ['required', 'email'],
];
}

💩 # Плохо

public function rules()
{
return [
'email' => 'required|email',
];
}

Все пользовательские правила валидации должны использовать стиль snake_case:

Validator::extend('organisation_type', function ($attribute, $value) {
return OrganisationType::isValid($value);
});

Авторизация

Политики должны использовать стиль camelCase.

Gate::define('editPost', function ($user, $post) {
return $user->id == $post->user_id;
});

Наименование классов

Множественное или единственное число

Множественное число применяется только к последнему слову, например Orders, OrderItems Краткий список, когда применять множественное число:

  1. Для директорий, которые хранят в себе множество однотипных классов. Например: Actions, Models, Controllers, Events
  2. Для контроллеров и ресурсов. Например: UsersController, CustomersResource
  3. Для действий (action, listener, request и т.д.), подразумевающих работу над множеством сущностей. Например: PatchOrdersAction - обновление полей множества сущностей, а PatchOrderAction - обновление полей одной сущности

В остальных случаях следует использовать единственное число

Доменный слой (app/Domain)

Домены

Как правило, домены (каталоги доменов) должны называться во множественном числе и НЕ должны оканчиваться на Domain

Например, app/Domain/Customers или app/Domain/Orders

Модели

Модели должны быть названы в форме единственного числа и НЕ должны оканчиваться на Model

Например, Customer

Observer

Observers должны быть названы точно так же, как названа модель и оканчиваться на Observer.

Например, CustomerObserver

Если в классе указано $afterCommit = true, то в названии это тоже должно быть отражено. Например: CustomerAfterCommitObserver

Действия (Action)

Название действия должно начинаться с глагола (что именно делает action), далее указывается существительное (над чем производится действие) и оканчиваться на Action.

Например, CreateCustomerAction

Форма существительного зависит от действия:

  • если обрабатывается только одна сущность, то указывается единственное число, например DeleteOrderAction
  • если обработка массовая, то указывается множественное число, например PatchProductsAction

После существительного допустимо добавлять дополнительную информацию, например, SavePaymentFromExternalAction

События

События зачастую запускаются до или после какого-то действия. Это должно быть очевидно по времени, используемому в названии события. Название НЕ должно оканчиваться на Event

Например, ApprovingProduct до завершения действия, ProductApproved - после.

Слушатели

Название должно отражать действие и оканчиваться на Listener.

Например, SendInvitationMailListener

Почтовые сообщения

Необходимо добавлять в конец почтовых сообщений Mail.

Например, AccountActivatedMail или NewEventMail

Http слой (app/Http)

Следующие классы именуются во множественном числе соответствующей сущности с добавлением в конце ключевого слова:

  • Контроллеры с добавлением Controller. Например, UsersController или EventDaysController
  • Ресурсы с добавлением Resource. Например, CustomersResource
  • Запросы от spatie/laravel-query-builder с добавлением Query. Например, OrdersQuery
Запросы

Название файла под FormRequest должно начинаться с глагола (что именно будет сделано в этом эндпоинте), далее указывается существительное (над чем производится действие) и оканчиваться на Request

Например CreateProductRequest или UpsertOrderItemsRequest

Тесты

Название файла с тестами эндпоинтов соответствует названию контроллера, только суффикс Controller должен быть заменён на ComponentTest

Например, для контроллера Controllers/UsersController должен быть файл с тестами Tests/UsersComponentTest

Policies

Если политики используются в сервисе, то название файла с политиками соответствует названию контроллера, только суффикс Controller должен быть заменён на ControllerPolicy

Например, для контроллера Controllers/UsersController должен быть файл с политиками Policies/UsersControllerPolicy

Спецификация

Спецификация должна соответствовать этому примеру.

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

Любые объекты для запросов должны оканчиваться на Request, а для ответов на Response

app/Console

Команды

Команды должны оканчиваться на Command.

Например, PublishScheduledPostsCommand