Search code examples
phpormdoctrineentity

PHP Doctrine 2 ORM: Non-Entity object as attribute in entity


I'm using Doctrine ORM 2. I got the following entity class.

/**
 * @Entity
 * @Table(name="objects")
 */
class MyObject
{
  /**
   * @Id
   * @GeneratedValue
   * @Column(type="integer")
   */
  private $id;

  /**
   * @var Coordinate
   */
  private $coordinate;
}

class Coordinate
{
   private $x;
   private $y;
   private $z;
}

I want to implement the 3 coordinate values in a separate class for better handling within php. But within the database I want the 3 values to be included in the database table "objects".

Does anyone know how to achieve this?

Best regards

Edit: I found a workaround but it's not the nicest.

    /**
     * 
 * @var integer 
 * @Column(type="integer")
 */
private $x;
/**
 * 
 * @var integer 
 * @Column(type="integer")
 */
private $y;
/**
 * 
 * @var integer 
 * @Column(type="integer")
 */
private $z;

public function getCoordinate()
{
    return new Coordinate($this->x, $this->y, $this->z);
}

public function setCoordinate(Coordinate $coord)
{
    $this->x = $coord->getX();
    $this->y = $coord->getY();
    $this->z = $coord->getZ();
}

Solution

  • The easiest way would be to set that field to use the "object" mapping type.

    /**
     * @Column(type="object")
     */
    private $coordinate;
    

    Then whatever class of object you put in that field, Doctrine will automatically serialise and unserialise when it is inserted and pulled out of the database.

    The other way is to make a custom mapping type - http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/custom-mapping-types.html. This uses the same method as the object type, but allows you to specify exactly how the object will be converted between PHP and SQL.

    If you used this method had a mapping type named coordinate, you would then just declare this for the field:

    /**
     * @Column(type="coordinate")
     */
    private $coordinate;
    

    One drawback and as far as I can see there is no way around it, is that you can only use one database column for the field. So you wouldn't be able to order by x, y or z separately using DQL.