Laravel Best Practices

After a few code reviews, I learned a few good "rule of thumb" from my senior developer to make a codebase more maintainable - for us to be kind for Charlie The Future Dev.

Use named routes!

When creating endpoints that don't follow the usual Laravel's Resource (i.e. 'create', 'index', 'show', etc.), it is a good idea to name the route. This will help during debugging process, when devs use artisan route:list to see the list of routes. It's more organised!

For example, an CustomController with __invokable() function for /customs/ route.

If we only do this:

// in routes/api.php
Route::get('/customs`, CustomController::class);

The output of artisan route:list will be:

/customs ... CustomController

If we add a named route,

// in routes/api.php
Route::get('/customs', CustomController::class)->named('customs.user-customs.index');

The output of artisan route:list will be:

/customs ... customs.user-customs.index > CustomController

In this isolated example, it might not make a huge difference. However, if you are using different Controllers for the same group of resource, it would make more sense for Charlie The Future Dev to understand how the different Controllers relate to one another.

Route::resource('keyboards', KeyboardController::class);
Route::get('keyboards/{id}/keycap-options', KeyboardKeycapController::class)->named('keyboards.keycaps.index');

In the artisan route:list, the correlation between the Controllers can be seen in the route names implicitly.

/keyboards ..... keyboards.index > KeyboardController@index
/keyboards/{keyboard}/keycap-options ..... keyboards.keycaps.index > KeyboardKeycaps

Use Eloquent if possible!

In Laravel, you can get data from the database in 2 possible ways:

  1. Eloquent, the built-in ORM
  2. Database queries Because we have access to Eloquent, it will be more robust to access data using the Eloquent models compared to raw database queries. The primary reason is that Eloquent models contains relationship data, while database queries do not.

The existence of relationship data in Eloquent models allow devs to access relational data in a more error prone way, especially compared to a database query.

For example, let's say we have a Keyboard model, with a many-to-many relationship with KeycapOptions

// Eloquent way
$keyboard = Keyboard::find(1);
$keycap_options = $keyboard->keycap_options;

// vs. DB queries
$keyboard_options = 
	DB::table('keyboard_keycap_options')
		->where('keyboard_id', '=', 1)
		->get();

What if you made a migration change: field name change or table name change? Instead of updating it in one place (the model), you have to go through every database query referencing the changed migration.

Of course, this is a very contrived scenario. However, the general rule of thumb still stands - use Eloquent (i.e. the model instance itself) to retrieve data where possible.

This does not mean that database queries are useless! It is still useful if you want to do your own RAW SQL statements, or complex database-specific queries where Eloquent does not support it.