2015-06-22 45 views
2

我正在開發一個使用ZF2和Doctrine的網站。我面臨的問題是我在我的代碼中使用Doctrine預定義的對象方法,如findAll(),findOneBy(),findBy()等。對於一些自定義操作,我爲我的一個實體準備了一個定製Repository。現在我無法訪問預定義的方法。我已經使用findAll()方法編寫了代碼。但是在構建存儲庫之後,我不能簡單地訪問findAll()方法。我怎樣才能訪問我自定義的方法以及Doctrine定義的方法?如何訪問自定義存儲庫後的Doctrine定義的方法?

例如:

我使用findOneBy()這樣的:

$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => '[email protected]')); 

現在我已經準備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' => '[email protected]')); 

B ut不是

$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => '[email protected]')); 

爲什麼?我已經使用教義定義的方法編寫代碼。我現在能做什麼?

+0

通過擴展'EntityRepository',您可以訪問默認的預定義方法。當你嘗試執行'findOneBy()'時,你會得到什麼錯誤? – Artamiel

+0

致命錯誤:在194行上的/var/www/html/new_mpt_hk/mpt_hk/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php中的非對象上調用成員函數getUnitOfWork() –

+0

@SubhasisLaha這裏有很多問題。爲什麼改變了這個類的方法簽名?你至少需要*擁有'__construct(Doctrine \ ORM \ EntityManager $ em,Doctrine \ ORM \ Mapping \ ClassMetadata $ class)'。另外你爲什麼要注射'$ sl'?我假設它代表'ServiceLocator'?不需要它,'$ qb = $ this-> sl-> createQueryBuilder();'只是錯誤的。 – AlexP

回答

2

我相信你會得到這個錯誤,因爲你已經重寫了存儲庫的構造函數方法,但沒有調用父構造函數,因此沒有正確設置所需的參數。

+0

我無法得到您的答案。我怎樣才能調用父構造函數,並在哪裏?你能舉個例子嗎? –

+0

我很困難。 Plz的幫助。 –

+1

@SubhasisLaha這個答案是正確的,並且是相當基本的OOP,你需要在'__construct'方法中添加'parent :: __ construct($ entityManager,$ classMetadata)'。 – AlexP

2

你的方法存在幾個問題;

  • 我想嘗試訪問服務定位器本身在一個實體存儲庫是個壞主意。您不應該在存儲庫級別需要服務容器。
  • 第二個細節是,當擴展任何類時,您需要簽出,閱讀並尊重父級的簽名。在你的情況下,你壓倒了父母的__construct。撥打parent::__construct()可能看起來像一個解決方案,但事實並非如此。您很快就會意識到,您還需要一個定製存儲庫工廠來將其他參數傳遞給構造函數,同時保持當前的功能。沒門。
  • 這比其他人更重要:您認爲$this->sl->createQueryBuilder()返回查詢生成器實例。理論上看起來像工作,但$this->sl不是服務定位器,服務定位器不知道任何關於查詢建設者,它只是EntityManager實例傳遞給你的構造函數。在Application\Entity\Usermain實體

    <?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(); 
        } 
    } 
    

    最後,您還需要告訴您的自定義庫教義,因爲你不希望使用默認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' => '[email protected]')); 
// this should also work 
$udata = $repo->findOneBy(array('userEmail' => '[email protected]')); 

我強烈建議仔細閱讀Working With Objects文檔部分,然後深入深入。

+0

非常感謝!正在工作...... –

+0

+1 @SubhasisLaha如果這個答案對你有幫助,[請將它標記爲接受的答案](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-工作#答案-5235) – AlexP

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();