Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you extend an entity in Symfony2 like you used to be able to in Symfony 1?

In older versions of Symfony you used to be able to build new objects within a data object by extending a model class with an extended subclass.

For example, I had a questionnaire model that had a results table. That results table had a Result.php model class that used to set and get the results through Doctrine. I then used the ResultPeer.php model subclass to add a new function to the Result object that took the result and depending on a fixed set of thresholds calculated a score and corresponding colour.

In the new Symfony2 version using Doctrine2 I am struggling to work out the best way to do this. When creating an entity I can only find in the documentation the ability to add objects based on the data structure relationships.

I looked at the entity repositories, but that does not appear to extend or add functionality to an original object. It seems to bring back data objects based on queries that are more complex than the standard query functions.

I also looked at services, which I can use to collect the object and then using the object create a new array that includes this object and the newly created data, but this just does not seem right or follow the philosophy that Symfony is all about.

Does anyone know how functions can be added to an existing data object. I found it really useful in the older version of Symfony, but cannot seem to find the alternative in the new version of Symfony2.

like image 241
Adam Stacey Avatar asked Dec 09 '11 10:12

Adam Stacey


1 Answers

Extending an entity is the way to go. In the Doctrine2 world, they talk about inheritance mapping. Here a code example. It defines a BaseEntity then it is extendsed to create a BaseAuditableEntity and finally there is a User entity extending BaseAuditableEntity. The trick is to use the @Orm\MappedSuperclass annotation. This inheritance scheme will create a single table even if there is three entities in my relationships graph. This will then merge all properties into a single table. The table created will contains every property mapped through the relations, i.e. properties from BaseAuditableEntity and from User. Here the code examples:

Acme\WebsiteBundle\Entity\BaseEntity.php

namespace Acme\WebsiteBundle\Entity;

use Doctrine\ORM\Mapping as Orm;

/**
 * @Orm\MappedSuperclass
 */
class BaseEntity {

}

Acme\WebsiteBundle\Entity\BaseAuditableEntity.php

namespace Acme\WebsiteBundle\Entity;

use Doctrine\ORM\Mapping as Orm;

/**
 * @Orm\MappedSuperclass
 */
class BaseAuditableEntity extends BaseEntity {

    private $createdBy;

    /**
     * @Orm\Column(type="datetime", name="created_at")
     */
    private $createdAt;

    /**
     * @Orm\ManyToOne(targetEntity="User")
     * @Orm\JoinColumn(name="updated_by", referencedColumnName="id")
     */
    private $updatedBy;

    /**
     * @Orm\Column(type="datetime", name="updated_at")
     */
    private $updatedAt;

    // Setters and getters here
}

Acme\WebsiteBundle\Entity\User.php

namespace Acme\WebsiteBundle\Entity;

use Acme\WebsiteBundle\Entity\BaseAuditableEntity;

use Doctrine\ORM\Mapping as Orm;

/**
 * @Orm\Entity(repositoryClass="Acme\WebsiteBundle\Entity\Repository\UserRepository")
 * @Orm\Table(name="acme_user")
 */
class User extends BaseAuditableEntity implements AdvancedUserInterface, \Serializable
{
    /**
     * @Orm\Id
     * @Orm\Column(type="integer")
     * @Orm\GeneratedValue
     */
    private $id;

    /**
     * @Orm\Column(type="string", name="first_name")
     */
    private $firstName;

    /**
     * @Orm\Column(type="string", name="last_name")
     */
    private $lastName;

    /**
     * @Orm\Column(type="string", unique="true")
     */
    private $email;

    // Other properties

    // Constructor

    // Setters and getters
}

Here a link to the official inheritance mapping documentation of Doctrine 2.1: here

Hope this helps, don't hesitate to comment if you need more information.

Regards,
Matt

like image 68
Matt Avatar answered Oct 28 '22 03:10

Matt