在两个关系上有条件地查找实体

时间:2015-09-23 14:39:19

标签: sql symfony doctrine-orm dql

这是我的问题:

我有3个实体:联系邮寄 MailTemplate

邮件仅用于向许多联系人发送 MailTemplate ;在关系方面,邮件 ManyTomany 联系人的关系以及 ManyToOne 与<的关系定义强> MailTemplate

我的一些 MailTemplate 实体有一个布尔字段“unique”,以便说这个模板应该多次发送给同一个联系人。说到前端,我有一个视图,我可以选择联系人并向他们发送邮件模板。

以下是这样的事情:我想限制显示的联系人,仅限于那些我没有发送邮件模板的人!

因此,如果 MailTemplate 的字段为“唯一”,我只想获得尚未收到此模板的联系实体;我尝试了很多东西,但是无法用DQL或Query Builder来解决这个问题。因为联系 MailTemplate 邮件 > ...

我可以获取所有联系人,然后循环浏览邮件并删除其中一些,但我希望这更加优化。

编辑 - 我的实体:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table
 * @ORM\Entity(repositoryClass="AppBundle\Entity\ContactRepository")
 */
class Contact
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

/**
 * @ORM\ManyToOne(targetEntity="ContactType", fetch="EAGER")
 */
protected $type;

/**
 * @ORM\Column(type="string", length=255)
 */
protected $name;

/**
 * @ORM\ManyToOne(targetEntity="Place", fetch="EAGER", cascade={"ALL"})
 */
protected $place;

/**
 * @ORM\Column(type="string", length=255)
 */
protected $email;

/**
 * @ORM\Column(type="string", length=20)
 */
protected $phone;

/**
 * @ORM\Column(type="string", length=255)
 */
protected $website;

/**
 * @ORM\Column(type="text")
 */
protected $description;

/**
 * @ORM\ManyToOne(targetEntity="User", fetch="EAGER")
 */
protected $createdBy;

/**
 * @ORM\OneToMany(targetEntity="Action", mappedBy="contact")
 */
protected $actions;

/**
 * @ORM\OneToMany(targetEntity="MailSent", mappedBy="contact")
 */
protected $mailSent;

/*
 * Custom methods
 */
public function isMailSent(\AppBundle\Entity\MailTemplate $template)
{
    foreach ($this->getMailSent() as $mailSent) {
        if ($mailSent->getTemplate() == $template) {
            return true;
        }
    }

    return false;
}

/*
 * Getters & Setters
 */

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

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

    return $this;
}

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

/**
 * Set email
 *
 * @param string $email
 * @return Contact
 */
public function setEmail($email)
{
    $this->email = $email;

    return $this;
}

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

/**
 * Set phone
 *
 * @param string $phone
 * @return Contact
 */
public function setPhone($phone)
{
    $this->phone = $phone;

    return $this;
}

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

/**
 * Set website
 *
 * @param string $website
 * @return Contact
 */
public function setWebsite($website)
{
    $this->website = $website;

    return $this;
}

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

/**
 * Set description
 *
 * @param string $description
 * @return Contact
 */
public function setDescription($description)
{
    $this->description = $description;

    return $this;
}

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

/**
 * Set type
 *
 * @param \AppBundle\Entity\ContactType $type
 * @return Contact
 */
public function setType(\AppBundle\Entity\ContactType $type = null)
{
    $this->type = $type;

    return $this;
}

/**
 * Get type
 *
 * @return \AppBundle\Entity\ContactType 
 */
public function getType()
{
    return $this->type;
}

/**
 * Set place
 *
 * @param \AppBundle\Entity\Place $place
 * @return Contact
 */
public function setPlace(\AppBundle\Entity\Place $place = null)
{
    $this->place = $place;

    return $this;
}

/**
 * Get place
 *
 * @return \AppBundle\Entity\Place 
 */
public function getPlace()
{
    return $this->place;
}

/**
 * Set createdBy
 *
 * @param \AppBundle\Entity\User $createdBy
 * @return Contact
 */
public function setCreatedBy(\AppBundle\Entity\User $createdBy = null)
{
    $this->createdBy = $createdBy;

    return $this;
}

/**
 * Get createdBy
 *
 * @return \AppBundle\Entity\User 
 */
public function getCreatedBy()
{
    return $this->createdBy;
}
/**
 * Constructor
 */
public function __construct()
{
    $this->actions = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add actions
 *
 * @param \AppBundle\Entity\Action $actions
 * @return Contact
 */
public function addAction(\AppBundle\Entity\Action $actions)
{
    $this->actions[] = $actions;

    return $this;
}

/**
 * Remove actions
 *
 * @param \AppBundle\Entity\Action $actions
 */
public function removeAction(\AppBundle\Entity\Action $actions)
{
    $this->actions->removeElement($actions);
}

/**
 * Get actions
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getActions()
{
    return $this->actions;
}

/**
 * Add mailSent
 *
 * @param \AppBundle\Entity\MailSent $mailSent
 * @return Contact
 */
public function addMailSent(\AppBundle\Entity\MailSent $mailSent)
{
    $this->mailSent[] = $mailSent;

    return $this;
}

/**
 * Remove mailSent
 *
 * @param \AppBundle\Entity\MailSent $mailSent
 */
public function removeMailSent(\AppBundle\Entity\MailSent $mailSent)
{
    $this->mailSent->removeElement($mailSent);
}

/**
 * Get mailSent
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getMailSent()
{
    return $this->mailSent;
}

}

邮寄

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Mailing
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

/**
 * @ORM\ManyToMany(targetEntity="Contact")
 */
protected $contacts;

/**
 * @ORM\ManyToOne(targetEntity="MailTemplate")
 */
protected $template;
/**
 * Constructor
 */
public function __construct()
{
    $this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add contacts
 *
 * @param \AppBundle\Entity\Contact $contacts
 * @return Mailing
 */
public function addContact(\AppBundle\Entity\Contact $contacts)
{
    $this->contacts[] = $contacts;

    return $this;
}

/**
 * Remove contacts
 *
 * @param \AppBundle\Entity\Contact $contacts
 */
public function removeContact(\AppBundle\Entity\Contact $contacts)
{
    $this->contacts->removeElement($contacts);
}

/**
 * Get contacts
 *
 * @return \Doctrine\Common\Collections\Collection 
 */
public function getContacts()
{
    return $this->contacts;
}

/**
 * Set template
 *
 * @param \AppBundle\Entity\MailTemplate $template
 * @return Mailing
 */
public function setTemplate(\AppBundle\Entity\MailTemplate $template = null)
{
    $this->template = $template;

    return $this;
}

/**
 * Get template
 *
 * @return \AppBundle\Entity\MailTemplate 
 */
public function getTemplate()
{
    return $this->template;
}

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

}

MailTemplate

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

use Symfony\Component\HttpFoundation\File\UploadedFile;


/**
 * @ORM\Table
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks()
 */
class MailTemplate
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

/**
 * @ORM\Column(type="string", length=255)
 */
protected $label;

/**
 * @ORM\Column(type="string", length=255)
 */
protected $subject;

/**
 * @ORM\Column(type="text", nullable=true)
 */
protected $content;

/**
 * @ORM\Column(name="uniqueSend", type="boolean")
 */
protected $unique = false;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
protected $templatePath;

/**
 * @Assert\File(maxSize="6000000")
 */
private $file;

private $temp;

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

/**
 * Set label
 *
 * @param string $label
 * @return MailTemplate
 */
public function setLabel($label)
{
    $this->label = $label;

    return $this;
}

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

/**
 * Set subject
 *
 * @param string $subject
 * @return MailTemplate
 */
public function setSubject($subject)
{
    $this->subject = $subject;

    return $this;
}

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

/**
 * Set content
 *
 * @param string $content
 * @return MailTemplate
 */
public function setContent($content)
{
    $this->content = $content;

    return $this;
}

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

/**
 * Set templatePath
 *
 * @param string $templatePath
 * @return MailTemplate
 */
public function setTemplatePath($templatePath)
{
    $this->templatePath = $templatePath;

    return $this;
}

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

public function getAbsolutePath()
{
    return null === $this->templatePath
        ? null
        : $this->getUploadRootDir() . '/' . $this->templatePath;
}

public function getWebPath()
{
    return null === $this->templatePath
        ? null
        : $this->getUploadDir() . '/' . $this->templatePath;
}

protected function getUploadRootDir()
{
    // the absolute directory path where uploaded
    // documents should be saved
    return __DIR__ . '/../../../web/' . $this->getUploadDir();
}

protected function getUploadDir()
{

    return 'uploads/templates';
}

/**
 * Sets file.
 *
 * @param UploadedFile $file
 */
public function setFile(UploadedFile $file = null)
{
    $this->file = $file;
    // check if we have an old image path
    if (isset($this->templatePath)) {
        // store the old name to delete after the update
        $this->temp = $this->templatePath;
        $this->templatePath = null;
    } else {
        $this->templatePath = 'initial';
    }
}

/**
 * Get file.
 *
 * @return UploadedFile
 */
public function getFile()
{
    return $this->file;
}

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function preUpload()
{
    if (null !== $this->getFile()) {
        // do whatever you want to generate a unique name
        $filename = sha1(uniqid(mt_rand(), true));
        $this->templatePath = $filename.'.'.$this->getFile()->guessExtension();
    }
}

/**
 * @ORM\PostPersist()
 * @ORM\PostUpdate()
 */
public function upload()
{
    if (null === $this->getFile()) {
        return;
    }

    // if there is an error when moving the file, an exception will
    // be automatically thrown by move(). This will properly prevent
    // the entity from being persisted to the database on error
    $this->getFile()->move($this->getUploadRootDir(), $this->templatePath);

    // check if we have an old image
    if (isset($this->temp) && file_exists($this->getUploadRootDir() . '/' . $this->temp)) {
        // delete the old image
        unlink($this->getUploadRootDir().'/'.$this->temp);
        // clear the temp image path
        $this->temp = null;
    }
    $this->file = null;
}

/**
 * @ORM\PostRemove()
 */
public function removeUpload()
{
    $file = $this->getAbsolutePath();
    if ($file) {
        if (file_exists($file)) {
            unlink($file);
        }
    }
}

/**
 * Set unique
 *
 * @param boolean $unique
 * @return MailTemplate
 */
public function setUnique($unique)
{
    $this->unique = $unique;

    return $this;
}

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

}

示例数据

template1 : MailTemplate { id: 1, unique: true }
template2 : MailTemplate { id: 2, unique: false }
template3: MailTemplate { id: 3, unique: true }

user1 : { id: 1 }
user2 : { id: 2 }
user3 : { id: 3}

mailing1 : Mailing { id: 1, contacts: { 1, 2 }, template: 1 }
mailing2: Mailing { id: 2, contacts: { 1 }, template: 3 }

应该导致:

Users available for template1 : user3
Users available for template2 : user1, user2, user3
Users available for template3 : user2, user3

1 个答案:

答案 0 :(得分:0)

首先,您必须使关系联系&lt; - &gt;邮寄双向。这意味着必须有一个财产&#34;邮件&#34;在您的联系人实体中。然后,您可以在表单中使用查询构建器属性,如下所示:

$template = $builder->getData()->getTemplate();
$builder
        ->add('contact', 'entity', 
            array(
                'class' => 'AppBundle:Contact',
                'query_builder' => function($contactRepository) use ($template){

                    return $contactRepository->createQueryBuilder('c')
                        ->leftJoin('c.mailings', 'm', 'WITH', 'm.template = :template')
                        ->where('m.template IS NULL')
                        ->setParameter('template', $template);
                }
            );

这应该只返回没有相关邮件的联系人,模板是当前模板。