This blog will guide you through best practices you need to follow for creating a great app in Laravel. Best practices help other or new developers quickly grasp the app. Decreasing the time for knowledge transfer and increasing readability of code.
The reason I love Laravel is OOP with the most simple language ever (PHP). All the practices defined here are to keep the OOP Paradigm consistent.
Logic
- Try to avoid nested if else.
- Keep less and less code per function. Make more function for more logic.
- Don’t repeat the code more than 2 times. In the beginning , repeating is good to find commonness.
Linting
In programming languages like python there are strict indentation rules but the same is not true for languages like php and js which make the code looks like shit even if it has best logic in it hence there are some standards set by the community and available for prettier code. It just makes the readability much better and readability is the second most important thing then logic.
I prefer the following extension in Vscode for code structuring
Phpcs or php fixer or Php Intellisense.
Phpcs is the hard thing to install in vscode but there is no other option I was left with hence anyway I implemented it.
It has some unnecessary requirements like spaces in between statements and strictness which cannot be leveled down hence for beginning I would surely avoid it.ESLINT.
You can install the extension in vscode or install it via npm.
Name Casing
As the developer the most frustrating part of daily life is naming, to name each new variable, function, class we write. And we always run out of names somewhere like edit, update.
What would you name the function which sets the data for the edit part? Or retrieving the same data with a variety of other datas. You feel the pain right.
- Keep all the Route names in a small case separated by dash.
- Keep all the Folder names in camelCase.
- Keep the class and component name in PascalCase.
- Keep the filename the same as the class or component.(PSR-2)
- Keep the function name in camelCase.
- Keep all local variable names in a lowercase and snake case.
- Keep global variable names in uppercase and snake case.
The last point is given by the laravel community so if we all follow it, it will help all of us.
- Modal name should be singular and the table name should be plural.
Laravel
Env
Along with all environment variables, env file is also helpful for keeping secret keys for services which are costing you. Because this is a file which has always been in gitignore.
Config
Keep all the programming constants which are not costing you inside the config directory. You can make files according to your own wish.
Route
With more complex applications you will find more and more routes and may find problems with traverse url->route->controller->function.
Well if you keep it sorted you will never need to traverse this path and reach the end directly.
Index route
Route::get(‘/items’, [ ItemController::class, ‘index’]);
Show route
Route::get(‘/item/{item}’, [ ItemController::class, ‘show’]);
Update route
Route::put(‘/item/{item}’, [ ItemController::class, ‘update’]);
Delete route
Route::delete(‘/item/{item}’, [ ItemController::class, ‘delete’]);
Don’t write any extra function if you want to get items for company or for user or filter or paginate. We will handle all that in the controller.
And writing array as second parameter with class will help you and your IDE directly jump to controller instead of finding it manually.
You can keep the master route for all Import Export if post variables are the same in all of them.
RouteServiceProvider
If you are tired of using findOrFail in each function you must use route binding.
FormRequest
Form Requests are the most lovely part of laravel as you can validate all the data by just defining the rules and it keeps the validation part separated from business logic. You may find difficulty in writing and testing withValidator function but at the end of the day it all looks good.
Controller
Here comes the most working guy of our application. People write all sorts of things inside controllers. After all, it's pure php. But as I said earlier, keeping functions small and seeing route patterns might confuse you.
Most of the developers end up with writing supportive functions inside Models or private function in controllers.
- Controller should only contain at max 4-5 functions index, show, update, delete.
- Controller function’s only job is to collect data and return either json or HTML.
- If you want to fetch complex data use a Query builder inside some Helper Class.
- Else if you want to use Eloquent right direct queries inside the controller.
- Don’t write try catch everywhere as it violates DRY rule and it’s difficult to cover inside the test.
I will explain the 3rd and 4th point a little more. For most applications I build the fetching part requires supportive functions like filtering, permissions, sorting. And sometimes it uses more then 4-5 tables from the database, Hence it becomes very complex to handle it via eloquent.
And why write eloquently if you can get all the data in one query.
And after all we would be debugging SQL so why not to write it initially.
You can separate your fetch queries easily in the form of multiple functions inside the helper class.
For the saving, updating and deleting part, It is more easy and readable to do so eloquently.
Even if an eloquent query is multiple lines and is repeated please repeat it.
Models
My last statement in the controller might confuse you but if you don’t want to end up with similar functions with the same job in model please do consider the following.
- Don’t return any data or query from a custom function inside the model.
- Only use Relationships, Getters, Setters, Scopes and boot functions inside the model.
- Use traits if you still want to use some abstracted code.
For all other functionality like import, export, notification, jobs use separate files each containing a single class and extending some base class hence following OOP.
VueJs
If you are starting project new project or new component from scratch in Vue, You must use Vue3 composition API with SFC mode. Because it feels like natural JS and future proof for vapor mode.
Folder Structure
- If you want to see common folder structure for VueJs see NUXT.js The folder structure must include Layouts, Components and Pages at top level and may also include Services, Containers, Store, Utils and Widgets.
- The Pages folder should contain subfolders denoting URL, so you can implement folder based routing in future via NUXT or vite-plugin-pages.
Pages
- Try to use minimum number of API call per page for fetching initial data.
- I you have multiple API calls in mounted, use async mounted and await API calls, here's the correct process to do so.
- First call main API to load main data.
- Then call all the other APIs like to load dropdown data
- Perform all data assignment operation like from dropdown data to main data in the end of mounted.
- If your page grows bigger then try to split it into components wrt sections as soon as possible.
- If sections repeats. Try to use sub-components inside loop, this way your code inside component will become simpler.
Components
- All the inside components should end up in the Components folder.
- Try to keep component sub folder structure same as pages to quickly find and recognize components.
- Common components like buttons and inputs may end up in Widgets folder or make shared sub folder inside components.
- Use Section tag as parent tag in all non-functional major components. It makes debugging via html more easier.
- Use @ for most importing paths.
Services
- Import APIs from a separate file to keep them structured, this way you keep track of APIs wrt to models. ```
Import User from ‘@/Apis/User.js’;
User.login(loginData);
2. You can handle all api related errors like 500, 401, 422 here in service folder itself, You can also use axios interceptor for the same purpose.
3. Don't try to over abstract things like defining name for each api, you will rarely need to change path of API but you will have to daily traverse the path name pair of API.
**Store**
1. Don’t use stores until you don’t need the same data in cousin components. If you need same data in parent or child you can use props, event, provide or inject.
2. Keep sub-folder structure same as models or Services.
**Dev Optimization**
1. Use only one blade file if you are using SPA.
2. Use the same language file from resources/lang for i18n and Laravel translation.
3. If you are using SPA, you can also try Inertia to directly return the Vue file from the controller removing the need of blade files in between. It will also help you to use routes on the server side removing the need of vue-router and continue using props.
**Build Optimization**
1. Use Dynamic import to reduce bundle size, Because site speed is an important factor.
2. Use Laravel mix for extracting, versioning, browserSync and HMR when working with webpack.
3. You can use "Vite" if you wanna save time in development and webpack bundle optimization.
I hope you enjoyed reading this.
Please give your love and support to my [Github ](https://github.com/yogeshgalav) open source repositories.
And If you are stuck somewhere or need to outsource your project feel free to hire us.
Thank You and Have Nice Day!
Top comments (0)