Is your test just copying your code?
I found this when writing tests for a project, sitting right in the routes/web.php file:
These entries contain content about programming efficient, effective and secure Laravel projects.
Working on a Laravel project that can use a second set of eyes? I can help.
I found this when writing tests for a project, sitting right in the routes/web.php file:
Let’s say we’re adding a Slack notification channel, and we go to update the method that labels each channel:
When I first started using Laravel, I really didn’t like the global middleware that trimmed strings. But after a while, it became an irreplaceable part of my tool belt, and I am a convert.
I became so used to this that the first time a user used my Filament input and I saw a space after some text, I was really confused. Why did this happen?
Let me tell you how to fix this on the form itself, how to do it globally, and what that might cause a problem with.
Laravel is always giving us little helpers.
One of which is Blade’s @foreach that gives you a $loop variable.
Inside the loop you get things like $loop->index and $loop->iteration, plus the two I want to talk about today: $loop->first and $loop->last.
first and last are boolean values that tell you if this is the first iteration or the last iteration of the loop.
Pretty self-explanatory.
But far too many times I see people abusing these for style - when they should be for flow control.
When I see something like this, I immediately want to “fix” it.
Let’s take a look at this job:
Maybe I’m behind. But I like to think of it as conservative. Parallel unit testing has been around for a while, and I haven’t really reached for it until recently.
This isn’t about not wanting to change, though. It’s about using the proper tools for the job, and only when necessary.
Or at least, that’s how I rationalize my delay. But maybe you’re in the same place. Let’s dig into why I waited, why you might want to wait still, and the reasons why this works now.
Pennant defaults to the database driver, and most tutorials follow that lead. That’s fine for long-lived flags, but it adds a row and a query for every feature resolution.
Laravel’s default behavior on a failed FormRequest validation is to throw a ValidationException, which the framework’s exception handler converts into a redirect to the previous URL with the input flashed to the session and errors attached.
That works perfectly when a person submits the form as the redirect lands them back on that page with the errors.
It breaks down when the form submits itself, for example a bookmark to a GET form with validation, or submitting something into a target="_blank" (like PDF generation).
Laravel gives you two ways to define translations, PHP array files with short keys, or JSON files where the key is the default string itself. Array files are nice when you want stable, namespaced keys you reference everywhere. JSON files are nice when you don’t want to invent a key for every string and you’d rather just write the English (or default) version inline.
I picked JSON on a recent project, and then I hit a moment that gave me pause. I needed pluralization.
Most Eloquent factory states I’ve created are pretty simple like ->published() or ->cancelled().
They flip a flag or override a field to a fixed value making the call site of the factory easier to understand and requiring less ceremony.
Awesome.
But, a state can also accept arguments, and that opens up some useful patterns like deriving values from another model passed in by the caller.
In tests, it’s common to have a service that takes an Eloquent model as an argument, and therefore you want to mock that service to confirm it was called with the right model instance.
A common pattern when testing Laravel validation looks like this:
Tests that read or write files can be really annoying. I’ll admit it, in the past I’ve skipped a few. I just hate having to think about seeding the files, cleaning them up after, and don’t get me started on the pollution left over when a test crashes before it can tear down.
Here’s a Livewire checkout component that looks completely fine:
I’ve taken the stance before against pulling code into a method just to make a longer one look shorter.
So you’d think my AppServiceProvider would be a straight line of code. It isn’t.
Our apps do a lot of writing. Emails, notifications, invoices, dashboards. All of that copy has to follow the same style guide as anything else we publish.
Say your style guide follows AP style, which spells out the numbers zero through nine and uses digits for 10 and up. It is a simple enough rule that most of us just write our own tedious conditional for it, never thinking to check if the framework already handles it.
Joel mentioned this convention in Why would I leave an unused variable in my test?, where he leaves “noise” records assigned to unused variables for readability. If you were wondering why bother with the noise records at all, here is the demonstration.
When I create a project, I will have at least one user seeded into the database. This usually is an admin user as well.
So, why would I create this user with a plain text password initially?! That’s crazy right?
Let me explain why - and then you can see if you agree.
What is the opposite of when()?
unless() is the obvious answer, and it is correct.
But there is also a quieter answer.
when() itself accepts a third callback that runs when the condition is falsy.
There are many reasons why we validate data - whether it’s a Laravel project or any other framework or technology. Sometimes it’s for user or business sanity, other times to keep the application functioning properly. We even do so for security - for both security attacks we know about and hopefully to stop ones we don’t understand.
This is the reason why I reached for validation on pagination requests. This is user input. Just because I don’t understand how it could hurt me doesn’t mean I should ignore it, right?
Let’s validate pagination - easily - in Laravel.
In a previous tip, I walked through a duplicate public_id bug caused by Eloquent::replicate() carrying the ULID over to the clone.
The fix I landed on was a replicating hook that overwrites public_id on the new instance.
Imagine I have this trait that gives any model a ULID-based public_id on create:
Each API seems to be different. However, there are some best practices that we should all try to follow.
One of those that I really like is the 201 Created HTTP response. If the object is created immediately, you may even return the full object contents.
In some cases, we don’t have the data or don’t want to return the full payload. We can return null with a location header. Here’s how to do that with Laravel.
I was working on a console command that imports data from a CSV file. Most of the time, I use the same file, but occasionally I need to specify a different one. So I set up an optional argument:
I love the Spatie Laravel Permissions package. I use it in almost all of my Laravel projects.
When testing, I’ll need to set up users with various different roles and permissions. Usually, I’m using an Eloquent Factory in order to accomplish this.
But it’s a little different when you’re dealing with relationships. Let’s find out how.
I’m working with Yajra DataTables in a Laravel project and I’ve ran into a little bit of a headache. They provide their own render() method, which you pass a blade file to as the first parameter. Something like users.dogs.index - and through that mechanism it loads the proper blade for the datatable.
Here’s the problem, though. I can’t get auto complete and I can’t click through on that in PhpStorm. But I want to. Let’s find out how.
I love using Eloquent’s sole() method in Laravel. It throws an exception if the result set is ever more than 1. It means you should only have a sole record. This is usually what I want. I’ve migrated away from firstOrFail() unless I legitimately want the first of a matching set.
But I just found another reason to love using the sole method - it helps add a layer of protection against SQL injection. Let’s find out how.
There are many ways to handle cascading functionality in Laravel. You can do this with observers, events, manually dispatched jobs - even in MySQL with cascading deletes.
I prefer to keep my cascading logic in the application code by using Eloquent Model Events. This is super easy when it’s just a single level of model. But what about relationships?
Docker provides the HEALTHCHECK instruction for Dockerfiles and Docker Compose files.
While not absolutely required, configuring these can make your IDE and environment more robust and verbose.
Here’s what I use with some common containers in Laravel projects.
Issuing events with Livewire is a useful way to communicate between components. But, there are some caveats to be aware of - especially if you’re coming from something like React or Vue. The majority of this comes from the fact that Livewire treats every component as an island.
This had stumped me a few times in the past. Because of this, I wanted to give a quick example of how you can use Livewire events in a way that you might be more familiar with: with reactivity.
In Laravel 11+, it’s quite easy to tell the exception handler to render all (or a select portion of them) as JSON regardless of the request/response type. But what about earlier versions?
Most things we want to validate in Laravel are simple. But, what should we do when we want to add more validation outside of the standard patterns that are provided? In this example, I’ll show how I do just that.
Oh that famous computer science joke: there are two hard problems in programming, cache invalidation, naming things and off-by-1 errors.
But, on a recent Laravel project, I realized something super important. Let me show you what I was doing and see if you can follow along.
Laravel gives a lot of syntactical sugar helpers. This allows you to write your Laravel code in a few different flavors or dialects. Some programmers prefer using fluent interfaces, others composition, and others pure functional statements.
As a seasoned and salty programmer, I tend to stick with what I know. It can be easy to overlook the helpers that Laravel provides. But, with Eloquent, the when function is way more useful than a simple helper. The true eloquence comes from its handling of the results of the first condition check.
Sometimes I need to spin up a quick Laravel instance on my Mac to test something out. With just a couple keystrokes, I can get a brand new Laravel instance running in a Docker container, ready for my IDE and testing. Here’s how.
In part 1, I introduced the problem of periodically retrieving a JSON data end point and appending it to a file. This small, quick task can easily be solved by the demonstrated Laravel code. It’s simple, concise and readable. But is it the best solution?
“If you only have a hammer, everything is viewed as a nail” is an idiom referred to as Maslow’s hammer. It basically means that if you only know one tool, and you over-rely on it, you’ll only use that tool to solve every problem, regardless of whether it’s the right one for the job. (It’s a common saying around these parts… that and Joel’s famous saying “Do you even have a 5th bathroom if the floor isn’t heated?”)
Laravel is quite the Swiss Army Knife - it has easy solutions for just about every problem and task you have. That’s why I’m such a fan of it. But is it always the right tool for the job?
I love writing in Markdown - and offering that functionality in WYSIWYG editors for our users. But, it just seems so complicated to try to show markdown in Laravel blade files. So, I made a quick anonymous component that makes this easier.
You’ve got Laravel throttling set up on authentication, password reset and other sensitive endpoints. But, how do you know this is actually working to stop people? Or what if you either want to admonish bad users or proactively reach out with support to help them? Perhaps you might want to log your throttled attempts. It’s pretty easy.
There are packages out there to add logging to the HTTP client in Laravel for outgoing requests freely available. Those are great, but what about if you’re providing an API - and you need to log incoming requests and responses? There’s not a single place to do that - or is there? Let’s look at a middleware to log our incoming requests and responses.
Normally, I would generate a slug for an Eloquent model with an observer or an event. The creating event can verify if the slug field is filled, and if not, use the Str helper to add it to the current creation payload. Pretty cool.
I was so happy when I saw that Enums had finally come to PHP. Up until this time, I had been faking this sort of thing with constants on interfaces.
The times are changing, and I’m here for it.
In most Enum declarations, you’ll find a simple set of key value pairs, or in the PHP language, a name and a value. The name allows you to reference it in your code. The value usually is stored or passed around as data.
So, what happens when you need to display something like a text label to the user?
A few years ago, I wrote a gentle introduction to sprintf. For those who read it, their code quality, speed and readability increased dramatically (I hope…).
But why would you even want to use sprintf? Its syntax looks pretty complex and we already have solutions for most of the things it solves. (This is how I felt about regular expressions early in my career. I have since learned the error of my ways.)
Joel and I were working on a project that had a number of business situations that the owners wanted to know about. They asked if they could get emails when these things happened. (Like a user flagged an article. Someone’s auto-renewal failed. Etc.) There were a number of mailables in the project when I joined.
I hissed. I boo’d. Joel asked me why I was being such a cranky boy.
You’re a professional, so you write thorough and secure validation for every one of your forms. You confirm values are in the proper shape and type, and when appropriate, even query the database with rules like exists. But what do we do when we aren’t the owners of that information? Let’s dig in.
In Blade files, we have a number of useful directives. Laravel decorates some of them with additional properties to make our life even easier.
When projects don’t have a proper set up of dev data using Laravel seeders, getting started can be kind of tough. And if you can help it, you really don’t want to be pulling data from production. User data is precious and should be protected! So what kind of package or utility could help us here? Let me detail out my thoughts - maybe it’s something you want to build!
I love using Laravel Database Factories for setting up test data. But, what about when we want to do more complex domain object creation besides just data values or relationships created outside of the factory? Let’s try using the afterCreated() hook and states.
There are a number of tools and packages that help you manage your users and their associated password reset flows available. The Laravel docs also describe a way that you can reset your password in your own controller. Depending on the use case of the application, I end up having to use code like this in some applications when other packages won’t work as drop-ins. But, can we make this example a little better, more secure, easier to read or a better UX? I think so. Let’s go.
I’m a huge fan of using the Laravel HTTP Client for requests to third-party APIs. It’s clean and easy, nice for unit testing, and exposes methods for the most common functionality we need when consuming APIs. But one thing has bothered me - how do I log both my request and the API’s response, no matter what, with no special calls. Well, we’re in luck - using some global middleware on the client, we can do just that.
If you’re going to use an Action pattern for your application, be careful what you expect coming in as input. In fact, input should be loose and output should be tightly coupled. Let me explain…
The other day I was troubleshooting some code for a form in Laravel that was using a PUT method. Turns out the previous developer had not understood - and I had missed - that the @method override was missing. So I got to thinking - what if we made a form component that handles this for us? Is this a good idea?
It’s nice that you can customize the 4xx/5xx error blade files if they’re published in Laravel - I like that. But what if you want to access the current user - or even use your standard layout - for the not found / 404 error? It’s actually quite easy. Let’s check it out.
The specific challenge is to sort users in a Laravel Nova application by their role. For this specific example, though, we have a number of assumptions. Although this article solves this very specific problem, you can probably extend it to apply to other custom data challenges in Nova. Let’s check it out.
I love PhpStorm, but it can only do so much. Even with plugins like Laravel Idea, you may still have some missing features. One that I wish I had was autocomplete of models from collections or paginators in blade files. Well, turns out there’s an easy enough way to add this functionality for yourself.
I love Laravel request classes for validation. You should be using these whenever you can! But sometimes, writing the rules seems redundant between store and update. There’s a quick fix, though.
The prepareForValidation() method is really useful in Laravel requests: it helps modify the incoming data so that validation might be easier. But you need to be careful that you implement it correctly and don’t mess up your data. Let me explain.
I love using Policies in Laravel. A particularly useful feature is the interception of checks. But what if only some of our policies need that? That’s where we can judiciously use traits.
What’s the difference between unit test, integration test, and a feature test? Which should you use for what type of test? Is it just preference or does performance factor in when using Laravel? Let me give you my take from over a decade of unit testing experience.
There seems to be an endless debate: clearly written code doesn’t need comments vs comments are needed to explain code and give context. I can see both sides of this debate, but there is a middle ground. Let me show you one way.
I’d like to say I don’t ever have tons of error logs in my Laravel projects - but, sometimes it happens. With a sea of text, how can you see what you need to see easily? Enter JetBrain’s idealog plugin in PhpStorm.
The State of Security of Laravel Apps in 2021 is a whitepaper based on the quiz submissions from Laravel programmers.
What if you need to see your config quickly in Laravel from the command line? And you don’t want to use Tinker? Let me show you how I do it…
First off, if you can use something like mailtrap I definitely recommend doing it. Mailtrap provides credentials and configuration so you can capture all of your email into a test inbox. But if that’s not possible, there is another option - and it has to do with Laravel’s mail events.
If you follow the instructions to customize the configuration of Bugsnag’s Laravel package, they’ll tell you to run vendor:publish. But this is not what I want.
I use Laravel Nova in a lot of my projects, but I’ve never liked the idea of storing the files in a local directory after download. Yes, you can use credentials for a Composer-based install, true, but I wanted something that didn’t require that. Turns out you can install packages like Laravel Nova from a zip file locally. Here’s how.
I’ll say it again: do not install Laravel Tinker in production, and certainly do not use it. It’s a great tool to do work in your application, but only in test and development environments. That’s why I only install it in my require-dev section of my composer.json file.
Laravel Hacker is no longer a brand. You can find more security writing in the security tag.
Laravel is a great framework that is pretty secure by default. However, configuration mistakes or coding errors can still leave your app open for attack. Where do you go for help?
When given a choice of methods and ways to do something, it might not be clear which way is the best. As programmers, we tend to pick the easiest, then. However, the easiest can have security implications. Let me illustrate why we should use more stringent controls in a Laravel project.
Please stop using assertDatabaseHas in Laravel. There are many reasons why this is bad, and there are better options available. Let’s find out why.
Currently, there are two pretty common packages for interacting with your database: Eloquent and Doctrine. Eloquent is part of Laravel and Doctrine, while used often on its own, is usually referenced with Symfony. If you’ve come to read this article, you’re probably versed in Doctrine and wondering why you can’t just - or shouldn’t just - use it with your new Laravel project.
Open source software is wonderful for many reasons. One of the best is we can see and inspect the software for vulnerabilities. But, far too many people actually do this. Let me demonstrate, using a Laravel package, how this lack of review might backfire and cause you grief.
Sometimes it makes sense to filter user input before it goes to validation. If you’re using controller-based validation in Laravel, this is pretty easy. But, if you’re doing your validation in request classes, your approach needs to be different.
There’s a struggle to balance the easy-to-use Laravel helpers and functions with very verbose, complicated methods in unit tests. As I’ve been relying on Laravel’s way of doing testing more, I’ve ran into a couple of gotchas that I should share.
There are tons of ways to answer this question each with its own benefits. Let’s check out a few.
Laravel has a built in request helper called wantsJson() that determines if the request is requesting JSON with the Accept: application/json header. But, what if you want to only accept JSON responses? I set up a Laravel middleware that rejects anything that isn’t JSON.
I guess I should RTFM more often… but I didn’t remember (or know??) that MySQL truncate table causes an implicit commit.
By now, you’ve probably written many database migrations in Laravel. But, then something else happens. Perhaps your business model changed, your data attributes changed or you’re just refactoring to a stronger architecture. Doesn’t matter which, you’re going to need to convert and migrate some data.
When someone breaches the security of a web app, sometimes it’s not discovered to weeks or months later. There are a number of tools that specialize in intrusion detection, but they may be costly or difficult to set up. Another idea is to use a canary in the coal mine or a honey pot. Here we’ll talk about the concept and then demonstrate some easy and quick methods.
Laravel has a lot of the most common functionality built into the framework. However, decisions need to be made to balance the needs of the majority of use cases with the stability and agility that programmers need. No one really wants a bloated library. Because of this, you might find that you need functionality that is not directly built into Laravel. When I started working with Laravel-based CSV responses, this was the case. (This article is based on Laravel 5.6.)
For some API work in Laravel, I wanted to validate that the incoming request parameter was a boolean value. At first I tried using the built in boolean slug validator but it didn’t accept all of the ‘boolean’ values I wanted to use. (Also there were weird scenarios where string values of false were triggering as true - like what I wrote about here.
You can make use of guarded or fillable attributes in Eloquent models in Laravel to help control what values you might allow to be updated via your API. But, I wanted to go a step further and actually stop certain values from being passed in. You could go pretty wild with this and try to block everything, but that’s not what I did. I made this validator.
This isn’t a one-size-fits-all suggestion, but it’s a start to help you think about how you actually interact with factories in Laravel. They are used for test data, and are ran very often, multiple times in a row. You don’t need as much random information as you need. (In fact, a lot of times I see people overusing Faker even.)
For testing, I tend to use Postman - which gives you the option to view your API JSON responses in a preview mode (interactive), pretty and raw. But, the other day I heard someone saying sometimes they just want to invoke pretty print in their JSON responses without having to use an external tool and set up a whole environment.
In Laravel, the Support\Str class has a lot of useful methods for switching formats of strings between each other. I needed to take a hyphenated slug and change it to title case words. In Laravel land, I think this is referred to as “Studly” - because I found something very similar called Str::studly(). This converts underline or hyphenated words into a single string with capital letters. I wanted to not concatenate all of these.
It’s important to unit test your application code - even your console commands. So many times, I’ve seen people using the Artisan facade inside of console commands to either queue up new commands or call a different command. This makes it more difficult to unit test the application - you have to rely more on fakery (requiring you to reset your application each time then) and/or integration tests.
One thing I like about Laravel is the amount of built-in functionality that is available. But when this functionality is left in default configuration (much like many default configuration items getting hacked), there can be consequences.
In my Laravel application, I have an end point that will retrieve a collection of Client models. I have many other unit tests that validate that my repository returns the proper clients when requested, that my client model is sound. My last test is a feature test checks that if I retrieve a list of clients from the end point there is proper pagination and client models exist. I don’t really need to test the exact values because I know this will work - from all my other tests.
A nice feature of Laravel is the ability to add a listener to the DB object’s events (or SQL queries). I’ve seen some people add this, then comment it out when it’s done, then un-comment it if they need it again. I don’t like that - I don’t want commented code in my files (also that’s why we have version control).
A pet-peeve of mine is pagination that doesn’t work properly. One that I ran into lately with Laravel is related to the pagination system it has built in. I was able to request pages that were larger than the last page with no discernible error. So, I decided to write a middleware to handle this issue for all of my content.
I hate to admit it, but I do like Laravel’s Tinker package. Sometimes, just testing out your relationships on the command line before you go further is super helpful.
Normally, when I write unit tests, I don’t use Laravel’s facade and fakery methods. I do a lot of injection of services, but in one particular case, when working with the Queue system, I had to use the facade for faking the queue and asserting some jobs were pushed.
If you’re not using Swagger (or OpenAPI) yet to document your APIs, you should start. It’s pretty simple to get started - especially in PHP. I recommend using the swagger-php package - it’s pretty easy. Just use annotations, and then generate the Swagger definition when you’re done.