Doctrine findBy '不等于'

67

我该怎么做

WHERE id != 1

在Doctrine中?

我目前有这个。

$this->getDoctrine()->getRepository('MyBundle:Image')->findById(1);

但是如何表示“不等于”?

这可能很傻,但我找不到任何相关的参考资料。

谢谢

6个回答

75

现在有一种方法可以使用Doctrine的Criteria来实现这一点。

完整的示例可以在如何使用带比较条件的findBy方法中查看,但以下是简要答案。

use \Doctrine\Common\Collections\Criteria;

// Add a not equals parameter to your criteria
$criteria = new Criteria();
$criteria->where(Criteria::expr()->neq('prize', 200));

// Find all from the repository matching your criteria
$result = $entityRepository->matching($criteria);

4
在被接受的答案被接受的时候,它是正确的答案 :) 几年后,情况发生了变化! - El Yobo
3
建议更新为: 使用Doctrine\Common\Collections\Criteria; $expr = Criteria::expr(); $criteria = Criteria::create(); - Jpsy
@Jpsy 我没有跟上Doctrine的最新动态,有什么理由更喜欢它吗? - El Yobo
1
@ElYobo:Doctrine\Common\Collections\Criteria被定义为一个带有静态方法的静态类(参见:http://www.doctrine-project.org/api/collections/1.3/class-Doctrine.Common.Collections.Criteria.html)。因此,应该使用`CLASS::method()`静态访问它,而不是使用`new CLASS()`实例化它。 - Jpsy
是的,你说得对。我复制的片段来自我上面提供的链接,示例代码来自Doctrine开发人员之一Ocramius,因此可能自编写以来该API已更改。 - El Yobo
我已经添加了它,因为现在它是一个独立的答案,如果没有它,它将无法工作,这可能会让新手感到困惑 :) - Martijn

56

没有内置的方法可以实现你想要做的事情。

你需要向你的代码库添加一个方法,像这样:

public function getWhatYouWant()
{
    $qb = $this->createQueryBuilder('u');
    $qb->where('u.id != :identifier')
       ->setParameter('identifier', 1);

    return $qb->getQuery()
          ->getResult();
}
希望这有所帮助。

我不确定这个回答如何解决问题,因为它试图基于值-1匹配记录,而不是查询不等于1的值。 - frak
这个答案在写的时候是正确的,但现在已经得到支持了;请参见我在此问题其他地方的回答。 - El Yobo

24
为了增加一些灵活性,我会把下一个函数添加到我的代码库中:
public function findByNot($field, $value)
{
    $qb = $this->createQueryBuilder('a');
    $qb->where($qb->expr()->not($qb->expr()->eq('a.'.$field, '?1')));
    $qb->setParameter(1, $value);

    return $qb->getQuery()
        ->getResult();
}

然后,我可以在我的控制器中像这样调用它:

$this->getDoctrine()->getRepository('MyBundle:Image')->findByNot('id', 1);

请问您在哪里添加这个方法? - Dency G B
1
在与实体相关的自定义存储库中。在Symfony中,要访问数据,您可以使用默认存储库,并可以定义自己的扩展。请参阅Doctrine文档了解更多信息。 - Luis

16

根据Luis的回答,您可以执行类似于默认findBy方法的某些操作。

首先,创建一个默认的存储库类,将被所有实体使用。

/* $config is the entity manager configuration object. */
$config->setDefaultRepositoryClassName( 'MyCompany\Repository' );

或者您可以在config.yml中进行编辑

doctrine:     orm:         default_repository_class:MyCompany\Repository

然后:

<?php

namespace MyCompany;

use Doctrine\ORM\EntityRepository;

class Repository extends EntityRepository {

    public function findByNot( array $criteria, array $orderBy = null, $limit = null, $offset = null )
    {
        $qb = $this->getEntityManager()->createQueryBuilder();
        $expr = $this->getEntityManager()->getExpressionBuilder();

        $qb->select( 'entity' )
            ->from( $this->getEntityName(), 'entity' );

        foreach ( $criteria as $field => $value ) {
            // IF INTEGER neq, IF NOT notLike
            if($this->getEntityManager()->getClassMetadata($this->getEntityName())->getFieldMapping($field)["type"]=="integer") {
                $qb->andWhere( $expr->neq( 'entity.' . $field, $value ) );
            } else {
                $qb->andWhere( $expr->notLike( 'entity.' . $field, $qb->expr()->literal($value) ) );
            }
        }

        if ( $orderBy ) {

            foreach ( $orderBy as $field => $order ) {

                $qb->addOrderBy( 'entity.' . $field, $order );
            }
        }

        if ( $limit )
            $qb->setMaxResults( $limit );

        if ( $offset )
            $qb->setFirstResult( $offset );

        return $qb->getQuery()
            ->getResult();
    }

}

用法与findBy方法相同,例如:

$entityManager->getRepository( 'MyRepo' )->findByNot(
    array( 'status' => Status::STATUS_DISABLED )
);

10

我很容易解决了这个问题(没有添加方法),所以分享一下:

use Doctrine\Common\Collections\Criteria;

$repository->matching(Criteria::create()->where(Criteria::expr()->neq('id', 1)));

顺便说一下,我正在使用Zend Framework 2中的Doctrine ORM模块,我不确定在其他情况下是否兼容。

在我的情况下,我正在使用这样的表单元素配置:在单选按钮数组中显示除“guest”以外的所有角色。

$this->add([
    'type' => 'DoctrineModule\Form\Element\ObjectRadio',
    'name' => 'roles',
    'options' => [
        'label' => _('Roles'),
        'object_manager' => $this->getEntityManager(),
        'target_class'   => 'Application\Entity\Role',
        'property' => 'roleId',
        'find_method'    => [
            'name'   => 'matching',
            'params' => [
                'criteria' => Criteria::create()->where(
                    Criteria::expr()->neq('roleId', 'guest')
                )
            ],
        ],
    ],
]);

1
你太棒了!我已经找了好久了。你在文档中找到了关于这个的任何信息吗? - halfpastfour.am
1
我非常确定我是通过浏览源代码挖掘出了这个细节。 - Emery King
谢谢你,我相信其他人也在寻找这个。 - halfpastfour.am

2
我使用QueryBuilder获取数据。
$query=$this->dm->createQueryBuilder('AppBundle:DocumentName')
             ->field('fieldName')->notEqual(null);

$data=$query->getQuery()->execute();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接