12

How to use entity as service in doctrine (Using Symfony 2.1).

Example usage:

<?php

namespace MyNamespace;

class MyEntity
{
  protected $container = NULL;
  public function __construct($container)
  {
    $this->container = $container;
  }

  /** 
   * @ORM\PrePersist
   */
  public function() 
  {
    // Must call to container and get any parameters
    // for defaults sets entity parameters
    $this->container->get('service.name');
  }
}

As a result, I need to get access to the entire container.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
ZhukV
  • 2,892
  • 6
  • 25
  • 36
  • 1
    An entity is a value object, and as such can not be a service. (The service container would always return the same entity.) – aderuwe Oct 31 '12 at 07:44

2 Answers2

30

EDIT: THIS IS NOT THE PREFERRED WAY, it's the only way to get service container inside an entity, it's not a good practice, it should be avoided, but this just answers the question.

In case you still want the container and/or repository you can extend a base abastractEntity like this:

<?php

namespace Acme\CoreBundle\Entity;

/**
 * Abstract Entity 
 */
abstract class AbstractEntity
{
    /**
     * Return the actual entity repository
     * 
     * @return entity repository or null
     */
    protected function getRepository()
    {
        global $kernel;

        if ('AppCache' == get_class($kernel)) {
            $kernel = $kernel->getKernel();
        }

        $annotationReader = $kernel->getContainer()->get('annotation_reader');

        $object = new \ReflectionObject($this);

        if ($configuration = $annotationReader->getClassAnnotation($object, 'Doctrine\ORM\Mapping\Entity')) {
            if (!is_null($configuration->repositoryClass)) {
                $repository = $kernel->getContainer()->get('doctrine.orm.entity_manager')->getRepository(get_class($this));

                return $repository;
            }
        }

        return null;

    }

}
TylerH
  • 20,799
  • 66
  • 75
  • 101
alex88
  • 4,788
  • 4
  • 39
  • 60
25

An entity is a data model and should only hold data (and not have any dependencies on services). If you want to modify your model in case of a certain event (PrePersist in your case) you should look into making a Doctrine listener for that. You can inject the container when defining the listener:

services:
    my.listener:
        class: Acme\SearchBundle\Listener\YourListener
        arguments: [@your_service_dependency_or_the_container_here]
        tags:
            - { name: doctrine.event_listener, event: prePersist }
Kristian Zondervan
  • 2,884
  • 1
  • 19
  • 11
  • How to link your answer with this one: http://stackoverflow.com/a/15669193/106140 ? I'm having hard times with the `your_service_dependency_or_the_container_here`. How would you get the `$dataManager` and the `$filterManager`, using your solution? – Olivier Pons Oct 22 '13 at 21:33
  • 1
    Yes, you said "`and should only hold data`". But when this data is a file, it's still a data, right? We just have to know *where* to put it, *when*, and *how* to put it. So, maybe it's "theorically" good, in practice it's a leaky abstraction. Read this: http://www.joelonsoftware.com/articles/LeakyAbstractions.html and you'll understand my point of view which is: when you think you gain time by abstracting, you always reach a point where you loose more time in handling exceptions with too much "abstraction". – Olivier Pons Oct 23 '13 at 08:20
  • 1
    So yes, *in theory* "data model should only hold data", in practice, it's a leaky abstraction: you have to put so much code "around it" to keep it "good abstraction" that it costs time (thus money) in developing and maintenance. – Olivier Pons Oct 23 '13 at 08:20