One of the things I personally love of the Laravel framework is how opinionated it is. Opinionated in relation to software means that it defines a standard for the developer experience. For instance Laravel introduce a system for notifications because few web applications today only need to send emails, they need to push to mobile devices or present information in the interface. To do this a structure had to be set out for unifying how these different notification types were sent. This is very opinionated compared to one of Laravel’s alternative options Symfony which has always had more of a stance to provide the basics and let you implement your own opinion with multiple paths to go down.
That might be a bit of a long way of putting this forward but opinions are often good because that’s how we get concessus on how things should be done. In this article I thought I would share some opinions of my own. Some of these might not be of use to you or clash with your own opinions. In fact if that’s the case I’d love to hear about it in the comments.
Use the static class property over strings, everywhere, always…
There are many places in the Laravel framework where it classes are registered as a way to configure something. For example when it comes to Laravel’s events and listeners you will have to register the event and which listeners will handle the event.
This is also done for Policies and can be done for Routing and personally I think to do it any other way in 2021 just doesn’t fly with me. Using the class property makes things far easier to read and refactor. For example this:
Just looks so much more readable as this:
Though some will say that this is a problem because it requires importing each class purely to reference it as a string but actually PHP has a very simple and easy solution for this that many still don’t use. Importing the namespace instead. Take for example what we had before can be reduced from needing several import states to now only needing two:
Use camelcase for route parameters, route names and translation inserts
This one might be the most divisive on this list because it really is open to the user and it’s hard to find justification for it other than, a standard across your app is better than no standard at all. For me, recent projects have made me choose to use camel case and you can seem in the examples below what I mean:
My only real explanation for why I would choose this is really that camel case is the standard for properties and methods on classes so why not continue that in the metadata that defines your app. Often I find camel case more legible than snake or kebab case myself but one thing I can say for sure is it uses less characters.
Ultimate this is one of those things that requires an opinion even if there isn’t much justification for which solution to choose, just choose one and stick to it. There’s nothing worse in development than having to remember where those inconsistencies exist.
Use classes instead of registering middleware in the kernel
Often now more developers in the Laravel community are using classes to point to their controllers in the routing files and as I pointed out earlier, I’m really for this. In fact I’m so much for this I think it makes absolute sense to do it with your middleware to.
A real problem with registering all your middleware in the kernel, in my opinion, is that you end up having to look up what middlewares you’ve added and which class implements it with no discernible reason to do so. It’s even worse if you have parameters which aren’t clear. Using a class with a static method can make for a far more readable experience. Take for example, creating static methods to config the parameters for a router.
See in the example below how we used the class name but also we have the static
overAgeOf method which makes it clear what the parameter will be doing in relation to the middleware.
We only need implement the static method in our middleware to return the name of the class with the colon and then our comma separated parameters. You can see there’s nothing special in our middleware otherwise.
Don’t use acronyms in class names, or if you do, treat them as words
A big pet peeve of mind is the over use of acronyms in businesses but especially so in code. A good example of this is something as simple as the acronym IP as in IP address. For me it makes no sense to name a class IPAddress. It’s a Horrible way to represent what the class is, in code, you should never be afraid to make names as descriptive as possible, as if reading it outloud you were using a short sentence. InternetProtocolAddress may be a longer name but it’s so clear what it is. At a push I will agree that you can use the class name IpAddress because, for the most part it’s a very obvious acronym but equally, why leave such a thing to chance?
Don’t structure your Feature tests by namespace
Something I’ve seen in some application is the confusion around structuring Feature tests, and it’s a common problem. The confusion almost always comes from structuring those Feature tests the same as they would Unit tests.
Unit tests have a one to one relationship with the class that is being tested. It’s understandable that they’re structured using the same namespace because of this. The problem is then that Feature tests don’t have this one to one relationship. Yes you’re often testing a controller when you make those HTTP requests but features are far more than that, they’re a test of middleware, template rendering, database interactions so why name them by purely a class. Instead I suggest a structure similar to this:
As you can see, Features tests are broken up into how they’re interfaced with. A set of API tests are their own folder, or in this case broken up even by the versioning of the endpoints to make it clear. Equally each web page and form action is its own feature test. Events and Jobs are also their own folders, not because they’re classes but that they form pipelines for the application. Equally a standard I’ve tried to keep persistent is to write tests as the actor involved.
For instance in unit tests you might write an a test method as it accepts a number between zero and one hundred and it’s clear the it refers to the class being tested. Whereas in a feature test a better naming convention would be user can select a number between zero and one hundred. This gives those reading the tests a clear description of who or what is involved. When it comes to an event or job we would simply call the actor the system. For example system generates a random number between zero and one hundred.
Bonus: Import the extending classes of the same name as the ‘Base class’.
This is a minor thing as well but often you might want to customise some logic of the Laravel Framework by extending a class. You might not have a reason to add to the name so you simple call it the same thing, e.g. MailChannel is just MailChannel. When importing you are then felt with a choice of using the fully qualified name or importing the class with an alias. I prefer using an Alias but that then leaves you with the question of what should the alias be called. For the example of the MailChannel, I would simply call the alias, BaseChannel. This makes it immediately clear to me that it’s extending a particular type of class for something simple to be overridden in it’s parent.
Hopefully even if you don’t like all of these opinions, you’ll take away something useful. Opinions when it comes to software development is a great thing to have. It will help your team work together instead of fighting over the different styles you might each have. Working together harmoniously is the best way.
I’m Peter Fox, a software developer in the UK who works with Laravel among other things. Thank you for reading my article, I’ve got several more on both medium and dev.to. If you want to know more about me, head over to https://www.peterfox.me. I’m also now also Sponsorable on GitHub. If you’d like to encourage me to write more articles like this please do consider dropping a small one off donation.