Doctrine2 Запрос, где потребуется подзапрос - PullRequest
0 голосов
/ 17 ноября 2011

Позвольте мне сначала представить сущности, используемые в этом примере:

Order (_order in mysql)
  $id (primary key, auto increment)
OrderStatus (order_status in mysql)
  $id (primary key, auto increment)
  $order (storing the order object it is related to, named order_id in mysql)
  $statuscode (Storing the integer code)
  $created_at (Storing the datetime of creation)

Отношение Order n:1 OrderStatus. Для каждого изменения статуса я создаю новый OrderStatus с новым кодом состояния. Таким образом, для одного Ордена может быть много OrderStatus. Фактический OrderStatus можно выяснить, посмотрев на OrderStatus с последним create_at.

Теперь я хочу получить все объекты, которые сейчас имеют статус 0. В SQL мой запрос будет выглядеть так:

SELECT o.id,os.statuscode,os.created_at 
FROM `_order` o 
LEFT JOIN `order_status` os ON o.id = os.order_id 
WHERE os.created_at = (SELECT MAX(created_at) 
                       FROM order_status 
                       WHERE order_id = os.order_id);

Могу ли я сделать такой запрос в DQL или мне нужно работать с объектами? Если да, нужно ли мне читать все объекты OrderStatus и вручную выяснять, какой из них является самым последним, или я могу каким-то образом предварительно выбрать?

1 Ответ

0 голосов
/ 17 ноября 2011

Я нашел способ, который не совсем то, что я искал, но он не требует каких-либо изменений в моем приложении, так что все в порядке, пока я не найду лучшего решения.

Что я сделаю, так это сохраню фактический статус непосредственно в Ордене. Через LifecycleCallbacks я обновлю заказ, как только будет создан связанный с ним OrderStatus.

Итак, мой объект-ордер выглядит так:

/**
 * @ORM\Entity
 * @ORM\Table(name="_order")
 */
class Order{
  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  //..

  /**
   * @ORM\Column(type="smallint", nullable=false)
   */
  protected $status = -1;

  // Getter and Setter!
}

Мой статус заказа будет выглядеть следующим образом:

/**
 * @ORM\Entity
 * @ORM\Table(name="order_status")
 * @ORM\HasLifecycleCallbacks
 */
class OrderStatus{

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  /**
   * @ORM\ManyToOne(targetEntity="Order", inversedBy="order_status", cascade={"persist"})
   * @ORM\JoinColumn(name="order_id", referencedColumnName="id", nullable=false)
   */
  protected $order;

  /**
   * @ORM\Column(type="smallint", nullable=false)
   */
  protected $statuscode;

  // ..

  /**
   * @ORM\prePersist
   */
  public function prePersist(){
    $this->order->setStatus($this->statuscode);
  }

  // Getter and Setter!
}

Помните , cascade={"persist"} внутри OrderStatus, чтобы Order также сохранялся при сохранении OrderStatus, в противном случае статус будет установлен, но не сохранен!

Плюсом этого решения является то, что теперь я получаю OrderStatus, вызывая $order->getStatus() вместо необходимости запрашивать у базы данных статус и что я могу сделать $repository->findByStatus(0). С другой стороны, в случае изменения поля состояния из-за какой-либо ошибки данные будут несогласованными.

Как уже говорилось, если у вас есть решение, в котором мне не нужно дополнительное поле для хранения статуса, опубликуйте его! Я очень заинтересован в лучшем решении!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...