cult3

Working with Entities in Doctrine 2

Jul 14, 2014

Table of contents:

  1. The Entities folder
  2. Creating the User
  3. Timestamps
  4. Soft Deletes
  5. Authentication
  6. Creating the database
  7. Conclusion

Entities are one of the most important building blocks when building a web application. Entities are objects that have an identity within our applications. So for example a User would be an entity, or a Post would be an entity.

In previous tutorials we would create an Eloquent model to represent an entity. An Active Record ORM like Eloquent would then map that entity to the row in the database. This Eloquent model would basically be an empty class because Eloquent would take care of a lot of the code for us.

However entities are a little bit different in Doctrine 2, and so we can’t just reuse the same Eloquent model.

In this tutorial I’m going to be looking at working with entities in Doctrine 2.

The Entities folder

The first thing I’m going to do is to create an Entities folder under my Cribbb namespace. Up until now our Model files have been housed under the Laravel 4 default app/models directory.

The reason why I’m moving my entities under the Cribbb namespace is, the entities are really a fundamental building block of Cribbb, they don’t have anything to do with Laravel the framework.

I think it can often be easy to tie yourself to a framework when you follow some of the default configuration options. Keeping everything Cribbb related under the Cribbb namespace means there is a clean separation between what is Cribbb and what is Laravel.

I don’t necessarily think you should do this for every project you work on. A lot of the time it does make sense to keep your model files under the models directory. This is usually the case for smaller applications.

However I think for larger applications, there is a big advantage to keeping all of your business related code under the same roof.

In order for Doctrine to know where our entities are located we need to update the metadata item under the laravel-doctrine package configuration:

'metadata' => [
base_path('app/Cribbb/Entities')
],

Creating the User

The first entity we will look at is probably going to be the most important entity in the majority of all web applications, the User entity:

<?php namespace Cribbb\Entities;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    public function getId()
    {
        return $this->id;
    }
}

The first important thing to notice is that we use annotations to specify metadata about the class.

The class has an annotation of:

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 */

This tells Doctrine that this class is an Entity and the table it maps to is the users table.

Next on the $id property we have the following annotation:

/**
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\Column(type="integer")
 */

Here we are specifying that this property should be mapped to the database as an integer and it is an auto-incrementing value. Auto-incrementing simply means that the database will automatically create new ids whenever a new row is added to the database.

Finally we have a getter method for the $id property:

public function getId()
{
return $this->id;
}

The database will be managing creating an id for new rows in the database so we would never have to set an id.

You will need to define class properties and getter and setter methods for each property of your entity. For example, here is what you would define for email, username and password entity properties:

/**
 * @ORM\Column(type="string")
 */
private $email;

/**
 * @ORM\Column(type="string")
 */
private $username;

/**
 * @ORM\Column(type="string")
 */
private $password;

public function getEmail()
{
return $this->email;
}

public function setEmail($email)
{
$this->email = $email;
}

public function getUsername()
{
return $this->username;
}

public function setUsername($username)
{
$this->username = $username;
}

public function getPassword()
{
return $this->password;
}

public function setPassword($password)
{
$this->password = $password;
}

Timestamps

One of the really nice things about Eloquent is it automatically handles created_at and updated_at timestamps for you.

By default Doctrine 2 does not have this functionality. However, Mitchell van Wijngaarden has already solved this problem for us by providing a trait that we can just drop into our entity!

First add the trait to the use statements at the top of the class:

use Mitch\LaravelDoctrine\Traits\Timestamps;

Next add the HasLifecycleCallbacks() annotation to the class.

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 * @ORM\HasLifecycleCallbacks()
 */

And finally add the trait to the class:

class User
{
    use Timestamps;

    // ...
}

HasLifecycleCallbacks() refers to Doctrine’s event system. We’ll look at Doctrine’s events in more depth in a future tutorial.

Soft Deletes

Another nice feature of Eloquent is allowing soft deletes. This means when you delete an entity, it won’t really be removed from the database. Instead it will be marked as deleted, meaning you can always bring it back at some point in the future.

Again Doctrine does not come with this functionality out of the box, but again Mitchell has provided the functionality as part of his Laravel package.

To add soft deletes to an entity, simply add the SoftDelete trait to your class:

use Mitch\LaravelDoctrine\Traits\SoftDeletes;

class User
{
    use SoftDeletes;
}

Authentication

As you probably already know, Laravel ships with a great authentication system already made available to you. Laravel’s authentication system is based upon a driver-based system. By default, Laravel’s authentication will use an Eloquent driver, but because we aren’t using Eloquent anymore, we can switch this out for a Doctrine based driver.

Once again Mitchell has already provided this functionality in his Laravel package!

The first thing to do is to change the driver under app/config/auth.php to doctrine:

'driver' => 'doctrine',

Next we need to add Laravel’s UserInterface interface to the User entity:

use Illuminate\Auth\UserInterface;

class User implements UserInterface
{
}

Finally you can add one of two traits that Mitchell provides as part of the package.

Firstly you could use the Authentication trait:

use Mitch\LaravelDoctrine\Traits\Authentication;

This trait will provide the password, remember token, getAuthIdentifier() and getAuthPassword() methods to satisfy the UserInterface contract.

Alternatively, you can use the RememberToken trait which will only take care of the remember_token method:

use Mitch\LaravelDoctrine\Traits\RememberToken;

I will be just using the RememberToken trait.

Creating the database

Now that we’ve got the first entity set up we can create the database.

To create a database table in Laravel, you would first create a migration file and specify the columns of the table.

In Doctrine 2, there are no migration files. Instead, each entity is analysed and the corresponding database table is created based upon the annotations.

This means that whenever you run the schema update command, Doctrine 2 will read through your entities and make the appropriate changes. Your database is therefore, a reflection of your entities.

Now that we’ve got the User entity set up, we can run the command to create the database.

The Laravel-Doctrine package provides access to Doctrine’s command line tools through the normal artisan command.

The three commands you are going to need are:

php artisan doctrine:schema:create
php artisan doctrine:schema:update
php artisan doctrine:schema:drop

So if you now run the doctrine:schema:create command from the command line, Doctrine should automatically create your users table.

Conclusion

If you are approaching Doctrine 2 for the first time, all of this can seem a little overwhelming. Active Record requires very little to get up and running, whereas there seems to be a lot to take in to get going with Doctrine 2.

Hopefully this tutorial will have given you enough to see something working so you can have a play around for yourself. I think once you get going with Doctrine 2, it feels like a very natural way to work with the entities of a project.

We should also give a huge thank you to Mitchell van Wijngaarden for creating his Laravel-Doctrine package. As I’ve shown in this article, Mitchell has already done a lot of the hard work to bridge the move from Eloquent to Doctrine and he has done a great job to replicate some of the really nice functionality of Eloquent so it works effortlessly in Doctrine 2.

There is still a lot to cover on working with Doctrine 2 entities, but in order to keep this tutorial from being overwhelming, I’ll call it a day here.

In future tutorials we’ll look at some of the other interesting things you can do with Doctrine 2 entities as and when we need them.

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.