Laravel: 3 ways to separate your “big service”

When you want to organize your application code, but also your other codebase for something complicated.

Italo Baeza Cabrera
4 min readJul 22, 2019

Sometimes I need to create a Service in my application. Think something like a very complicated repository for Users, and API implementation with underlying drivers, a Factory to create some complicated information, whatever you can imagine that can’t be contained in just one file.

Eventually, this code will land inside the App namespace. But wouldn’t be nice to use a custom Namespace, or rather a folder where it could live separated from the rest of the application code? Here are my top three ways to separate that from your application, starting from the simpler.

1. Using a Service Provider

Put your code into app\Services\YourService. Then create a Service Provider where you register and boot your service. This will allow your main class (or classes) to live in the Service Container, and only be instantiated when your application needs it.

/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->singleton(\App\Services\YourService\Stuff::class);
}

Once you’re done, there are two options:

/**
* Register any application services.
*
* @return void
*/
public function register()
{
// ...
$this->app->register(
\App\Services\YourService\ServiceProvider::class
);
}
  • Or add it manually inside the providers key of your app.php config file:
'providers' => [    // ...    \App\Services\YourService\ServiceProvider::class,]

I use this when I need order, and also my “Service” consists on just a few files that do complicated stuff. Keep calm and nobody dies.

2. Using a separated PSR-4 Namespace

The same as the above, we create a Service Provider and register it in your AppServiceProvider.php.

The difference is in the namespace and directory. Instead of using a folder inside the app directory, create a folder in the root of your project called services\YourService (or anything you want), and use a custom namespace for everything under it matching the path, like Services\YourService.

After that, you will need to instruct composer to autoload your files. I personally like the approach to add a new key in the autoload array called Services pointing to the services folder, so if I create a new “Service” inside it Composer will autoload it automatically.

{
// ...
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/",
"Services\\": "services/"
}
}
}

Then, in your PHP files, you can use your Class following the namespace you have set:

<?phpnamespace Services\MyPackage;class SuperService  {
// ...
}

3. Go hardcore with your own Composer package

I use this when I’m doing multiple applications which are totally unrelated but I need the same private codebase available to them.

Most of this it already panned out in my article about Composer: Using your own local package.

Instead of copy-pasting the files, or making a symlink, I just instruct Composer to treat a folder like a Composer package, which I will require inside every project composer.json that needs it.

First, I make a full fledged Composer package. Personally I use the Laravel Package Boilerplate for a quick start, and delete the tools used for internet-hosted repositories (.travis.ci, .gitignore, etc.) since I don’t use them. A easy namespace can be Services, but you can use whatever you want, like CompanyRepository or MyServices.

Assuming you finished your package, all test passed, and configuring correctly the composer.json schema, put it inside a folder where all your shared packages will be, like /Users/AwesomeDev/ComposerPackages.

Now, in each of your projects composer.json files you will add your own package as a local private repository:

{
// ...

"require": {
// Bunch of packages required...
"services/my-service": "@dev"
},
"repositories": [
{
"type": "path",
"url": "/Users/AwesomeDev/Composer/MyService"
}
],
}

Note here that your package name required in your project must match what your package composer.json says. If your package is called services/my-service, then you must put the same name inside the the require array.

The version will depend on the package itself. If you’re using a VCS like Git, you can safely omit the version key since it’s inferred from the tagging, but if not, or you don’t have any 100% immutable stable version, just use @dev.

If you want the advantages of the Internet, you can use Github private repository, or Gitlab, to name a few. Form more tight control, use Private Packagist or mount your own Satis.

--

--

Italo Baeza Cabrera
Italo Baeza Cabrera

Written by Italo Baeza Cabrera

Graphic Designer graduate. Full Stack Web Developer. Retired Tech & Gaming Editor. https://italobc.com

No responses yet