Doctrine:ManyToMany匹配条件设置错误的表达式

时间:2015-12-03 15:09:50

标签: symfony doctrine-orm many-to-many relationship criteria

我有两个实体:User和Event,它们处于ManyToMany关系中。 我尝试按$ user-> getEvents()的条件匹配事件,但什么也得不到。检查分析器后,我看到构建sql时标准无法正常工作,我使用了表达式lte和gte,但在sql doctrine中继续使用=。

这是我的课程 用户

<?php

namespace App\UserBundle\Entity;

use App\CoreBundle\Entity\Event;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use JMS\Serializer\Annotation as JMS;

/**
 * @JMS\ExclusionPolicy("all")
 *
 * @ORM\Entity(repositoryClass="App\UserBundle\Repository\UserRepository")
 * @ORM\Table(name="users", uniqueConstraints={@ORM\UniqueConstraint(name="User",columns={"login", "email"})})
 * @UniqueEntity(fields={"login","email"})
 * @ORM\HasLifecycleCallbacks()
 */
class User
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="login", type="string", length=255, unique=true, nullable=false)
     * @Assert\NotBlank()
     */
    protected $login;

    /**
     * @JMS\Expose
     *
     * @ORM\Column(name="name", type="string", length=255, unique=true, nullable=false)
     * @Assert\NotBlank()
     */
    protected $name;

    /**
     * @JMS\Expose
     *
     * @ORM\Column(name="email", type="string", length=255, unique=true, nullable=false)
     * @Assert\NotBlank()
     */
    protected $email;

    /**
     * @ORM\Column(name="roles", type="array", nullable=false)
     * @Assert\NotBlank()
     */
    protected $roles;

    /**
     * @ORM\Column(name="blocked", type="boolean")
     * @Assert\NotBlank()
     */
    protected $blocked;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $created;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $updated;

    /**
     * @ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Event", inversedBy="users", cascade={"persist", "remove"})
     * @ORM\JoinTable(name="users_events",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="cascade")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="event_id", referencedColumnName="id", onDelete="cascade")}
     * )
     */
    protected $events;

    public function __construct()
    {
        $this->roles = array();
        $this->events = new ArrayCollection();
        $this->setCreated(new \DateTime());
        $this->setUpdated(new \DateTime());
    }

    public function __toString()
    {
        return (string) $this->id;
    }

    /**
     * @ORM\PreUpdate
     */
    public function setUpdatedValue()
    {
        $this->setUpdated(new \DateTime());
    }

    /**
     * Set created.
     *
     * @param \DateTime $created
     *
     * @return User
     */
    public function setCreated($created)
    {
        $this->created = $created;

        return $this;
    }

    /**
     * Get created.
     *
     * @return \DateTime
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * Set updated.
     *
     * @param \DateTime $updated
     *
     * @return User
     */
    public function setUpdated($updated)
    {
        $this->updated = $updated;

        return $this;
    }

    /**
     * Get updated.
     *
     * @return \DateTime
     */
    public function getUpdated()
    {
        return $this->updated;
    }

    public function getId()
    {
        return $this->id;
    }

    /**
     * Get Login.
     *
     * @return string
     */
    public function getLogin()
    {
        return $this->login;
    }

    /**
     * Set Login.
     *
     * @param $login
     *
     * @return User
     */
    public function setLogin($login)
    {
        $this->login = $login;

        return $this;
    }

    /**
     * Get Name.
     *
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set Name.
     *
     * @param string $name
     *
     * @return User
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get Email.
     *
     * @return mixed
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set Email.
     *
     * @param mixed $email
     *
     * @return User
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get roles.
     *
     * @return mixed
     */
    public function getRoles()
    {
        return $this->roles;
    }

    /**
     * Set Roles.
     *
     * @param mixed $roles
     *
     * @return User
     */
    public function setRoles($roles)
    {
        $this->roles = array();

        foreach ($roles as $role) {
            $this->addRole($role);
        }

        return $this;
    }

    /**
     * Add role to collection.
     *
     * @param $role
     *
     * @return User
     */
    public function addRole($role)
    {
        $role = strtoupper($role);

        if (!in_array($role, $this->roles, true)) {
            $this->roles[] = $role;
        }

        return $this;
    }

    /**
     * Get Blocked.
     *
     * @return boolean
     */
    public function getBlocked()
    {
        return $this->blocked;
    }

    /**
     * Set Blocked.
     *
     * @param boolean $blocked
     *
     * @return User
     */
    public function setBlocked($blocked)
    {
        $this->blocked = $blocked;

        return $this;
    }

    /**
     * Add event.
     *
     * @param Event $event
     *
     * @return User
     */
    public function addEvent(Event $event)
    {
        if (!$this->events->contains($event)) {
            $this->events[] = $event;
        }

        return $this;
    }

    /**
     * Remove event.
     *
     * @param Event $event
     *
     * @return User
     */
    public function removeEvent(Event $event)
    {
        if ($this->events->contains($event)) {
            $this->events->removeElement($event);
        }

        return $this;
    }

    /**
     * Get events.
     *
     * @return ArrayCollection
     */
    public function getEvents()
    {
        return $this->events;
    }
}

事件

<?php

namespace App\CoreBundle\Entity;

use App\UserBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Event
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="App\CoreBundle\Repository\EventRepository")
 */
class Event
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="event_name", type="string", length=50)
     */
    private $eventName;

    /**
     * @var string
     *
     * @ORM\Column(name="event_description", type="string", length=160)
     */
    private $eventDescription;

    /**
     * @var string
     *
     * @ORM\Column(name="event_type", type="string", length=100)
     */
    private $eventType;

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

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="start_date", type="datetime")
     */
    private $startDate;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="end_date", type="datetime")
     */
    private $endDate;

    /**
     * @ORM\ManyToMany(targetEntity="App\UserBundle\Entity\User", mappedBy="events")
     */
    protected $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set eventName
     *
     * @param string $eventName
     * @return Event
     */
    public function setEventName($eventName)
    {
        $this->eventName = $eventName;

        return $this;
    }

    /**
     * Get eventName
     *
     * @return string 
     */
    public function getEventName()
    {
        return $this->eventName;
    }

    /**
     * Set eventDescription
     *
     * @param string $eventDescription
     * @return Event
     */
    public function setEventDescription($eventDescription)
    {
        $this->eventDescription = $eventDescription;

        return $this;
    }

    /**
     * Get eventDescription
     *
     * @return string 
     */
    public function getEventDescription()
    {
        return $this->eventDescription;
    }

    /**
     * Set eventType
     *
     * @param string $eventType
     * @return Event
     */
    public function setEventType($eventType)
    {
        $this->eventType = $eventType;

        return $this;
    }

    /**
     * Get eventType
     *
     * @return string
     */
    public function getEventType()
    {
        return $this->eventType;
    }

    /**
     * Set visible
     *
     * @param boolean $visible
     * @return Event
     */
    public function setVisible($visible)
    {
        $this->visible = $visible;

        return $this;
    }

    /**
     * Get visible
     *
     * @return boolean 
     */
    public function getVisible()
    {
        return $this->visible;
    }

    /**
     * Set startDate
     *
     * @param \DateTime $startDate
     * @return Event
     */
    public function setStartDate($startDate)
    {
        $this->startDate = $startDate;

        return $this;
    }

    /**
     * Get startDate
     *
     * @return \DateTime 
     */
    public function getStartDate()
    {
        return $this->startDate;
    }

    /**
     * Set endDate
     *
     * @param \DateTime $endDate
     * @return Event
     */
    public function setEndDate($endDate)
    {
        $this->endDate = $endDate;

        return $this;
    }

    /**
     * Get endData
     *
     * @return \DateTime 
     */
    public function getEndDate()
    {
        return $this->endDate;
    }

    /**
     * Set users.
     *
     * @param ArrayCollection $users
     *
     * @return Event
     */
    public function setUsers(ArrayCollection $users)
    {
        $this->users = $users;

        return $this;
    }

    /**
     * Add user.
     *
     * @param User $user
     *
     * @return Event
     */
    public function addUser(User $user)
    {
        if (!$this->users->contains($user)) {
            $this->users[] = $user;
        }

        return $this;
    }

    /**
     * Get user.
     *
     * @return User
     */
    public function getUsers()
    {
        return $this->users;
    }

    /**
     * Remove user
     *
     * @param User $user
     */
    public function removeUser(User $user)
    {
        $this->users->removeElement($user);
    }
}

以下是我尝试查找与用户相关的事件的方法:

    private function getActiveEventsCriteria($camelStyle = true, $dateAsObject = true)
    {
        $currentDateTime = new \DateTime();

        $criteria = Criteria::create()
            ->where(
                Criteria::expr()->andX(
                    Criteria::expr()->lte($camelStyle ? 'startDate' : 'start_date', $dateAsObject ? $currentDateTime : $currentDateTime->format("Y-m-d H:i:s")),
                    Criteria::expr()->gte($camelStyle ? 'endDate' : 'end_date', $dateAsObject ? $currentDateTime : $currentDateTime->format("Y-m-d H:i:s"))
                )
            )
            ->andWhere(Criteria::expr()->eq('visible', 1));

        return $criteria;
    }

    public function getParticipatingEventsBy(User $user)
    {
        $userEvents = $user->getEvents();

        if (is_null($userEvents)) return [];

        return $userEvents->matching($this->getActiveEventsCriteria(false, false));
    }

    $this->getParticipatingEventsBy($user);

在profiler / debug中,我看到下一个sql:

SELECT 
  te.id AS id, 
  te.event_name AS event_name, 
  te.event_description AS event_description, 
  te.event_type AS event_type, 
  te.visible AS visible, 
  te.start_date AS start_date, 
  te.end_date AS end_date 
FROM 
  event te 
  JOIN users_events t ON t.event_id = te.id 
WHERE 
  t.user_id = ? 
  AND te.start_date = ? 
  AND te.end_date = ? 
  AND te.visible = ?

使用应用参数:

SELECT 
  te.id AS id, 
  te.event_name AS event_name, 
  te.event_description AS event_description, 
  te.event_type AS event_type, 
  te.visible AS visible, 
  te.start_date AS start_date, 
  te.end_date AS end_date 
FROM 
  event te 
JOIN users_events t ON t.event_id = te.id 
WHERE 
  t.user_id = 14 AND 
  te.start_date = '2015-12-03 16:26:44' AND 
  te.end_date = '2015-12-03 16:26:44' AND 
  te.visible = 1;

我将WHERE更改为下一个:

WHERE 
  t.user_id = 14 AND 
  te.start_date <= '2015-12-03 16:26:44' AND 
  te.end_date >= '2015-12-03 16:26:44' AND 
  te.visible = 1;

使用那个sql我得到了正确的结果。

当我使用与存储库无关的相同标准时,一切正常:

public function getActiveEvents() {
    return $this->matching($this->getActiveEventsCriteria());
}

public function matching(Criteria $criteria)
{
    return $this->repository->matching($criteria);
}

$this->getActiveEvents();

这是格式化的sql:

SELECT 
  t0.id AS id_1, 
  t0.event_name AS event_name_2, 
  t0.event_description AS event_description_3, 
  t0.event_type AS event_type_4, 
  t0.visible AS visible_5, 
  t0.start_date AS start_date_6, 
  t0.end_date AS end_date_7 
FROM 
  event t0 
WHERE 
  (
    (
      t0.start_date <= ? 
      AND t0.end_date >= ?
    ) 
    AND t0.visible = ?
  )

使用应用参数:

SELECT 
  t0.id AS id_1, 
  t0.event_name AS event_name_2, 
  t0.event_description AS event_description_3, 
  t0.event_type AS event_type_4, 
  t0.visible AS visible_5, 
  t0.start_date AS start_date_6, 
  t0.end_date AS end_date_7 
FROM 
  event t0 
WHERE 
  ((t0.start_date <= '2015-12-03 17:01:47' AND t0.end_date >= '2015-12-03 17:01:47') AND 
  t0.visible = 1);

正如你所看到的,对于我不尝试搜索关系的情况 - 一切正常,我得到了结果。但是当我使用Criteria向用户尝试相关事件时 - 它失败并返回空结果导致错误的sql。

我使用的是php 5.6。*,symfony 2.8,doctrine 2.5.2,最新的MySQL。

任何帮助将非常感谢。 谢谢。

更新
- 在JIRA中创建了问题:here

0 个答案:

没有答案