Back to Course |
Laravel Travel Agency API From Scratch

Laravel Pint and Larastan

We've finished the functionality but also need to "cleanup" our code. And we will use two different tools for that.


Laravel Pint: Code Styling Fixes

This tool helps identify various code styling issues like unused imports we left, line/symbol spaces here and there, etc.

Laravel Pint is an official first-party tool built on top of PHP-CS-Fixer and makes it simple to ensure that your code style stays clean and consistent.

To fix your code styling with Pint, you only need to install it with Composer and run its command in Terminal. That's it. Let's do that and see what Pint will say about the errors in our code.

Notice: Pint will immediately make changes to your files. But you can roll them back if you want or run Pint with the --test option.

composer require laravel/pint --dev

And then we just run this in Terminal:

./vendor/bin/pint

Pint found and fixed some issues in three files:

If we take a closer look at GitHub commit, these are the changes.


Change 1. Unused Import

I just used this Model earlier, changed the code, and forgot to remove the Model from the use section.


Change 2. No DocBlock If Return Type Used

There's no point in having @return array if we use the (): array in the function name. Remember, I've pasted this code example from the Sluggable package Readme.


Change 3. Comma After Last Array Item

This may look like a personal preference, but over the years, I found it a good practice: just more convenient to add more array items in the future if there's already a comma present.

And again, this code came by pasting from the package Readme file.


Change 4. Correct Order Of Imports

According to standards, imports in the use section should be alphabetically ordered. So Pint suggested precisely that.


And that's it from Laravel Pint. It didn't spot any more flaws or styling issues in our code, which means our code styling is pretty good!

Generally, Pint uses only one of the possible code styling "rules preset" called "laravel". If you don't like its suggestions, you can customize it to use a well-known PSR-12 standard, create your own preset, or override/turn off specific rules. It's all described in the Pint documentation.

Now, remember: all those code styling rules are optional and opinionated. There are standards like PSR, but they are not "sacred", and if you don't style your code precisely as they advise, it's not a big deal. The problem appears when working in a team, and you write code differently, so those minor fixes here and there make it hard to read and review the teammate's code.

You can also read this tutorial: Code Styling in Laravel: 11 Common Mistakes


Larastan: Static Analysis

If Laravel Pint above takes care of how the code looks (styling), then Larastan is about how the code works (structure).

Here's the official description of the tool:

Larastan is a PHPStan wrapper for Laravel. Larastan focuses on finding errors in your code. It catches whole classes of bugs even before you write tests for the code.

Here's what we need to do to run this analysis.

Obviously, install Larastan.

composer require nunomaduro/larastan --dev

Then we need to create a configuration file called phpstan.neon in the main folder of our Laravel application.

There are many levels and options available, but for now, we will stick to the default recommendation from the official docs:

phpstan.neon:

includes:
- ./vendor/nunomaduro/larastan/extension.neon
 
parameters:
paths:
- app/
 
# Level 9 is the highest level
level: 5

And that's it, we can execute this in Terminal:

./vendor/bin/phpstan analyse

This is the result:

Ok, so we have errors! But don't be afraid: these are only potential errors, as Larastan/PHPStan is trying to look for mismatches in the variable names/definition, which may lead to some bugs.

For example, in this case, all those 11 errors happen because Larastan "doesn't like" Laravel "magic" of API Resources where we call $this->id without really defining what $this really is. It also conveniently provides the URL where you can read more about the flagged error.

There are a few things that we may choose to do here.


Option 1. Fix Error: Define Property for Larastan

Ok, if Larastan doesn't "understand" what $this->id is, let's explain it.

There are actually various ways you can do it, by providing comments before the method and/or class name, but after some experiments, I landed on this solution. See @mixin and @property above the Class definition:

app/Http/Resources/TravelResource.php:

/**
* @mixin \App\Models\Travel
* @property int $number_of_nights
*/
class TravelResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug,
'description' => $this->description,
'number_of_days' => $this->number_of_days,
'number_of_nights' => $this->number_of_nights,
];
}
}

With the @mixin, we tell Larastan that there will be that Travel Class used inside this JsonResource Class. This way, Larastan "understands" all the $this->id and $this->slug except one. See below.

For property number_of_nights, we need to define a special @property because that is a "virtual" column, the Accessor, remember? So it isn't actually defined in the Travel Model.

Re-run Larastan and we have errors only in another JsonResource!

So, let's perform the same change there.

app/Http/Resources/TourResource.php:

/**
* @mixin \App\Models\Tour
*/
class TourResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'starting_date' => $this->starting_date,
'ending_date' => $this->ending_date,
'price' => number_format($this->price, 2),
];
}
}

And... Larastan is showing that we're ok now!


Option 2. Ignore Certain Rules/Files

You could "disagree" with Larastan and tell it to accept Laravel "magic" and not check specific rules in some files.

For that, we add a line in the phpstan.neon:

phpstan.neon:

parameters:
paths:
- app/
 
# Level 9 is the highest level
level: 5
 
ignoreErrors:
- '#Access to an undefined property App\\Http\\Resources\\[a-zA-Z0-9::a-zA-Z]#'

And then Larastan won't flag those errors, even if you don't add those @mixin and @property comments in the API Resource files.


GitHub commits for this lesson:


Links to read/watch more: