Руководство по стилю кода: 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
Краткий список, когда применять множественное число:
- Для директорий, которые хранят в себе множество однотипных классов. Например:
Actions
,Models
,Controllers
,Events
- Для контроллеров и ресурсов. Например:
UsersController
,CustomersResource
- Для действий (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