Code style guide: Laravel
Disclaimer:
- Гайд основан на https://spatie.be/guidelines/laravel-php
- Соглашения принятые в уже устоявшейся кодовой базе имеют приоритет над данным гайдом
Configuration
Configuration files must use kebab-case.
config/
pdf-generator.php
Configuration keys must use snake_case.
// config/pdf-generator.php
return [
'chrome_path' => env('CHROME_PATH'),
];
Do not use the env helper outside of configuration files. Create a configuration value from the env variable like above.
Artisan commands
The names given to artisan commands should all be kebab-cased.
👍 # Good
php artisan delete-old-records
💩 # Bad
php artisan deleteOldRecords
A command should always give some feedback on what the result is. Minimally you should let the handle method spit out a comment at the end indicating that all went well.
// in a Command
public function handle()
{
// do some work
$this->comment('Finished!');
}
When the main function of a result is processing items, consider adding output inside of the loop, so progress can be tracked. Put the output before the actual process. If something goes wrong, this makes it easy to know which item caused the error.
At the end of the command, provide a summary on how much processing was done.
// in a Command
public function handle()
{
$this->comment("Start processing items...");
// do some work
$items->each(function(Item $item) {
$this->info("Processing item id `{$item-id}`...");
$this->processItem($item);
});
$this->comment("Processed {$item->count()} items.");
}
Routing
Public-facing urls must use kebab-case.
https://project.ru/admin/product-ratings
Prefer to use the route tuple notation when possible.
👍 # Good
Route::get('product-ratings', [ProductRatingsController::class, 'index']);
💩 # Bad
Route::get('product-ratings', ProductRatingsController@index');
<a href="{{ action([\App\Http\Controllers\ProductRatingsController::class, 'index']) }}">
Open Source
</a>
Route names must use camelCase.
👍 # Good
Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('productRatings');
💩 # Bad
Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('product-ratings');
All routes have an http verb, that's why we like to put the verb first when defining a route. It makes a group of routes very readable. Any other route options should come after it.
👍 # Good: all http verbs come first
Route::get('/', [HomeController::class, 'index'])->name('home');
Route::get('product-ratings', [ProductRatingsController::class, 'index'])->name('productRatings');
💩 # Bad: http verbs not easily scannable
Route::name('home')->get('/', [HomeController::class, 'index']);
Route::name('openSource')->get('product-ratings',[ProductRatingsController::class, 'index']);
Route parameters should use camelCase.
Route::get('news/{newsItem}', [NewsItemsController::class, 'index']);
A route url should not start with / unless the url would be an empty string.
👍 # Good
Route::get('/', [HomeController::class, 'index']);
Route::get('open-source', [OpenSourceController::class, 'index']);
💩 # Bad
Route::get('', [HomeController::class, 'index']);
Route::get('/open-source', [OpenSourceController::class, 'index']);
Controllers
Controllers that control a resource must use the plural resource name.
class PostsController
{
// ...
}
Try to keep controllers simple andTry to keep controllers simple and stick to Api Design Guide keywords (get, replace, patch, delete, search
).
This is a loose guideline that doesn't need to be enforced.
Views
View files must use camelCase.
resources/
views/
favouritePosts.blade.php
class FavoritePostsController{
public function index() {
return view('favouritePosts');
}
}
Validation
When using multiple rules for one field in a form request, avoid using |, always use array notation. Using an array notation will make it easier to apply custom rule classes to a field.
👍 # Good
public function rules()
{
return [
'email' => ['required', 'email'],
];
}
💩 # Bad
public function rules()
{
return [
'email' => 'required|email',
];
}
All custom validation rules must use snake_case:
Validator::extend('organisation_type', function ($attribute, $value) {
return OrganisationType::isValid($value);
});
Blade Templates
Indent using four spaces.
<a href="/favourite-posts">
Favourite Posts
</a>
Don't add spaces after control structures.
@if($condition)
Something
@endif
Authorization
Policies must use camelCase.
Gate::define('editPost', function ($user, $post) {
return $user->id == $post->user_id;
});
@can('editPost', $post)
<a href="{{ route('posts.edit', $post) }}">
Edit
</a>
@endcan
Try to name abilities using default CRUD words. One exception: replace show with view. A server shows a resource, a user views it.
Translations
Translations must be rendered with the __
function. We prefer using this over @lang
in Blade views because __
can be used in both Blade views and regular PHP code. Here's an example:
<h2>{{ __('newsletter.form.title') }}</h2>
{!! __('newsletter.form.description') !!}
Naming Classes
CONTROLLERS
Generally controllers are named by the plural form of their corresponding resource and a Controller
suffix. This is to avoid naming collisions with models that are often equally named.
e.g. UsersController
or EventDaysController
When writing non-resourceful controllers you might come across invokable controllers that perform a single action. These can be named by the action they perform again suffixed by Controller.
e.g. PerformCleanupController
RESOURCES (AND TRANSFORMERS)
Both Eloquent resources and Fractal transformers are plural resources suffixed with Resource
or Transformeraccordingly
. This is to avoid naming collisions with models.
e.g. CustomersResource
EVENTS
Events will often be fired before or after the actual event. This should be very clear by the tense used in their name.
E.g. ApprovingLoan
before the action is completed and LoanApproved
after the action is completed.
LISTENERS
Listeners will perform an action based on an incoming event. Their name should reflect that action with a Listener
suffix. This might seem strange at first but will avoid naming collisions with jobs.
E.g. SendInvitationMailListener
COMMANDS
To avoid naming collisions we'll suffix commands with Command
, so they are easily distinguishable from jobs.
e.g. PublishScheduledPostsCommand
MAILABLES
Again to avoid naming collisions we'll suffix mailables with Mail
, as they're often used to convey an event, action or question.
e.g. AccountActivatedMail
or NewEventMail
DOMAINS
Generally domains (domain directories) should be named by the plural form without Domain
suffix
e.g. Customers
or Orders
MODELS
Models should be named by the singular form without Model
suffix
e.g. Customer
QUERIES from spatie/laravel-query-builder
Queries are named by the plural form of their corresponding resource and a Query
suffix.
e.g. CustomersQuery
ACTIONS
An action name should describe what it does and have Action
suffix.
E.g. CreateCustomerAction