A
A
Anton Dyshkant2017-06-15 22:00:04
symfony
Anton Dyshkant, 2017-06-15 22:00:04

How to implement interface at database level (Symfony3, Doctrine ORM, SonataAdminBundle)?

Good afternoon.
I am using Symfony 3, Doctrine ORM, SonataAdminBundle.
A task arose, the solution of which I see the introduction of a certain interface, but so far I have no idea how to properly store the data of such a structure in the database and edit it in the admin panel.
Suppose there are such initial conditions (I apologize for the artificiality of the construction).
There is an entity "Film", which has some of its own properties (we are not interested in them). There is a table for movies in the `film` database.

Film class
/**
 * @ORM\Table(name="film")
 * @ORM\Entity
 */
class Film
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    ...
}

There is an entity "User", which means the user. The `user` table in the database.
User class
/**
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    ...
}

There is an entity "Cinema". The cinema, among other things, has a "City" field, which determines in which city the cinema is located. For movie theaters there is a table in the `cinema` database.
Cinema class
/**
 * @ORM\Table(name="cinema")
 * @ORM\Entity
 */
class Cinema
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Town
     *
     * @ORM\ManyToOne(targetEntity="Town")
     * @ORM\JoinColumn(name="town_id", referencedColumnName="id", nullable=false)
     */
    private $town;

    /**
     * @return Town
     */
    public function getTown()
    {
        return $this->town;
    }

    ...
}


Well, there is, in fact, the essence of "City":
Town class
/**
 * @ORM\Table(name="town")
 * @ORM\Entity
 */
class Town
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    ...
}

Next, it becomes necessary to create a "view log" from this data, i.e. concatenate data about each view into the "View" entity (i.e. "View", nothing to do with view from MVC). Table `view` in db:
View class
/**
 * @ORM\Table(name="view")
 * @ORM\Entity
 */
class View
{
    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     */
    private $user;

    /**
     * @var Film
     *
     * @ORM\ManyToOne(targetEntity="Film")
     * @ORM\JoinColumn(name="film_id", referencedColumnName="id", nullable=false)
     */
    private $film;

    /**
     * @var Cinema
     *
     * @ORM\ManyToOne(targetEntity="Cinema")
     * @ORM\JoinColumn(name="cinema_id", referencedColumnName="id", nullable=false)
     */
    private $cinema;

    /**
     * @return Cinema
     */
    public function getCinema()
    {
        return $this->cinema;
    }

    ...
}

A fairly simple schema that gives a fairly simple structure of tables and relationships between them.
Let's assume that in our business logic it is very important in which city the user has viewed . To do this, we, having an object of the "View" class, call $view->getCinema()->getTown() without any problems, moving along the many-to-one chain.
But suddenly it turns out that the user could watch the movie not only in the cinema (SUDDENLY) , but also:
  • on TV
  • on the computer

At the code level, the solution seems extremely simple: in the "View" class, instead of the "cinema" field, there should be a "viewPlace" (viewing location) field, which contains an object that implements the ViewPlaceInterface interface, which has a getTown () method, which will allow us to call $view ->getViewPlace()->getTown():
New View class, ViewPlaceInterface interface, Cinema, TV, Computer classes
class View
{
    ...

    /**
     * @var ViewPlaceInterface
     */
    private $viewPlace;

    /**
     * @return ViewPlaceInterface
     */
    public function getViewPlace()
    {
        return $this->viewPlace;
    }

    ...
}

interface ViewPlaceInterface
{
    /**
     * @return Town
     */
    public function getTown();
}

class Cinema implements ViewPlaceInterface
{
    /**
     * @return Town
     */
    public function getTown()
    {
        ...
    }
}

class TV implements ViewPlaceInterface
{
    /**
     * @return Town
     */
    public function getTown()
    {
        ...
    }
}

class Computer implements ViewPlaceInterface
{
    /**
     * @return Town
     */
    public function getTown()
    {
        ...
    }
}

Question: how to implement this in terms of Symfony 3, Doctrine ORM, SonataAdminBundle?
What should be the entities, what tables, what annotations?
How should the admin panel be configured so that all this can be filled through it?
Thank you.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question