【问题标题】:How to access Doctrine defined methods after custom Repository is made?创建自定义存储库后如何访问 Doctrine 定义的方法?
【发布时间】:2015-06-22 10:31:20
【问题描述】:

我正在使用 ZF2 和 Doctrine 开发一个网站。我面临的问题是我在代码中使用了 Doctrine 预定义的对象方法,如 findAll()、findOneBy()、findBy() 等。对于一些自定义操作,我为我的一个实体准备了一个自定义存储库。现在我无法访问预定义的方法。我已经使用 findAll() 方法编写了代码。但是在构建存储库之后,我不能简单地访问 findAll() 方法。如何同时访问自定义定义的方法和 Doctrine 定义的方法?

例如:

我正在像这样使用 findOneBy():

$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => 'subh.laha@gmail.com'));

现在我已经准备好了 UsermainRepository,如下所示:

namespace Application\Entity\Repositories;

use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ObjectRepository;

class UsermainRepository extends EntityRepository
{   
    protected $sl;

    public function __construct($sl){

        $this->sl = $sl;    
    }

    public function customFind($arr)
    {
        $qb = $this->sl->createQueryBuilder();

        $whereStr = '';

        if(count($arr)){

            foreach($arr as $kvarr=>$varr){

                $whereStr .= "u.$kvarr = '".$varr."'";  
            }   
        }

        $qry = $qb->select('u')
                   ->from('Application\Entity\Usermain','u')
                   ->where($whereStr)
                   ->getQuery()
                   ->getResult(); 

        return $qry;
    }
}

现在我可以访问了

$udata = $this->em()->getRepository('Application\Entity\Usermain')->customFind(array('userEmail' => 'subh.laha@gmail.com'));

但不是

$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => 'subh.laha@gmail.com'));

为什么?我已经使用学说定义的方法编写了代码。我现在能做什么?

【问题讨论】:

  • 扩展 EntityRepository 默认情况下使您可以访问预定义的方法。当您尝试执行 findOneBy() 时,您究竟会得到什么错误?
  • 致命错误:在 /var/www/html/new_mpt_hk/mpt_hk/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository 中的非对象上调用成员函数 getUnitOfWork()。第194行的php
  • @SubhasisLaha 你这里有很多问题。为什么更改了类的方法签名?您需要至少拥有__construct( Doctrine\ORM\EntityManager $em, Doctrine\ORM\Mapping\ClassMetadata $class )。另外你为什么要注入$sl?我假设它代表ServiceLocator?不需要它,$qb = $this->sl->createQueryBuilder(); 是错误的。

标签: php symfony zend-framework2 doctrine


【解决方案1】:

我相信您收到此错误是因为您已覆盖存储库的构造函数方法,但没有调用父构造函数,因此未正确设置所需的参数。

【讨论】:

  • 我无法得到您的答复。如何调用父构造函数以及在哪里?你能给我举个例子吗?
  • 我深陷其中。请帮忙。
  • @SubhasisLaha 这个答案是正确的并且是相当基本的OOP,您需要将parent::__construct($entityManager, $classMetadata)添加到__construct方法中。
【解决方案2】:

我认为您的代码不正确,您可以使用以下查询而不是编写复杂的自定义对象。

$query = $this->getEntityManager()->createQueryBuilder()
                    ->select('U.id,U.name')  
                    ->from('Application\Entity\StudentClass', 'U')
                    ->where('U.pkStudentClass = :pkStudentClass')
                    ->setParameter('pkStudentClass', 1)
                    ->setMaxResults(20); 
                    ->orderBy('id', 'DESC') 
                    ->getQuery();

 $result = $query->getScalarResult();

【讨论】:

    【解决方案3】:

    您的方法存在几个问题;

    • 我认为尝试在实体存储库中访问服务定位器本身是个坏主意。您不应该需要存储库级别的服务容器。
    • 第二个细节是,在扩展任何类时,您需要签出、阅读并尊重父级的签名。在您的情况下,您将覆盖父母的__construct。调用parent::__construct() 似乎是一个解决方案,但事实并非如此。您很快就会意识到,您还需要一个自定义存储库工厂来将其他参数传递给构造函数,同时保持当前功能。没办法。
    • 这比其他人更重要:您相信$this->sl->createQueryBuilder() 返回查询构建器实例。理论上似乎可行,但$this->sl 不是服务定位器,服务定位器对查询构建器一无所知,它只是传递给您的构造函数的EntityManager 实例。

    试试这个:

    <?php
    namespace Application\Entity\Repositories;
    
    use Doctrine\ORM\EntityRepository;
    
    class UsermainRepository extends EntityRepository
    {
    
        public function customFind($arr)
        {
            // Just pass an alias for your entity
            $qb = $this->createQueryBuilder('u');
    
            $whereStr = '';
    
            if (count($arr)) {
                foreach ($arr as $kvarr => $varr) {
                    $whereStr .= "u.$kvarr = '".$varr."'";
                }
            }
    
            return $qb->where($whereStr)
                      ->getQuery()
                      ->getResult();
        }
    }
    

    最后,在您的 Application\Entity\Usermain 实体中,您还需要将您的自定义存储库告知教义,因为您不想使用默认的 EntityRepository

    namespace Application\Entity;
    
    /**
     * @ORM\Entity(repositoryClass="Application\Entity\Repositories\UsermainRepository")
     */
    class Usermain
    {
    
    }
    

    现在在您的控制器(或服务)级别,您可以测试:

    $em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
    $repo = $em->getRepository('Application\Entity\Usermain');
    // repo is a UsermainRepository instance
    // this should work:
    $udata = $repo->customFind(array('userEmail' => 'subh.laha@gmail.com'));
    // this should also work
    $udata = $repo->findOneBy(array('userEmail' => 'subh.laha@gmail.com'));
    

    我强烈建议您在深入研究之前仔细阅读文档的Working With Objects 部分。

    【讨论】:

    猜你喜欢
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多