This site serves as a guide for those who is using Laravel Framework by Taylor Otwell and its contributors.
Laravel : Best Practices aims to put together all the resources and best practices in using the Laravel Framework.
Laravel Framework is not strict on how and where you define your classes as long as it could be loaded by Composer. This is a double-sided blade – it’s beneficial for advanced developers, but could be confusing for beginners and for those who is trying to reverse engineer an existing codebase. The ability to place anything, anywhere is good. But there are times some methods is way better than the others, and that is what we are after. This site tried to collect all the best practices, tools and methodologies, so that it could serve a guide for beginners and existing developers alike.
This is a living document and will continue to be updated with more helpful information and examples as they become available.
Laravel: The Best Practices is currently available in the following languages. Please contribute to the project so that it could support multiple languages.
Help make this website the best resource for new PHP programmers! Contribute on GitHub
Laravel Best Practices has web banner images you can use on your website. Show your support, and let new PHP developers know where to find good information!
At the very minimum, you need to know how to use Git and Composer. Though not required, it is better that you have an account on GitHub.com as it is where all the code and its dependencies are hosted.
You MUST be comfortable in using Command Line Interface (CLI), specially Unix Shells (sh, ksh, csh, tcsh, bash etc) as it is heavily used for common tasks in working with Laravel.
For local development, you’ll need to have at least Vagrant and VirtualBox installed. This is used by Homestead (a special vagrant box made for running Laravel apps). Although you can use the traditional WAMP/MAMP/XAMPP stack, those are not officially supported, thus you might have hard time down the road.
Pure “Laravel-way” frontend development might be a daunting one as it got has a long chain of technologies. You can either use Laravel Blade which is server-side templating or do client-side (browser), which at the very top of the chain is Mix, a wrapper for Webpack. Webpack has its dependencies managed through npm, all of which are packages of NodeJS.
CSS is managed either through Sass or LESS, while JavaScript can be done through Plain JavaScript, ReactJS and the more common frontend framework used with Laravel: VueJS.
For the backend stack, at the very least, you need a web server like Nginx, a php interpreter like PHP-FPM and a database like MySQL. Other optional stack components are Memcached, Redis and Beanstalkd.
While you are not required to understand them all at once, it is advantagous that you are at least familiar with these and do some reading about what they are and where they are being used. This will save you tons of confusion when reading the documentation and references in the future.
This guide is divided into several sections such as each one tries to group related conventions. For example, all database-related convention is grouped in the same section. Each of the convention have the following keywords, which indicates how important it is to comply with such convention:
the above specifications is derived from RFC 2119
There are multiple ways to run Laravel in local environment as outlined below:
You are free to choose which local environment that works for you and your team as long as the following conditions are met:
Your local environment MUST be able to duplicate the production server or close to its specifications such as PHP version, extensions installed and MySQL version
.env file MUST NOT be commited into repository
You SHOULD NOT be connecting to your any production server when you are debugging locally, to prevent accidental corruption of data, unintended API call or similar incident.
You SHOULD NOT be using personally identiable information (PII) of your end-users data or any data that could potentially identify a specific individual such as first/last name, address, medical condition so on and so forth, unless you are explicitly authorized by your company or client to do so.
You MUST update the readme.md file for any special instruction on how to run the app in local environment, so that other developers who will setup the app in their local machine can follow them properly.
While it is possible to WAMP or XAMP for Laravel, this is un-common practice so you SHOULD try to familiarize yourself on how server components works and be comfortable in dealing with them.
Staging servers is a type of server that is used to test a software, website or service in a production-similar environment before being set live. It is the role of a staging environment or staging site, to serve as a temporary hosting and testing server for any new software or feature.
APP_KEYS are set when you initialized a new Laravel application or executed the following command
php artisan key:generate
Laravel uses the key for all encrypted cookies, including the session cookie, before handing them off to the user’s browser, and it uses it to decrypt cookies read from the browser. This prevents the client from making changes to their cookies and granting themselves admin privileges or impersonating another user in your application. Encrypted cookies are an important security feature in Laravel
From APP_KEY And You
Use .env files to store any secure information and retrieve it via env function. There should be no instance on which you will put it inside models/controllers and commit it to Git.
Good
// .env
API_HOST=https://example.com/api
API_USERNAME=myuser
API_PASSWORD=secret
// access the value from app/config.php file
return [
...
'api_host' => env('API_HOST', 'https://defaultdomain.com')
'api_username' => env('API_USER', 'defaultuser')
'api_password' => env('API_USER', 'defaultpassword')
...
]
Bad
define('API_HOST', 'https://defaultdomain.com');
define('API_USERNAME', 'defaultuser');
define('API_PASSWORD', 'defaultpassword');
class DomainController extends Controller
{
public function index()
{
$api_username
}
php artisan key:generate
Good
config/my_config.php
Bad
config/MyConfig.php
Good
// config/myconfig.php
return [
'my_api' => [
'domain' => env('API_DOMAIN'),
'secret' => env('API_SECRET'),
],
Bad
// config/myconfig.php
return [
'MyApi' => [
'DOMAIN' => env('API_DOMAIN'),
'SECRET' => env('API_SECRET'),
],
The best way to figure out if you have implemented best-practice in configuring your app, is if the codebase could be made open source at any moment without compromising any credentials
The following is the generally accepted naming conventions being used by Laravel Community:
Good
class ArticleController extends Controller
{
Bad
class ArticlesController extends Controller
{
class wp_articlesController extends Controller
{
class Article extends Controller
{
Good
class DomainController extends Controller
{
public function index(){} // list domains
public function create(){} // show create form
public function store(Request $request){ } // handle the form POST
public function show($id){} // show a single domain
public function edit($id){} // show edit page
public function update(Request $request, $id){} // handle show edit page POST
public function destroy($id){} // delete a domain
}
Bad
class DomainController extends Controller
{
public function list(){} // list domains
public function create_or_save(){} // show create form then handle save
public function show_edit($id){} // show a single domain then show edit page
public function delete($id){} // delete a domain
}
Good
class Flight extends Model
{
...
Bad
class Flights extends Model
{
...
class flight extends Model
{
...
Good
class User extends Model
{
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Bad
class User extends Model
{
public function phones()
{
return $this->hasOne('App\Phone');
}
}
Good
class Post extends Model
{
public function comments()
{
return $this->hasMany('App\Comment');
}
}
Bad
class Post extends Model
{
public function comment()
{
return $this->hasMany('App\Comment');
}
}
Good
$user->created_at
Bad
$user->createdAt
Good
class User extends Model
{
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
Bad
class User extends Model
{
public function scope_popular($query)
{
return $query->where('votes', '>', 100);
}
Laravel comes with a lot of useful helper functions, but you can also define your own helper functions, given the following conditions:
Good
project_folder/app/helper.php
project_folder/app/Http/helper.php
Bad
project_folder/functions.php
Good
// file composer.json
...
"autoload": {
"files": [
"app/helpers.php"
],
...
Bad
// file app/Http/Controllers/HomeController.php
class HomeController.php
{
function index(){
require_once(app_path("helpers.php"));
}
}
Good
if (! function_exists('my_custom_helper')) {
function my_custom_helper($key, $default = null) {
// ...
}
}
Bad
function my_custom_helper($key, $default = null) {
// ...
}
Good
Route::get('/users', 'UserController@index');
Route::resource('photos', 'PhotoController');
Bad
Route::get('/user', 'UserController@index');
Route::get('/UsersList', 'UserController@index');
Route::resource('PHOTO', 'PhotoController');
Good
Route::get('/user', 'UserController@active')->name('users.show_active');
Bad
Route::get('/user', 'UserController@active')->name('users.show-active');
Route::get('/user', 'UserController@active')->name('show-active-users');
Good
$articlesWithAuthor
Bad
$articles_with_author
Good
$activeUsers = User::active()->get()
Bad
$users = User::active()->get()
$user = User::active()->get()
$User = User::active()->get()
Good
$activeUser = User::active()->first()
Bad
$users = User::active()->first()
Good
show_filtered.blade.php
Bad
showFiltered.blade.php
show-filtered.blade.php
Good
// $api_results is passed by controller <ul> @foreach($api_results as $result) <li>{{ $result->name }}</li> @endforeach </ul>
Bad
@php $api_results = json_decode(file_get_contents("https://api.example.com")); @endphp <ul> @foreach($api_results as $result) <li>{{ $result->name }}</li> @endforeach </ul>
Good
class CreateFlightsTable extends Migration
{
public function up()
{
Schema::create('flights', function (Blueprint $table) {
Bad
class CreateFlightsTable extends Migration
{
public function up()
{
Schema::create('flight', function (Blueprint $table) {
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('MyUsers', function (Blueprint $table) {
Good
post_user
article_user
photo_post
Bad
posts_users
user_articles
post_photos
Good
username
title
thumb_url
Bad
UserName
_title
ThumbUrl
post_title
Good
user_id
Bad
userid
siteid
Memberid
TransactionID
Good
id
Bad
ID
pkid
guid
Good
php artisan migrate
Bad
creation of table
yyyy_mm_dd_<timestamp>_create_<table name>_table
Good
2019_06_06_164210_create_domains_table.php
Bad
2019_06_06_164210_domains.php
Is a practice of using different data storage technologies for different kinds of data. Eloquent ORM can support multiple database for a reason, so don’t limit yourself to MySQL.
It is RECOMMENDED to use MongoDB for records that have attributes that vary a lot. For example, in an inventory system, an office supplies product might have a different set of fields compared to vehicle and auto supplies.
It is RECOMMENDED to use ElasticSearch for high volume data searching and indexing.
It is RECOMMENDED to use Neo4J for applications that require complex relationships between models. For example a multi-level networking application, social network site and similar apps.
From this article, here is a sample breakdown of different databases being used by a retailer company
SOLID is five design principles intended to make software designs more understandable, flexible and maintainable.
A class should only have a single responsibility, that is, only changes to one part of the software’s specification should be able to affect the specification of the class.
Software entities … should be open for extension, but closed for modification.
Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
Many client-specific interfaces are better than one general-purpose interface.
One should depend upon abstractions, [not] concretions.
The idea with this pattern is to have a generic abstract way for the app to work with the data layer without being bothered what storage technology is used when saving/retrieving the data.
We suggests to check first this tutorial for in-depth understand about this design pattern.
Good
class ExampleTest extends TestCase
{
public function testBasicTest()
{
Bad
class ExampleTest extends TestCase
{
public function test_basic_test()
{
WIP (work in progress): this will be filled up by collected best practices once we had done enough research about the subject matter.
WIP (work in progress): this will be filled up by collected best practices once we had done enough research about the subject matter.
WIP (work in progress): this will be filled up by collected best practices once we had done enough research about the subject matter.
TODO
TODO
WIP (work in progress): this will be filled up by collected best practices once we had done enough research about the subject matter.
Laravel can use a variety of frontend javascript frameworks. It also provides for frontend presets (or ways to scaffold a frontend) which provides a basic starting point using Bootstrap, React, and / or Vue.
Starting in laravel 6, the artisan make:auth scaffolding has been moved to the laravel/ui
package.
You can read more about generating scaffolding on the docs/frontend page.
Everytime you add a new component to your app.js file, you need run npm run dev
to compile the new component into javascript. To develop while automatically reloading your page everytime you change a frontend file, you can run npm run watch
. For more information on how to configure laravel mix to compile different types of assets, please checkout the docs on compiling assets.
When developing a Single Page Application with laravel as the backend, you have to setup your middleware to accept CORS request. Laravel 7 introduced native support for CORS, but if you are on an earlier version of laravel, you can use spatie/laravel-cors to allow for requests to push through. You can learn about CORS here.
When developing your SPA, you may still want to secure your application’s forms with Laravel’s default CSRF Tokens. To do so, you’ll need to attach the CSRF token to your form requests. You can do this by adding the value of the X-XSRF-TOKEN
header. If you are building the SPA separately from your laravel app, you might want to use api-tokens instead. In Laravel 7, you can use Laravel Sanctum’s API Token Authentication for this.