Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SachinAgarwal's avatar

What are Services?

Can anyone explain me what exactly a service is?
e.g., we have Registrar service in fresh installation of laravel.
When to make a service? Do I need to extend or implement any Laravel Core class to a service?

0 likes
27 replies
bastiaan89's avatar

A service is basically just a class that handles one thing (single responsibility), so that the functionality that the class provides, can be reused in multiple other parts of the application. The Registrar service included with Laravel is responsible for registering new users, for example.

There is no need to extend any core classes, you can just create one and type hint it in controllers for example, so that it'll be resolved out of the service container.

4 likes
rodrigo.pedra's avatar

Generally speaking a Service is a class where you implement related and common functionality that you want to be used in various places.

If you look into the Registrar class you mentioned, it has two methods: validator() and create().

The validator()method returns a Validator object that contains the rules for registering a new user. Note that this validation rules are specific for registering a user, you could have a different validation rule set for other operations, like letting a user to change his/her e-mail address.

The create() methods uses the User eloquent model to create a user with a minimum set of fields that are required to register. You could add more attributes to your User model, but for registering these ones will be sufficient.

If you think about it, both of these methods are very specific to a user registration process, so they should not belong to the User model, nor are candidates for a repository. This is when a service is helpful.

Another example: in a project of mine I have a Service which calculates the distance between two cities, using Google Distance Matrix API, I have something like this:

<?php namespace App\Services;

use GuzzleHttp\Client;

use App\City;

class DistanceService
{
    const GOOGLE_API_URL = 'http://google/api/url/here';

    public function calculate( City $from, City $to )
    {
        // 1. get cities api-comapatible name representation

        // 2. replace on the API URL

        // 3. make a request using Guzzle

        // 4. fetch and parse the response

        // 5. return the distance
    }
    
    /* private helper methods */
}

This is a very specific task, and has a somehow lengthy algorithm. This Service class encapsulates its logic, and can I use it in various places along my app.

I also adheres to the Single Responsibility Principle from the SOLID best-practices [ https://laracasts.com/tags/principles ].

tl;dr;

A Service class encapsulates functionality that should be shared along different parts of an application.

EDIT: for the second part of your question (Do I need to extend or implement any Laravel Core class to a service?), no you don't need. Declaring an interface and implementing it, is a best-practice. For example, if I want to change my Distance calculation service to use a different service than google's api, it would be better to declare an interface, and inject the interface on the methods I require this Service. The declare a Service Provider to tell Laravel's container which concrete implementation to use whenever an interface "instance" is required.

For more info about Service Providers see this laracast: [ https://laracasts.com/series/laravel-5-fundamentals/episodes/26 ].

4 likes
SachinAgarwal's avatar

@rodrigo.pedra Thanks for the details explanation. But Then How is a repository different from a Service? And When exactly should I use a service?
For example. maximum of the time we do validation in form request. And then Create a User in Repository. Same with any other registration process.

SachinAgarwal's avatar

@bastiaan89 Thanks For the explanation. But then registering a user is best implemented in repository right? If not then can you explain why? And when exactly should I use service?

rodrigo.pedra's avatar

A Repository is similar to a Service if you look on the single responsibility and shared functionality point of view.

But you should name a class like a Repository when it encapsulates methods that persist and retrieve your business data with some kind of storage (e.g.: a database). Also generally we create a Repository to each entity (model).

A Service is more generic, it is basically functionality you want to share, not necessarily tied to an entity, not necessarily specific to manipulate storage.

I am not an scholar, but I think you can see a Repository as a specialized Service that encapsulates entity manipulation and business rules specific to persisting/retrieving it in your storage.

A Service can have a more generic functionality, not related to a specific entity or related to a storage.

2 likes
bastiaan89's avatar

You could implement the registration in the repository if all you're doing is simply creating the new user with the request data. However, you'll often have more stuff going on when registering, such as sending a welcome email, or setting up billing. The repository should only be responsible for storing the user, not the other things, so that's where the registrar would come in.

A typical workflow would be to have the Registrar depend on several other services (Mailer, Repository, etc), then call those from within the Registrar::create method (referring to the interface here). The idea is that the Registrar knows what should be done to register a user (store in database, send mail, bill credit card), however it shouldn't know how. That's the responsibility of the other services. Likewise, the controller doesn't (and shouldn't) know how to register the user, but just pass data to the Registrar and tell it to register.

1 like
pmall's avatar

@SachinAgarwal when you think of a service think about a bare class with only one responsability (with eventually injected dependencies needed to perform its task).

Imagine you have to perform matrix calculations. You have two Matrix models and you want to multiply them. It is strange to put the multiplication method in the Matrix class. A better approach is a matrix calculation service with a multiply method that takes two matrixs as argument and return the resulting matrix. You can have many methods in the service performing matix algebra.

bastiaan89's avatar

One side note though, don't take these patterns and best practices too far. In some cases, it's no big deal to have some extra logic in one place if there's likely not gonna be another place where you need it. An example would actually be the above post, if you're gonna have separate classes for every bit of logic in your application, it'll become a mess as well. Others may disagree, but I find m1.multiply(m2) to be more readable than MatrixOps::multiply(m1, m2). It also depends on whether you think the logic is gonna change at some point (your user registration process just might, but matrix multiplication will be the same forever).

2 likes
SachinAgarwal's avatar

@bastiaan89 But we will issue event emailing (example) right?
This is the workflow I was following till now for registering user (example):

  1. Submit the html form
    2.Hit the controller
  2. Dispatch a command to register the user
  3. Command uses the repository to register the user and returns the data
  4. Controller now fires an event (UserRegistered for example) And I will have multiple Handlers for performing tasks like Welcome Email etc.
    Now here can I use a Service in this workflow?
rodrigo.pedra's avatar

Repository mostly for data transactions, Services for any other shared functionality, including business logic.

Also @bastiaan89 is 100% correct.

5 likes
pmall's avatar

@bastiaan89 hey man it was an example. Matrix calculation is the best example i've found to explain services so far.

pmall's avatar

@SachinAgarwal

Now here can I use a Service in this workflow?

Nowhere. Why do you want to use a service when you dont have to ?

rodrigo.pedra's avatar

@SachinAgarwal , I don't see where a Service fit on this workflow, it looks you do not need it in this.

But let's imagine that in this various handlers you need to format the user name in a very specifc way, only for e-mails, to send in several e-mails handled in several of these Handlers, you could have a Service to encapsulate the logic that does the formatting and use it on this various Handlers. This way if you change the way you need to format it, you change only in the service.

2 likes
bastiaan89's avatar

I may be wrong on this, but I consider Commands to be services as well. Also, if you want to use Events instead, that's perfectly fine. I personally put what I consider to be a core part of the operation (registering in this case) in the command, and side effects in event handlers.

@pmall Yeah of course, I didn't mean to correct you, but ironically I also found it a good example of when a separate service class would be overdoing it :p

2 likes
pmall's avatar

@bastiaan89

but ironically I also found it a good example of when a separate service class would be overdoing it :p

Not if your app is focused on algebra calculation :p

1 like
SachinAgarwal's avatar

@rodrigo.pedra So, Suppose if i have to do some simple calculations for data transactions, I should make a service for that? For example: Suppose I have an array to be parsed to store to database. So I should make a parsing method in a service and call the repository to store?
P.S. I would prefer making a method in repository itself.

1 like
bastiaan89's avatar

If you prefer doing it in the repository itself, by all means, do just that. Isn't that the entire purpose of the repository, to have a way to store data in a format of your choice?

2 likes
SachinAgarwal's avatar

@pmall I was asking just as an example as @bastiaan89 mentioned that If I need to perform various tasks apart from registering a user then I can use service.

1 like
SachinAgarwal's avatar

@bastiaan89 @pmall @rodrigo.pedra So the basicaly it would be like:
For a very specific tasks I make a service.
For example (related to my current project):

  1. If I need some Image manipulation I create a service instead of a repository.?
  2. If I need to create PDFs I make service instead of repository?
    And I can call a service inside a repository and a repository inside a service?
    Another example:
    I can create a service for registering a user which will Validate the data and dispatch an event for registration and can fire and event for emails?
1 like
rodrigo.pedra's avatar

I side with @bastiaan89 opinion, if it is a simple calculation and related only to the persist operation of that very specific array, I see no problem at all on doing this in a controller.

If you have a calculation that should be done in 2, 3, 4 or more repositories, models, commands or handlers, you can create a service for that.

The best way to go is to develop a pattern you'll follow in the life-time of the project ans stick with it.

2 likes
rodrigo.pedra's avatar

Image and PDF I would go with a service to encapsulate the specific logic.

For the e-mail sending job I would go with a Command or an Event, the magic word here is dispatching.

4 likes
bastiaan89's avatar

The best way to go is to develop a pattern you'll follow in the life-time of the project ans stick with it.

Definitely this. What I often see (and also sometimes catch myself doing) is people trying too hard to adhere to all kinds of patterns and practices, and not seeing a better/simpler way because of this.

5 likes
SachinAgarwal's avatar
The best way to go is to develop a pattern you'll follow in the life-time of the project ans stick with it.
@ rodrigo.pedra @bastiaan89 I myself do it this way. The reason for this thread is I did not understand the concept of a service, I searched a lot on google but did not found a good explanation.

And @rodrigo.pedra Yea I use commands and Events I was asking dispatching them from a service. for example will this workflow be efficient?
1. Submit HTML form
2. Hit the Controller
3. Call the service
4. Service will dispatch a command for Registration
5. Command will register through Repo and return
6. Then Service will fire event and return to controller

And as you mentioned If more than 1 repo is using same logic of parsing I can create a service. Wouldn't it be better to make abstract class and extend the repo with it? Or create a trait and use it in the classes? Just asking out of curiosity. :)
1 like
rodrigo.pedra's avatar

The flow looks fine to me. And also, all the other options (abstract parent class, trait) can also be correct, depending on your usage.

There is no correct answer, and that is the beauty of it. All this concepts looks similar and you can adhere to any of them. But I understand you want to have things clearly defined.

This is what I generally do:

  1. Abstract Classes: common functionality that generally does not change and I don't want to type it over and over.
  2. Repositories: encapsulate model manipulation, most of the times I extend a base repository.
  3. Traits: functionality that should be injected to slightly modify a class adding very specific functionality. One good example is the Illuminate\Database\Eloquent\SoftDeletes trait included with Laravel, take a look.
  4. Commands: Task to be executed when who called it does not need the results nor to know if it raised an error, for example, I need explicitly to send the manager an e-mail when a customer cancels an order, but if the e-mail fails to be sent, it should not affect the response to the customer. Also useful for queuing tasks that can be done later.
  5. Events: Functionality that I can hook into a process to extend it and that I might turn on or off.
  6. Services: Functionality that: does not fit on the other options, that I use in several places, that I might wait for a result, that can be decoupled or that are too large to pollute my other classes :)

Maybe other devs organize their code differently, but that is the way I do. Again, the most important thing is to stick with the approach you choose for the project. Consistency leads to a longer life-cycle for your project and easier maintenance.

11 likes
SachinAgarwal's avatar

@rodrigo.pedra Thanks a lot Helped me a lot to understand it better :)

@pmall @rodrigo.pedra @bastiaan89 Thanks a lot for making this concept clear to me :) I find all the replies as the Best answer as each reply explains something on the topic. So I will leave this thread without a Best reply. And Suggest any person looking at this thread to please go through all the replies if you are looking for answer :) :)

4 likes

Please or to participate in this conversation.