cult3

Creating Entities in Laravel 4

Jan 27, 2014

Table of contents:

  1. What is an Entity?
  2. Why use an Entity?
  3. Creating the dependencies
  4. Creating an Entity
  5. Creating a Service Provider
  6. Creating the Entity Interface
  7. Creating an Abstract Entity
  8. Creating a User Entity
  9. Using an Entity in your Contoller
  10. Advanced Entities
  11. Conclusion

As a web application begins to grow, the number of individual components you have to manage can become unwieldy. For example, working with data storage can often mean that you require Repositories, Validation, Caching as well as many other possible services that you rely upon to make your web application work effectively.

Bringing these disparate services together in the Controller is one approach but you will end up with a lot of code duplication. In reality, your application does not care about the implementation of your Repositories, Validation or Caching, it only cares about having that public interface available.

Instead of having the mess of different services tied together in your Controller, you should create an Entity which acts as a public API. With Laravel’s excellent IoC container we can maintain our separation of concerns whilst also providing a clean interface to work with throughout our code. This means if you ever wanted to switch out a component, you will only have to change a single abstraction.

So let’s look at Entities.

What is an Entity?

Before I jump into the process of creating Entities in a web application, first an explanation of what an Entity exactly is.

In Domain Driven Design, an Entity is An object that is not defined by its attributes, but rather by a thread of continuity and its identity.

So for example, a user is an entity because you can change the user’s email address without changing the identity of the user. This is because the user has an id so even when you change the user’s attributes, it’s still the same user.

So an Entity is basically just a unique object within the system that has identity. You can’t have two users with the same id and so users are Entities. An entity can be a user, an order, a product, a blog post, really anything with an identity.

Why use an Entity?

So why would I use an Entity rather than just calling the methods on the Repository directly?

As I mentioned above, I don’t want to have any implementation details in my Controller. Laravel should be an implementation of Cribbb, rather than Cribbb being an implementation of Laravel.

So the basic architecture of Cribbb will be as follows.

  1. A Repository handles the implementation of data storage.
  2. A Validation Service handles validating the input.
  3. A Cache Service handles caching if applicable.

None of the above should be in the Controller or the Model.

Instead, the Repository, Validation and Cache should be injected into the Entity so the Controller will only ever interact with the Entity as a public interface to these services.

This means that if you ever change your cache, validation or repositories, you won’t have to change your Controllers you will only ever have to update what gets injected into the Entity. And because we will be using Dependency Injection through Laravel’s IoC container, everything will be decoupled and easily testable.

Creating the dependencies

In this tutorial I’m going to be making an Entity for working with User’s in Cribbb. Remember, the Entity is really just a public API, there isn’t going to be any logic inside the Entity. Instead, all of the logic will be handled by separate services.

So first I need to create a User Repository. I’ve already covered creating Repositories in this series, so I won’t cover the same ground again. If you haven’t already created a repository, go read this tutorial first.

Secondly I need to create Validation services for creating a new user and updating an existing user. I covered creating advanced validation services a couple of weeks ago so again I won’t cover the same ground again.

So at this point we should have a User Repository (UserRepository.php) and Validation services for creating and updating users (UserCreateValidator and UserUpdateValidator).

Creating an Entity

Next we can actually create the Entities. As with all of my Cribbb specific code, I will create a new directory under the Cribbb namespace for my Entities Cribbb\Entity.

Creating a Service Provider

The first thing to do is to create a Service Provider that will inject the dependencies into the Entity and make it available through Laravel’s IoC container:

<?php namespace Cribbb\Entity;

use Illuminate\Validation\Factory;
use Illuminate\Support\ServiceProvider;
use Cribbb\Entity\User\UserEntity;
use Cribbb\Service\Validation\Laravel\User\UserCreateValidator;
use Cribbb\Service\Validation\Laravel\User\UserUpdateValidator;

class EntityServiceProvider extends ServiceProvider
{
    /**
     * Register the binding
     *
     * @return void
     */
    public function register()
    {
        /**
         * User Entity
         *
         * @return Cribbb\Entity\User\UserEntity
         */
        $this->app->bind("Cribbb\Entity\User\UserEntity", function ($app) {
            return new UserEntity(
                $app->make("Cribbb\Repository\User\UserRepository"),
                new UserCreateValidator($app["validator"]),
                new UserUpdateValidator($app["validator"])
            );
        });
    }
}

So when I request an instance of Cribbb\Entity\User\UserEntity I will be returned an instance with the dependencies injected for me.

In this example I’m resolving the UserRespository out of the IoC container and I’m creating my two validation services by injecting the Laravel Validation Factory as a dependency.

This is a good example of why you should use Service Providers, Dependency Injection and Inversion of Control. Imagine having to set up this complicated object in multiple places around your application!

Creating the Entity Interface

If you have been following along with this series, you will know that it is a good practice to use an Interface when dealing with different instances of a particular type of class.

At this point I’m going to make the assumption that all of my Entities will require all, find, create, update and delete methods as these are pretty typical things to require of an Entity. At a later date I might regret this decision, but I will cross that bridge when I come to it.

So next I will create an EntityInterface that all of my entities will implement. This will be handy because then I can type hint any particular Entity and be certain that it will have these methods available:

<?php namespace Cribbb\Entity;

interface EntityInterface
{
    /**
     * All
     *
     * @return Illuminate\Database\Eloquent\Collection
     */
    public function all();

    /**
     * Find
     *
     * @param int $id
     * @return Illuminate\Database\Eloquent\Model
     */
    public function find($id);

    /**
     * Create
     *
     * @param array $input
     * @return Illuminate\Database\Eloquent\Model
     */
    public function create(array $input);

    /**
     * Update
     *
     * @param array $input
     * @return Illuminate\Database\Eloquent\Model
     */
    public function update(array $input);

    /**
     * Delete
     *
     * @param int $id
     * @return boolean
     */
    public function delete($id);

    /**
     * Errors
     *
     * @return Illuminate\Support\MessageBag
     */
    public function errors();
}

Creating an Abstract Entity

The common methods that have been defined on the interface usually have basically the same implementation. This means we can abstract that code into an Abstract Entity so that we don’t have to repeat ourselves in each of the specific Entities. If any of your Entities require a different implementation, you can just overwrite the method within the specific Entity implementation:

<?php namespace Cribbb\Entity;

abstract class AbstractEntity
{
    /**
     * All
     *
     * @return Illuminate\Database\Eloquent\Collection
     */
    public function all()
    {
        return $this->repository->all();
    }

    /**
     * Fimd
     *
     * @return Illuminate\Database\Eloquent\Model
     */
    public function find($id)
    {
        return $this->repository->find($id);
    }

    /**
     * Create
     *
     * @param array $data
     * @return boolean
     */
    public function create(array $data)
    {
        if (!$this->createValidator->with($data)->passes()) {
            $this->errors = $this->createValidator->errors();
            return false;
        }

        return $this->repository->create($data);
    }

    /**
     * Update
     *
     * @param array $data
     * @return boolean
     */
    public function update(array $data)
    {
        if (!$this->updateValidator->with($data)->passes()) {
            $this->errors = $this->updateValidator->errors();
            return false;
        }

        return $this->repository->update($data);
    }

    /**
     * Delete
     *
     * @return boolean
     */
    public function delete($id)
    {
        return $this->repository->delete($id);
    }

    /**
     * Errors
     *
     * @return Illuminate\Support\MessageBag
     */
    public function errors()
    {
        return $this->errors;
    }
}

Hopefully the code above should be fairly easy to understand. As you can see in the create and update methods, I’m using my injected Validation Services to validate the data that was entered, if the data is valid I can pass it to the appropriate method on the Repository.

Creating a User Entity

Finally I can create my specific User Entity implementation. In a big application you will likely have many different Entities. To prevent this directory getting messy, I will create a new directory for each specific Entity. In this case Cribbb\Entity\User.

Here is my User Entity:

<?php namespace Cribbb\Entity\User;

use Cribbb\Entity\AbstractEntity;
use Cribbb\Entity\EntityInterface;
use Cribbb\Repository\User\UserRepository;
use Cribbb\Service\Validation\Laravel\User\UserCreateValidator;
use Cribbb\Service\Validation\Laravel\User\UserUpdateValidator;

class UserEntity extends AbstractEntity implements EntityInterface
{
    /**
     * @var Cribbb\Repository\User\UserRepository
     */
    protected $repository;

    /**
     * @var Cribbb\Service\Validation\Laravel\UserCreateValidator
     */
    protected $createValidator;

    /**
     * @var Cribbb\Service\Validation\Laravel\UserUpdateValidator
     */
    protected $updateValidator;

    /**
     * @var Illuminate\Support\MessageBag
     */
    protected $errors;

    /**
     * Construct
     *
     * @param Cribbb\Repository\User\UserRepository $repository
     * @param Cribbb\Service\Validation\Laravel\UserCreateValidator $createValidator
     * @param Cribbb\Service\Validation\Laravel\UserUpdateValidator $updateValidator
     */
    public function __construct(
        UserRepository $repository,
        UserCreateValidator $createValidator,
        UserUpdateValidator $updateValidator
    ) {
        $this->repository = $repository;
        $this->createValidator = $createValidator;
        $this->updateValidator = $updateValidator;
    }
}

As you can see in this example, because I have abstracted the basic functionality of the Entity to the Abstract Entity class, there isn’t anything to implement yet in this class. All we have to do is set the injected dependencies on the correct class properties.

However when I need to add specific methods to the User Entity such as friending or following another user, sending a message or getting a feed of updates, I can simply add those methods to this class a public API that will be available to my application. The actual implementation of validating the data, making a request or communicating with an external service will all be handled by a separate service that is injected into the Entity.

Using an Entity in your Contoller

Now that you have created an Entity, you Controller can be really clean because it doesn’t need to know about validation, caching or any other service that you need to apply to the Entity.

To use an Entity in your Controller, simply inject it into the constructor:

use Cobweb\Entity\User\UserEntity;

class UserController extends ApiController {

/**
 * Construct
 *
 * @param Cobweb\Entity\UserEntity $user
 */
public function __construct(UserEntity $user)
{
    $this->user = $user;
}

Next you can use it in your methods. To find a user, all we need to do is pass the id to the Entity:

/**
 * Show
 *
 * @param $id
 * @return Response
 */
public function show($id)
{
    $user = $this->user->find($id);

    if ($user)
    {
        return View::make('user.show', compact('user'));
    }

    App::abort(404);
}

Although I haven’t implemented caching just yet, you can see that when I do add caching, I won’t need to change my Controller code at all. The caching process will happen in the Entity, but the Controller doesn’t need to know about that.

Next creating a new user is also really easy:

/**
 * Store
 *
 * @return Response
 */
public function store()
{
    $user = $this->user->create(Input::all());

    if ($user)
    {
        return Redirect::route('user.show', $id)->with('message', 'The user has been created!');
    }

    return Redirect::route('user.create', $id)->withInput()->withErrors($this->user->errors());
}

We don’t have to deal with any validation logic in the Controller because all we need to do is to pass the input array to the create method. If the data is valid, the new user will be created and returned. If the data is invalid, the method will return false and the appropriate errors will be set.

Advanced Entities

This pattern is also very useful when you need to work with more advanced Entities. Every tutorial uses creating a new user as an example, but in reality our applications are usually more complicated than that.

Often you will be required to use multiple different Repositories in order to fully represent an Entity. For example, to create an Order in an ecommerce application, you will usually need an Order, a Customer and potentially many different Products.

In this example, an OrderEntity is made up of these different repositories and services. However, your Contoller doesn’t care what it takes to make an Order so you should handle that logic in your project specific code.

This means you could use your Order entity in your application, in your API or on the command line. Being able to interact with your application through a browser is just one form of interaction. You should build your application to be agnostic to specific ways in which it is interacted with.

Conclusion

Phew, that was some high level stuff. Give yourself a pat on the back for getting this far. If you are new to this way of thinking about writing web applications, I would highly recommend watching Architecture the Lost Years by Uncle Bob. If you found any of this article confusing, watching this talk should give you some more clear examples of what I’m getting at when I tell you to structure your application in this way.

Using Entities in our applications creates a clean abstraction between our Controller and the actual business logic of our application. When you build an web application, you shouldn’t be building a “Laravel Application”. You should think about it as building your application, Laravel just happens to be one implementation of it.

By building our applications in this way, we don’t tie ourselves to messy code and we make it much easier for others (or our future selves) to pick up a project and understand how it works and how it is structured.

Model-View-Controller has been bastardised over the years. As Uncle Bob says in his talk, this is mainly due to the Internet. But by thinking about our applications in the way in which I’ve outlined in this article, we can move away from the old thinking towards a better future.

Update Ok so I’ve decided to scrap the idea behind this tutorial for a couple of reasons. Firstly I picked a terrible naming word in “Entity”. I hate terms like “Builder” or “Manager” but “Entity” is just too confusing. There are already too many concepts in programming that can be referred to as “Entity”.

So instead of using a “builder” class, I’m just going to inject my validation into the repository. I’m basically just moving the methods from the AbstractEntity class to a AbstractRepository class and then extending my repositories from there. I think this will make my code clearer to understand and easier to work with going forward.

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.