olek07
olek07

Reputation: 563

Getter for a object from the JSON-Field

I have 2 entities:

class Opponent
{
  ...
  ...
  ...
}

class Process 
{

    /**
     * @var array
     * 
     * @ORM\Column(name="answers_in_related_questionnaires", type="json", nullable=true)
     */
    private $answersInRelatedQuestionnaires = [];

    .
    .        
    . 

}

I have in the field answersInRelatedQuestionnaires amongst other things the object opponent

"opponent": {
 "id":1088,
 "name":"Inora Life Versicherung"
}

I want to write a getter in the entity process, that gets not only the both values id and name from opponent, but the whole entity Opponent. Something like this:

private function getOpponent() : Opponent
{
    $id = $this->answersInRelatedQuestionnaires['opponent']['id'];
    return $entityManager->getRepository(Opponent::class)->find($id)
}

I have read, that using of the entity manager within the entity is not a good idea. Which solutions for my issue are there? Can I use the Process repository in the Process entity?

Upvotes: 0

Views: 469

Answers (1)

iiirxs
iiirxs

Reputation: 4582

You should not inject entity manager in an entity, it's a very bad practice and violates the separation of concerns between classes. BUT if you really want you indeed can inject entity manager in your entity.

GOOD PRACTICE:

Create a Model/Process class and include there any functionality that concerns your model. Doctrine entities are not model classes. In Model/Process you can inject the entity manager and any other service, you need.

EDIT: By creating a Model/Process class I mean creating a class named Process inside Model directory in your /src folder. Your path of your class will be: /src/Model/Process. Of course, the name of the directory or the class can by anything, but this is a typical convention. Your Model class should be responsible for all your business logic, such as validation of your model etc. This will indeed make your code structure more complicated but will be a savor in the long run for large scale projects. You will also need a Model/ProcessManager to properly populate Process model in different cases (e.g. when loaded from Database, user form etc.) Of course, in the end it's all a matter of trade-off between complexity and sustainability.

An interesting approach about models in Symfony, mostly applicable in large scale projects, can be found here.

ALTERNATIVES:

If you access the opponent attribute only after an entity has been loaded you can use Doctrine PostLoad LifecycleCallback to properly set opponent attribute. This is not a bad practice:

use Doctrine\Common\Persistence\Event\LifecycleEventArgs;

/**
 * @ORM\Entity()
 * @ORM\HasLifecycleCallbacks()
 */
class Product
{
    // ...
    private $opponentObject;

    /**
     * @ORM\PostLoad
     */
     public function onPostLoad(LifecycleEventArgs $args){
         $em = $args->getEntityManager();

         $id = $this->answersInRelatedQuestionnaires['opponent']['id'];
         $this->opponentObject = $em->getRepository(Opponent::class)->find($id);

     }

     public function getOpponent() {
         return $this->opponent;

     }
} 

Finally if you really really want to inject the entity manager into your entity you can achieve that with dependency injection via autowiring:

use Doctrine\ORM\EntityManagerInterface;

class Process
{
    private $em;

    public function __contruct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }
    ....
}

Upvotes: 1

Related Questions