Shaun
Shaun

Reputation: 546

Symfony Relations

In my app I have 3 entities; User, Booking and Room.

Booking entity:

namespace App\Entity;

/**
 * @ORM\Table(name="booking")
 * @ORM\Entity(repositoryClass="App\Repository\BookingRepository")
 */
class Booking
{
/**
 * @ORM\Column(type="boolean")
 * @Assert\NotBlank()
 */
private $isActive;

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\Room", inversedBy="bookings")
 */
private $room;

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="bookings")
 */
private $user;

Room entity:

/**
 * @ORM\Table(name="room")
 * @ORM\Entity(repositoryClass="App\Repository\RoomRepository")
 */
class Room
{
/**
 * @ORM\OneToMany(targetEntity="App\Entity\Booking", mappedBy="room")
 * @Expose
 */
private $bookings;

User entity:

/**
 * @ORM\Table(name="app_user")
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity(fields="email", message="This email address is already in use")
 */
class User implements AdvancedUserInterface
{

/**
 * @ORM\Column(type="string", length=255, unique=true)
 * @Assert\NotBlank()
 * @Assert\Email()
 */
private $email;

/**
 * @ORM\OneToMany(targetEntity="App\Entity\Booking", mappedBy="user")
 * @Expose
 */
private $bookings;

Given a user's email I can get a room id like this:

    $user = $this->getEntityManager()
        ->getRepository(User::class)
        ->findOneBy([
            'email' => '[email protected]'
        ]);

    $booking = $this->getEntityManager()
        ->getRepository(Booking::class)
        ->findOneBy([
            'user' => $user,
            'isActive' => true,
        ]);

    $roomId = $booking->getRoom()->getId();

However this seems like a long way to do it. Is it possible to optimise this and query for a room without having to make 2 databases calls?

Upvotes: 1

Views: 71

Answers (2)

M Khalid Junaid
M Khalid Junaid

Reputation: 64466

You could use a single join query to get the room for a spcific user

$this->getEntityManager()
    ->createQueryBuilder()
    ->select('r')
    ->from(Room::class, 'r')
    ->join('r.bookings', 'b')
    ->join('b.user', 'u')
    ->where('u.email = :email')
    ->andWhere('b.isActive = :isActive')
    ->setParameter('isActive', true)
    ->setParameter('email', '[email protected]')
    ->getQuery()
    ->getResult();

Upvotes: 2

Chip Dean
Chip Dean

Reputation: 4302

Yes you can get it directly from the $user variable. I don't see any getters or setters listed here but I'm assuming you have created them. If so then you can do the following:

$bookings = $user->getBookings();

Bookings is an array so you will need to select which booking you want to get the room for. Let's just select the first:

$roomId = $bookings->first()->getRoom()->getId()

To make it cleaner you can add a getCurrentBooking method or something similar to your User class that will return the exact booking you want.

Then you would end up with something like this:

$roomId = $user->getCurrentBooking->getRoom()->getId()

Upvotes: 3

Related Questions