Curious about the next feature of Laracheck? Visit the Roadmap.
Do you have a feature request or want to report a bug? Visit the Request Board.
You can read about the motivation behind Laracheck In this article.
When you open a new PR Laracheck will run 10+ code checks and tries to identiy issues in your code. If it finds some issues it'll write a comment on the PR: If everything is fine with your code it'll write a comment like this: So when you open a PR you should always see a Laracheck comment.
After you open a PR you probably will push more commits to your branch. These commits can also contain some issues. This is why Laravel runs after every push. After these pushes, it will only comment about new issues that didn't occur in your original PR. If no issues found there's no new comment.
Users, Collaborators, and Organizations
TLDR: Only one developer from the repository being checked has to have an account and active subscription. It's usually the owner.
If you want to use Laracheck on your personal GitHub account it's quite straightforward. Just register with your account, select a plan and you're good to go. You can have as many collaborators as you'd like to.
So let's say you subscribed to Laracheck with your jon.doe GitHub account and installed it to 10 of your repositories. Anyone who has access to these repos can open PRs and run the checks. It doesn't matter if the author of the PR is jane.doe since Laracheck will look for the owner of the repository and that is you, john.doe.
TLDR: Only one developer from the organization needs an account and active subscription.
When you install Laracheck you can choose any organization you're a member of. If the repository (that is being checked) belongs to an organization Laracheck will look for the person who installed the app on behalf of that organization. In this case, only this person has to have an account and active subscription.
TLDR: You can install Laracheck on any number of accounts or organizations.
After the installation, you'll see an aggregated list of repositories coming from multiple accounts and organizations. All the rules mentioned above still apply.
Since GitHub API has a rate limit, Laracheck will analyze only 50 files from each PR. The following files are excluded from every code check:
- Roue files
- Language files
- View files (such as blade or html)
N+1 query detection
Anytime you write a foreach loop or call a Collection method Laracheck will look for potential N+1 problems.
Here are the list of things that qualifies as a problem:
- You access a relationship that is not eager-loaded either in the body of the current function (using with() or load()) or in the model itself (using the $with property).
- You call DB functions in the loop such as DB::table()
- You call static Model functions in the loop such as Product::find()
- You call Model functions in the loop such as $product->save()
Please keep in mind if your project has modules or domains, so it differs from the standard Laravel project structure you need to configure where your models located are. You can do it on the configuration page.
For the time being, it won't detect N+1 problems in nested loops. There are some PHP8 features that are not supported by Laracheck yet. For example: readonly classes, or using $variable::class.
The following files are excluded from N+1 detection:
- View files (such as blade or html)
- Service Providers
- HTTP or Console Kernel
- Support files (typically helper function and classes inside app/Support)
Missing whenLoaded() calls
If you push an HTTP resource class we check if you used the whenLoaded() helper provided by Laravel. It's a great way to avoid N+1 and performance issues. The filename must end with Resource.php or the full path has to include Resources in order to trigger this check.
Missing DB index in migration
If you push a migration we check if you added any kind of index to new columns. The full path has to include migration in order to trigger this check.
Missing down method in migration
If you push a migration we check if it has a down method and it's not empty. The full path has to include migration in order to trigger this check.
Missing foreign key in migration New
If you create a new column that ends with _id Laracheck will warn you if you forgot to add a foreign key to that column.
Missing authorization in request
If you push a HTTP request we check if it has an authorize method and it's not return true. The filename must end with Request.php or the full path has to include Requests in order to trigger this check.
Validation in controller
If you push a controller we check if it uses any kind of validator. Usually it's a better idea to move this logic to a Request class. The filename must end with Controller.php or the full path has to include Controllers in order to trigger this check.
If your PR contains any changes related to PHP files we check if you wrote or modified tests as well.
Missing ENV variable
If you added a new key to one of your config file we check if you also included it in the .env.example file.
Missing/changed composer lock file
If you modified composer.json we check if you also pushed composer-lock.json. This way your production environment will have the dependencies as your local machine.
Any time your PR contains composer-lock.json as a change Laracheck will leave a comment so you can check it one more time that it only contains the necessary changes. Or you can ignore the comment if your task was to upgrade to Laravel 9 and you changed everything on purpose.
env() call outside of config files New
If your code contains an env() call anywhere ouside of a config file Laracheck will warn you. It's a best practice to only use env() in config files. Learn more about configs and deployments.
Forgotten cache keys New
If your code contains an Cache::rememberForever() call Laracheck will warn you so you can make sure that you clear the cache when you need to.
Incorrect dependencies New
There are different layers in every Laravel application. Layers such as: HTTP, Business Logic, Database, etc. Each layer has its own dependencies. For example, the database layer should not depend on the HTTP layer. If it does, Laracheck will show you a warning.
Here are what counts as an incorrect dependency:
|This class||Depends on these|
|Model||HTTP, Job, Command|
|Mail/Notification||HTTP, Job, Command|
|Repository||HTTP, Job, Command|
Complex data object New
There are some typical classes that should not contain too much business logic since their main purpose is to hold data. These classes are:
- DataTransferObjects (DTO)
- Value Objects
If you have a class that contains too much business logic, Laracheck will warn you. "Too much" means that the cyclomatic complexity of the class is larger than 3.
Do you have a cool check idea? Check out the Request Board.
Custom Checks New
You can define your own rules with our new custom check feature. Go to the Custom Checks page and create your own rules.
A custom check contains the following properties:
- Name. This is just an information to identify your checks.
- GitHub comment. This will show up in the GitHub comment if your check gets triggered.
- When to run. There are two types of custom checks:
On every PR. Whenever you open a PR your comment in the GitHub comment field will show up. So it can contain some reminder/warning that is true for every PR in your project. For example, if your team constantly forgets to update your Wiki page, it's an excellent opportunity to remind them.
Only when specific files changed. You can define a list of files that will trigger your check. Your comment will show up on GitHub only if the PR changed these files. Let's say your team needs to write API documentation manually. You can define a check that will remind them if an HTTP-related class or file has changed in the PR.
You can select pre-defined folders that represent the basic Laravel files, such as Controllers or Models. Here's an example that will add a comment any time an HTTP-related file has been changed in the PR:
Individual files and folders
If you don't want to use the pre-defined folders, you can define your own files and folders. In the Individual Files and Folders field you can list, well, individual files and folders.
For example, this check will remind the developer to not forget about soft-deleted users when they modify user-related files:
You can also define a whole folder. For example, if you write app/Formatters then your custom check will run if your PR contains changes inside the app/Formatters folder such as a file called app/Formatters/Integer.php. This works for subfolders as well so if you have a file app/Formatters/Number/Integer.php your custom check will run.
Or you can define any part of the file name you want to trigger the check. For example, if you write User the check gets triggered if your PR contains a file that contains the word User in its name. For example, app/Models/User.php or app/Http/Controllers/UserController.php.
The results will be shown in the GitHub comment under the Custom Checks section, such as this:
Finally, you can select on which repositories you want to run your custom checks. You can select all of them or just a few. If you want your check to run on all of your repos, just skip the repositories selection.
Do you have a cool check idea? Check out the Request Board.
Custom Project Structure
N+1 detection requires to scan your model files to find the relationships. If your project differs from the standard Laravel project structure - meaning you have everything in the
app directory - and your models are not located inside the
app/Models folder, you can specify the location of your models here.
For example, if your project looks like this:
You would need to specify the following path:
src/Domain/**/Models. You need to follow these rules:
- Starting from the root folder
**to match any folder name
Skipping a Specific File
It's possible to instruct Laracheck to skip specific files. It's useful when you're working on a legacy class, for example. To accomplish that add this annotation anywhere to your file:
/** @laracheck-skip-file */
In this case, none of the checks will run for this specific file.