K. Weber
K. Weber

Reputation: 2773

Entity property calculated from DB data

This question maybe is more related to architecture and application design more than development itself. Here it goes:

I have an entity defined with date and session (AM or PM), and I need a get/set property to know if isReservedAllDay(), which mean, this entity has a complimentary entity reserved in same day but different session.

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

class HallReservation
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \Date
     *
     * @ORM\Column(name="date", type="date")
     */
    private $date;

    /**
     * @var string: "AM" | "PM"
     *
     * @ORM\Column(name="session", type="string")
     */
    private $session;

This isReservedAllDay() or getReservedAllDay() is actually set by accessing database, which of course, should be out of scope of an entity and done in controller or service.

My first solution is to do so, a query in controller to set de property and then be able to get this property value on twig, forms or wherever, without ever persisting or even mapping this property, this may be a proper solution from the architecture point of view (or maybe not!) but not nice from the point of view of develoment, as it forces me to set the property everytime I get an instance.

function setReservedAllDay($reserved)
{
    $this->reservedAllDay = $reserved;
    return $this;
}

function getReservedAllDay()
{
    return $this->reservedAllDay;
}

Could you criticize this approach or suggest a better one?

Thank you

Upvotes: 1

Views: 257

Answers (1)

Joe
Joe

Reputation: 2436

Setting the value through a doctrine listener for example. Just copied/typed this together so it'll probably not be fully working but you should get the idea. Maybe this approach will cover your needs.

Edit: Like ccKep mentioned the entityManager is already available through the LifecycleEventArgs in the postLoad function directly. Adding the custom event would only be needed if you need another service that depends on the entityManager and can't be injected directly because of that. I'll leave the code here unchanged maybe it could be useful to someone else (who needs more than the entityManager).

The doctrine listener:

class HallReservationLoadListener
{
    /** @var  EventDispatcherInterface */
    protected $eventDispatcher;

    public function __construct(EventDispatcherInterface $eventDispatcher)
    {
        $this->eventDispatcher = $eventDispatcher;
    }

    /**
     *
     * @param LifecycleEventArgs $args
     */
    public function postLoad(LifecycleEventArgs $args)
    {
        $item = $args->getEntity();
        if($item instanceof HallReservation) {
            $event = new HallReservationLoadedEvent($item);
            $this->eventDispatcher->dispatch(HallReservationLoadedEvent::NAME, $event);
        }

    }
}

The custom event:

class HallReservationLoadedEvent extends Event
{
    const NAME = 'hallreservation.loaded';

    protected $hallreservation;

    public function __construct(HallReservation $hallreservation)
    {
        $this->hallreservation = $hallreservation;
    }

    public function getHallreservation()
    {
        return $this->hallreservation;
    }
}

The listener for your custom event:

class HallReservationReservedListener
{
    protected $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function setReservedProperty(HallReservationLoadedEvent $event)
    {
        $hallreservation = $event->getHallreservation();
        //do your stuff
    }
}

Services definitions:

app.listener.hallreservationload:
        class: AppBundle\Listener\HallReservationLoadListener
        arguments: ['@event_dispatcher']
        tags:
            - { name: doctrine.event_listener, event: postLoad }
    app.listener.hallreservationload.reservedproperty:
        class: AppBundle\Listener\HallReservationReservedListener
        arguments: ['@doctrine.orm.entity_manager']
        tags:
            - { name: kernel.event_listener, event: 'hallreservation.loaded', method: 'setReservedProperty'}

Upvotes: 1

Related Questions