Laravel is a PHP framework and just like any other PHP framework there are several ways to get a single thing done in a lot of cases, for conformity these are hand-picked best practices.
- Installation of every Laravel project should be done with:
laravel new {projectname-backend}
- The project name should be in kebab cases in the format:
{projectname-backend}
- All file names should be in title cases ProductController, PostService, Category
- All services should be named after the model name if tied to a model, else it should carry the name of the entity, and the suffix 'Service' i.e. {Name}Service
- The RouterServiceProvider should be used for route patterns.
- The code editor or IDE should always have the PHPCS setup and active on it.
- PSR12 standard should be used in the Laravel Pint setup.
- Every function should have only one responsibility
- When several models use a certain logic or function that performs similar operation, a Trait should be created.
- A class and a method should have only one responsibility.
- Put all DB-related logic into Eloquent models or into Repository classes if you're using Query Builder or raw SQL queries.
public function index()
{
return view('index', ['clients' => $this->client->getWithNewOrders()]);
}
class Client extends Model
{
public function getWithNewOrders()
{
return $this->verified()
->with(['orders' => function ($q) {
$q->where('created_at', '>', Carbon::today()->subWeek());
}])
->get();
}
}
- Reuse code when you can. SRP is helping you to avoid duplication. Also, reuse Blade templates, use Eloquent scopes etc.
public function scopeActive($q)
{
return $q->where('verified', 1)->whereNotNull('deleted_at');
}
public function getActive()
{
return $this->active()->get();
}
public function getArticles()
{
return $this->whereHas('user', function ($q) {
$q->active();
})->get();
}
- Eloquent allows you to write readable and maintainable code. Also, Eloquent has great built-in tools like soft deletes, events, scopes etc.
Article::has('user.profile')->verified()->latest()->get();
- Document your code, but prefer descriptive method and variable names over comments
if ($this->hasJoins())
- Follow naming conventions accepted by Laravel community and PSR2
What | How | Good | Bad |
---|---|---|---|
Controller | singular | ArticleController | |
Route | plural | articles/1 | |
Named route | snake_case with dot notation | users.show_active | |
Model | singular | User | |
hasOne or belongsTo relationship | singular | articleComment | |
All other relationships | plural | articleComments | |
Table | plural | article_comments | |
Pivot table | singular model names in alphabetical order | article_user | |
Table column | snake_case without model name | meta_title | |
Model property | snake_case | $model->created_at | |
Foreign key | singular model name with _id suffix | article_id | |
Primary key | - | id | |
Migration | - | 2017_01_01_000000_create_articles_table | |
Method | camelCase | getAll | |
Method in resource controller | table | store | |
Method in test class | camelCase | testGuestCannotSeeArticle | |
Variable | camelCase | $articlesWithAuthor | |
Collection | descriptive, plural | $activeUsers = User::active()->get() | |
Object | descriptive, singular | $activeUser = User::active()->first() | |
Config and language files index | snake_case | articles_enabled | |
View | kebab-case | show-filtered.blade.php | |
Config | snake_case | google_calendar.php | |
Contract (interface) | adjective or noun | AuthenticationInterface | |
Trait | adjective | Notifiable |