Writing code that feels native to Laravel
Once you become familiar with Laravel, certain patterns start to stand out. Classes get resolved out of the container through facades, you can swap out instances inside of tests, entry points are predictable, configuration lives in familiar places.
Laravel does this on purpose, it's all about convention. Consistency is probably the framework's strongest selling point.
When a new feature gets introduced to the framework it tends to feel natural because it follows the same patterns. You don't necessarily have to think about what a method might be called, or where it belongs, or even how it works. It just integrates nicely alongside the rest of your code and behaves in the way you expect.
I think that this same idea can be applied to, and ultimately shape, your application code.
I'll give you an example. Laravel has facades (tl;dr static proxies that resolve their underlying classes from the container) and those facades can be "faked" inside of tests, essentially swapping out the real instance for a testable, mocked one.
There's no reason you can't apply this same pattern to your own service classes.
If your service classes are resolved through the container, they become trivial to replace during tests. Pull out a shared interface or contract, implement that for the real service implementation and then create a "fake" version of the service class that can be used inside of your tests. That fake version could use mocks and provide useful testing helpers, or simply do nothing and be mocked itself.
Go a step further and let your testing code leak into your production code by adding a static fake() method to the real class that just swaps the bound instance in the container.
The benefit isn't just clearer tests, it's consistency. You would use a fake version of a Laravel class in your test, so why shouldn't you use a fake version of your own class?
The same logic can be applied to entry points. Jobs use a handle method, middleware uses a handle method, listeners use a handle method. The convention makes these classes predictable to write.
If you're using the action class pattern, give those classes a handle method instead of an __invoke or execute method so that they align with the rest of the framework. It becomes easy to reason about, easy to swap, and easy to compose with things like pipelines or decorators later on.
The broader idea here is to lean on the same conventions that Laravel has already established.
When your application code follows those patterns, it starts to feel like a part of the framework itself. Other developers don't necessarily need to learn your complex architecture, they can rely on what they already know about Laravel.
This might not be something that you apply to all classes in your application, but when you're introducing a service, action, or subsystem, it's worth considering.