
Laravel: Modularizing Little Pieces of Logic Through Local Composer Packages
Premature optimisation is the root of all evil.
But sometimes you know upfront that you can create a clean module, separate from the rest of the Laravel app. And I like Kelly Suttons mantra https://kellysutton.com/2017/05/29/deletability.html">optimize for deletability.
Why?
By working with code, we see that modularity and deletability are closely related. Properly modularized code is easy to delete. - Kelly Sutton
If a feature is spread across multiple files throughout different parts of the code base, when it comes to updating and maintaining the code, it means looking around everywhere to do so. Its inefficient. And if you plan on having the code for a long time, chances are, it will be changed.
So a simple solution to keep the new feature separate and modularised, is to create a new autoload configuration in the composer.json
file eg.
"autoload": { "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/", "YourLib\\": "lib/" } },
And voila!
Add your your new feature there:
touch lib/Abc/Example.php
<?phpnamespace YourLib\Abc;class Example{ public function greet(string $name): string { return "Hello, $name!"; }}
A step further
You can treat it like its own Composer package.
mkdir -p lib/composer/examplecd lib/composer/example
You can define its dependencies:
{ "name": "your-namespace/example", "description": "An example package", "type": "library", "autoload": { "psr-4": { "YourNamespace\\Example\\": "src/" } }, "require": { "php": "^8.2" }}
Then you can add it to your main composer.json file as a local repository:
"repositories": [ { "type": "path", "url": "lib/composer/*" }]
And finally reference it as if it was a separate package.
"require": { "your-namespace/example": "*@dev"}
Youll need to run composer update
otherwise your code wont find it.
And when youre done, you can put it into its own repository and install it like any other compose package.
Downsides of creating a local package
So going to all this effort to create a local package that you dont publish wont prevent you from hoisting in application code into your module, at which, youre now polluting the separated module.
If youre not going to truly separate the package out at some point, just keeping it as an autoload path is more than sufficient. But it suffers the same problem, that you need discipline to not use your main application code or other modules within it.