Martin Joo
Martin Joo

@mmartin_joo

24 Tweets 28 reads Jan 08, 2023
đź’ˇThere are common mistakes that you can make in Laravel. I collected some of them I see (and make) on a daily basis.
There are three main groups:
- Performance issues
- Deployment issues
- Maintenance issues
đź§µKeep Reading
1/23 Downloadable PDF
At the end of this thread, you can download a more detailed 40-page ebook (free).
2/23 Missing whenLoaded in resources
Laravel HTTP Resources are great! However, they can be a source of poor performance. Consider this class:
3/23 Missing whenLoaded
Nice and simple. Now let's take a look at how we use it in a Controller that returns a list of posts:
4/23 Missing whenLoaded
This API endpoint will perform N+1 database queries. First, it queries the posts (Post::all()) then it'll create a Resource for each one.
In the PostResource class, we perform a select * from comments where post_id = ? query.
5/23 Missing whenLoaded
We can solve this problem in two steps:
- Only access the comments relationship in the Resource if it's already loaded in the model
- Eager-loading the comments relationship in the controller using Post::with('comments')->get()
6/23 Missing whenLoaded
This is what the new resource looks like:
7/23 Missing whenLoaded
The only difference is the whenLoaded call but it makes a big difference! If the comments relationship in the Post model hasn't been already loaded it will not access the relationship and will return an empty Collection.
8/23 Missing whenLoaded
So to make it work we need to change the controller as well:
9/23 Missing whenLoaded
Now that comments are eager-loaded the Resource will include them in the resulting array. And now the API has only two database queries:
10/23 Missing index
TL;DR: Under the hood, MySQL stores tables in files. So every time you make a query it needs to fetch the data from the disk.
Which is slow. This is why indices exist.
11/23 Missing index
TL;DR: When you add a B-TREE (balanced tree) index MySQL will load the column's content into a tree data structure and it doesn't have to fetch all the rows in a sequential way.
This tree is stored in memory. This is why indices are fast.
12/23 Missing index
When you add an index such as published_at MySQL will store the dates in the B-TREE.
This makes queries pretty fast because the DB engine can search in the sorted, balanced tree compared to fetching everything in a linear fashion from the filesystem.
13/23 Missing down method
When a deployment goes wrong and you need to roll back it's crucial to have this process as easy and fast as possible.
The down method in your migration plays a colossal role in this. If you miss one your app will be left in an inconsistent state.
14/23 Missing down method
It’s especially true when you’re refactoring your DB structure and migrating data from the old version to the new one.
15/23 Missing down method
If you’d like to see a concrete example of this download the 40-page PDF that contains much more detail.
martinjoo.gumroad.com
16/23 Missing env variables
Lots of Laravel deployments and pipelines start with this: cp .env.example .env
Also, every new developer who joins the team starts with this command. This is why it's a good idea to add every new env variable to the .env.example file as well.
17/23 Inconsistent composer files
- Make sure you always push the lock file as well when changing composer.json
- If you want to update a package always check the composer.json that you really updated only one package
18/23 env() outside of config files
It's a best practice to use env('MY_ENV_VALUE') calls only in config files.
- env calls can cause problems when caching configs in prod
- config values can be easily “mocked” in tests
19/23 N+1 Queries
I posted an entire thread dedicated to N+1 queries which is the most common performance issue in Laravel.
You can find it here:
20/23 Incorrect dependencies
There are different layers in every Laravel application. Layers such as HTTP, Database, etc. Each layer has its own dependencies.
For example, the database layer should not depend on the HTTP layer.
21/23 Incorrect deps
A common one is when a model or trait depends on an HTTP request.
The developer thinks that "I need to call this method from the controller and it'll use 3 parameters from the request. I just pass the whole request so it'll be simpler.”
22/23 Incorrect deps
These are some examples I consider "incorrect" dependencies:
23/23 Thank you!
Thank you if you’re still here!
As I promised you can download a more detailed 40-page ebook here: martinjoo.gumroad.com

Loading suggestions...