写" NOT IN"在Doctrine查询语言中

时间:2014-03-24 16:33:05

标签: php symfony doctrine-orm doctrine

我有两张表company(id, ...)company_has_wtax(company_id, ....)。我需要让所有不在company_has_wtax表中的公司。在原始SQL中应该是这样的:

SELECT id FROM company LEFT JOIN (company_has_wtax) 
                       ON company.id = company_has_wtax.company_id

但我不知道如何在DQL for Doctrine上构建这个,有什么帮助?

向存储库添加方法并从Controller

调用它

这是我在@Javad回答后留下的代码:

public function findCompanyByDocument() {
    $q2 = $this->createQueryBuilder('ApprovalBundle:CompanyHasWtax c2');

    $query = $this->createQueryBuilder('c')
            ->leftJoin('c.CompanyHasWtax', 'chw')
            ->where($query->expr()->notIn('c.id', $q2->select('c2.company')->getDQL())
    );

    echo $query->getQuery()->getSQL();
    // return $query->getQuery()->getResult();
}

这就是我在控制器中调用它的方式:

$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('RegisterCompanyBundle:Company')->findCompanyByDocument();

但是我收到了这个错误:

  

ContextErrorException:注意:未定义的变量:查询输入   /var/www/html/kraken/src/Company/RegisterCompanyBundle/Entity/Repository/CompanyRepository.php   第40行

第40行是->where($query->expr()->notIn('c.id', $q2->select('c2.company')->getDQL())

这是实体:

Company.php

class Company {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer", unique=true, nullable=false)
     * @ORM\GeneratedValue
     * 
     */
    protected $id;

    /**
     * @ORM\Column(name="legal_name",type="string",nullable=false,length=255)
     * @Assert\NotBlank(message="Este valor no debería estar vacío.")
     * @Assert\Regex("/^[a-zA-Z0-9ñÑÁÉÍÓÚñáéíóú\s\,]+$/", message="Este valor debería ser de tipo alfanumérico.")
     */
    protected $legalName;

    /**
     * @ORM\Column(name="social_reason",type="string",nullable=false,length=255)
     * @Assert\NotBlank(message="Este valor no debería estar vacío.")
     * @Assert\Regex("/^[a-zA-Z0-9ñÑÁÉÍÓÚñáéíóú\s\,]+$/", message="Este valor debería ser de tipo alfanumérico.")
     */
    protected $socialReason;

    /**
     * @ORM\Column(name="tax_id",type="string",nullable=false)
     * @Assert\NotBlank(message="Este valor no debería estar vacío.")
     * @Assert\Regex("/^[\d{9}$]/", message="Este valor debería tener exactamente 9 caracteres.")
     */
    protected $taxId;

    /**
     * @ORM\OneToOne(targetEntity="Common\MediaBundle\Entity\Media")
     * @ORM\JoinColumn(name="logo", referencedColumnName="id")
     */
    protected $logo;

    /**
     * @ORM\OneToOne(targetEntity="Common\MediaBundle\Entity\Media")
     * @ORM\JoinColumn(name="banner", referencedColumnName="id")
     */
    protected $banner;

    /**
     * @ORM\OneToOne(targetEntity="Company\RegisterCompanyBundle\Entity\NCompanyType")
     * @ORM\JoinColumn(name="type", referencedColumnName="id")
     */
    protected $type;

    /**
     * @ORM\OneToOne(targetEntity="Company\RegisterCompanyBundle\Entity\NCompanyStatus")
     * @ORM\JoinColumn(name="status", referencedColumnName="id")
     */
    protected $status;

    /**
     * @ORM\Column(type="integer",nullable=false,length=1)
     */
    protected $certified;    
}

CompanyHasWtax.php

class CompanyHasWtax {

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="\Company\RegisterCompanyBundle\Entity\Company")
     * @ORM\JoinColumn(name="company", referencedColumnName="id")
     */
    protected $company;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="\Configuration\FeeBundle\Entity\Fee")
     * @ORM\JoinColumn(name="wtax", referencedColumnName="id")
     */
    protected $wtax;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="\User\SecurityBundle\Entity\User")
     * @ORM\JoinColumn(name="kuser", referencedColumnName="id")
     */
    protected $user;

    /**
     * @ORM\Column(name="from_date", type="datetime")
     */
    protected $from_date;

    /**
     * @ORM\Column(name="to_date", type="datetime")
     */
    protected $to_date;

}

丑陋的解决方案

我找到了一种让这种方法有效的方法,但这对我来说很难看,也有人说我这样做是不对的:

public function findCompanyByDocument() {
    $sql = "SELECT * FROM company c WHERE c.id NOT IN (SELECT chm.company FROM company_has_media chm WHERE chm.company = c.id)";
    $em = $this->getEntityManager();

    return $em->getConnection()->fetchAll($sql);
}

2 个答案:

答案 0 :(得分:4)

试试这个:

$q2 = $this->createQueryBuilder('c')
    ->select('IDENTITY(c2.company)')
    ->join('RegisterCompanyBundle:CompanyHasMedia', 'c2', 'WITH', 'c2.company = c.id');

$query = $this->createQueryBuilder('c3');
$query->where($query->expr()->notIn('c3.id', $q2->getDQL()));

$companies = $query->getQuery()->getResult();

请注意我们通过reversedBy / mappedBy来创建一个无相关实体的查询 我们需要将IDENTIY用于相关表格的特定字段

答案 1 :(得分:2)

试试这个:

$em = $this->getDoctrine()->getManager();

$query = $em->createQuery('SELECT * FROM YourBundle\Entity\Company c WHERE c.id NOT IN (SELECT c2.company_id FROM YourBundle\Entity\Company_has_wtax c2)');

$companies = $query->getResult(); // array of Company objects