BugHunterUK BugHunterUK - 1 day ago 4
PHP Question

What are Repositories, Services, and Actions/Controllers?

I started a project using Slim3 and PHP using limited knowledge of application architecture. The plan was to create the project and separate application concerns. It was all going well, but things got confusing fast as the application grew.

The whole idea for doing this was to make development easier. It does in a way, but I find it's complex at times to keep tabs on the data flow.

I need some advice on what Repositories, Services and Controllers/Actions are. And how they should work in a system. My current understanding of them is below:

Repository

Repositories are used between the service layer and the model layer. For example, in a

UserRepository
you would create methods that contains the code to read/write from the database. In PHP PDO would be used, or an ORM, within the repo methods. For example:

class UserRepository
{
public function findByID($id) { ... }
public function findByEmail($email) { ... }
public function findByMobile($mobile) { ... }
public function createEmail($email, $firstname, $lastname, $password) { ... }
public function createMobile($mobile, $firstname, $lastname, $password) { ... }
}


I've put a few example methods in there. But there would likely be many more.

Services

The service layer encapsulates application logic. For example, the
UserService
would be responsible for creating an account, and performing the required logic in order to register the user. Services can also be third party, for example creating a service for Facebook's SDK, or ORM.

An example service:

class UserService
{
public function createMobile($mobile, $firstname, $lastname, $password) {
/*
* Call a validation service to validate input
*/
...

/*
* Use UserRepository's findByMobile() to check if account exists
*/
...

/*
* Use UserRepository's createMobile() to create account
*/
...

/*
* Call SMS service to send verification code
*/
...
}

public function createEmail(...) { ... }
public function getFollowers (...) { ... }
}


Actions

I'm not sure if this is a real term. It's used in the Slim Framework documentation and seems to represent a thin controller.

An Action contains very little logic and is used to make calls to services. Rarely does the Action make direct calls to the repositories unless there's a valid reason. The Action will perform basic checks on the data returned from the services in order to send a response back to the client.

They're tied to individual routes. I'm using them like so:

class ActivateEmailAction extends Action {

public function __invoke(Request $request, Response $response, $args = [])
{
if(!$this->ci->ActivationService->activateEmail($args['token'])){
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'Invalid verification token'
]);
};

return $response->withJson([
'status' => 'success',
'data' => null,
'message' => null
]);
}
}


Am I using these patterns correctly? The flow I seem to have adopted is like so:


  1. Everything starts at the route. For example a request is made to
    /create
    . The route is registered to an Action.

  2. Action decides what services to call

  3. Services perform the logic, make calls to other services and repositories if required

  4. Service hands back data to the Action

  5. Action returns a response



Any advice would be much appreciated.

Answer

Am I using these patterns correctly?

Yes, you are. General advice I'd give is not to give your classes in general and services in particular too many responsibilities: follow single responsibility principle, which, basically states "my class should have only one reason to change" (that's M.Fowler, as far as I remember that actually was R. Martin, thanks to Gordon's correction in the comment).

Your UserService seems to be handling too many different tasks: it handles registration and grabs followers. And probably sends SMS. Extract registration-related logic into UserRegistrationService class.

Comments