Laravel Coding Best Practices You Absolutely Should Know

How to write Laravel smart coding or Laravel Best Practices. Here in this article, I will be taking up the opportunity to discuss some of such best practices that you should follow in your Laravel project.

tufayalhossin
tufayalhossin
Tufayal Hossin Emon

Share now
Laravel Coding Best Practices You Absolutely Should Know

Here's what we've been up to recently.


Laravel Coding Best Practices You Absolutely Should Know

To make Laravel development a breeze, you need to follow the best practices from time to time. Here in this article, I will be taking up the opportunity to discuss some of such best practices that you should follow in your Laravel project.

Best Practices for Laravel Development

Single responsibility principle

A class and a method should have only one responsibility.


Wrong approach:
public function getFullNameAttribute()
{
    if (auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified()) {
        return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' $this->last_name;
    } else {
        return $this->first_name[0] . '. ' . $this->last_name;
    }
}


Recommended practices:
public function getFullNameAttribute()
{
    return $this->isVerifiedClient() ? $this->getFullNameLong() : $this->getFullNameShort();
}
public function isVerfiedClient()
{
    return auth()->user() && auth()->user()->hasRole('client') && auth()->user()->isVerified();
}
public function getFullNameLong()
{
    return 'Mr. ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name;
}
public function getFullNameShort()
{
    return $this->first_name[0] . '. ' . $this->last_name;
}


Powerful model & simple controller

If you use a query constructor or raw SQL to query, put all database related logic into the eloquent model or repository class.


Bad approach:
public function index()
{
    $clients = Client::verified()
        ->with(['orders' => function ($q) {
            $q->where('created_at', '>', Carbon::today()->subWeek());
        }])
        ->get();
    return view('index', ['clients' => $clients]);
}


Good:
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();
    }
}


The business logic should be in the service class

A controller must have only one responsibility, so the business logic should be moved from the controller to the service class.


Bad:
public function store(Request $request)
{
    if ($request->hasFile('image')) {
        $request->file('image')->move(public_path('images') . 'temp');
    }
    
    ....
}


Good:
public function store(Request $request)
{
    $this->articleService->handleUploadedImage($request->file('image'));
    ....
}
class ArticleService
{
    public function handleUploadedImage($image)
    {
        if (!is_null($image)) {
            $image->move(public_path('images') . 'temp');
        }
    }
}


Don’t repeat yourself (dry)

Reuse code as much as possible. SRP (single responsibility principle) is helping you avoid duplication. Of course, this also includes the blade template, the scope of eloquent, etc.


Bad:
public function getActive()
{
    return $this->where('verified', 1)->whereNotNull('deleted_at')->get();
}
public function getArticles()
{
    return $this->whereHas('user', function ($q) {
            $q->where('verified', 1)->whereNotNull('deleted_at');
        })->get();
}


Good:
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();
}


It’s best to use eloquent instead of query builder and native SQL queries.

Eloquent can write readable and maintainable code. In addition, eloquent also has great built-in tools, such as soft deletion, event, scope, etc.

For example, you write:


SELECT *
FROM `articles`
WHERE EXISTS (SELECT *
              FROM `users`
              WHERE `articles`.`user_id` = `users`.`id`
              AND EXISTS (SELECT *
                          FROM `profiles`
                          WHERE `profiles`.`user_id` = `users`.`id`) 
              AND `users`.`deleted_at` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC


Might as well write:
Article::has('user.profile')->verified()->latest()->get();


Instead of trying to annotate your code, write a descriptive name for a method or variable


Bad:
if (count((array) $builder->getQuery()->joins) > 0)


Good:
//Determine if there are any connections.
if (count((array) $builder->getQuery()->joins) > 0)


Best:

if ($this->hasJoins())


Use configuration and language files and constants in your code instead of writing it dead


Bad:
public function isNormal()
{
    return $article->type === 'normal';
}
return back()->with('message', 'Your article has been added!');


Good:
public function isNormal()
{
    return $article->type === Article::TYPE_NORMAL;
}
return back()->with('message', __('app.article_added'));


Don’t directly from .env Get data from file

Pass the data to the configuration file, and then use auxiliary functions config() Use data in your application.


Bad:
$apiKey = env('API_KEY');


Good:

// config/api.php
'key' => env('API_KEY'),
// Use the data
$apiKey = config('api.key');


Store the date in a standard format and use accessors and modifiers to modify the date format if necessary


Bad:
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->toDateString() }}
{{ Carbon::createFromFormat('Y-d-m H-i', $object->ordered_at)->format('m-d') }}


Good:
// Model
protected $dates = ['ordered_at', 'created_at', 'updated_at']
public function getMonthDayAttribute($date)
{
    return $date->format('m-d');
}
// View
{{ $object->ordered_at->toDateString() }}
{{ $object->ordered_at->monthDay }}


I hope these best practices are going to help you avoid any potential problems while building your application and you benefit from these tips that I discussed in this post. Thank you for reading!


Credit: Rizwan Azhar


Further Resources For You

Here's what we've been up to recently.

View all