2014-03-25 57 views
0

我在Controller,Repository中使用了DI。所有存储库都使用BaseRepository进行扩展。但是,当使用FormType给出错误。 错误消息:Symfony2 FormType依赖注入

ContextErrorException: Catchable Fatal Error: Argument 2 passed to Personal\SiteBundle\Repository\BaseRepository::__construct() must be an instance of Memcache, instance of Doctrine\ORM\Mapping\ClassMetadata given, called in /home/personal/www/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php on line 75 and defined in /home/personal/www/src/Personal/SiteBundle/Repository/BaseRepository.php line 22 

我该怎么想?结构如下

AdminBundle/services.yml

personaladmin.towncontroller: 
    class: Personal\AdminBundle\Controller\TownController 
    arguments: ["@personalsite.townrepository", "@doctrine.orm.entity_manager", "@personalsite.townformtype"] 
    parent: "personaladmin.basecontroller" 

SiteBundle/services.yml

services: 
memcache: 
    class: Memcache 
    calls: 
     - [addServer , [127.0.0.1, 11211]] 
personalsite.baserepository: 
    class: Personal\SiteBundle\Repository\BaseRepository 
    arguments: 
     entityManager: "@doctrine.orm.entity_manager" 
     memcacheProvider: "@memcache" 
personalsite.cityrepository: 
    class: Personal\SiteBundle\Repository\CityRepository 
    parent: personalsite.baserepository 
personalsite.townrepository: 
    class: personal\SiteBundle\Repository\TownRepository 
    parent: personalsite.baserepository 

personalsite.townformtype: 
     class: personal\SiteBundle\Form\TownType 
     arguments: ["@personalsite.cityrepository"] 

BaseRepository.php

<?php 
namespace Personal\SiteBundle\Repository; 

use Doctrine\ORM\EntityManager; 
use \Memcache; 

class BaseRepository 
{ 

    protected $_memcacheProvider; 

    /** 
    * Connection 
    * 
    * @var \Doctrine\ORM\EntityManager 
    */ 
    protected $_em; 

    public function __construct(
     EntityManager $entityManager, 
     Memcache $memcachedProvider 
    ) 
    { 
     $this->_memcacheProvider = $memcachedProvider; 
     $this->_em = $entityManager; 
    } 

} 

TownController.php

<?php 

namespace Personal\AdminBundle\Controller; 

use Doctrine\ORM\EntityManager; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; 


use Symfony\Component\HttpFoundation\Request; 
use Personal\AdminBundle\Controller\BaseController; 
use Personal\SiteBundle\Form\TownType; 
use Personal\SiteBundle\Entity\Town; 
use Personal\SiteBundle\Repository\TownRepository; 

/** 
* @Route("/town", service="personaladmin.towncontroller") 
*/ 
class TownController extends BaseController 
{ 

    protected $_townRepository; 
    protected $_entityManager; 

    public function __construct(
     TownRepository $townRepository, 
     EntityManager $entityManager, 
     TownType $townType 
    ) 
    { 
     $this->_townRepository = $townRepository; 
     $this->_entityManager = $entityManager; 
     $this->_townType  = $townType; 
    } 

    /** 
    * @Route("/list", name="managerv3_town_list") 
    * @Template() 
    */ 
    public function townsAction() 
    { 
     $contents = $this->_townRepository->getAll(); 

     return $this->render('PersonalAdminBundle:Town:list.html.twig', array('contents' => $contents)); 
    } 

    /** 
    * @Route("/add", name="managerv3_town_add", defaults={"id" = null}) 
    * @Route("/edit/{id}", name="managerv3_town_edit", defaults={"id" = null}) 
    * @Template() 
    */ 
    public function townAction(Request $request, $id) 
    { 
     if(is_null($id)) 
     { 
      $content = new Town(); 
     } 
     else 
     { 
      $content = $this->_townRepository->getSingle(array('id' => $id)); 
     } 
     $form = $this->createForm($this->_townType, $content); 

     if($request->getMethod() == 'POST') 
     { 
      $form->bind($request); 
      if($form->isValid()) 
      { 
       $this->_entityManager->persist($content); 
       $this->_entityManager->flush(); 
       return $this->redirect($this->generateUrl('managerv3_town_list')); 
      } 
     } 

     return $this->render('PersonalAdminBundle:Town:form.html.twig', array('form' => $form->createView())); 
    } 

TownRepository.php

<?php 

namespace Personal\SiteBundle\Repository; 

use Doctrine\ORM\EntityRepository; 
use Personal\SiteBundle\Repository\BaseRepository; 
use Doctrine\ORM\Query; 

/** 
* TownRepository 
* 
* This class was generated by the Doctrine ORM. Add your own custom 
* repository methods below. 
*/ 
class TownRepository extends BaseRepository 
{ 
    function getAll($orderBy = array('town.title' => 'ASC'), $hydrateMode = false) 
    { 
     $towns = 
      $this->_em 
       ->createQueryBuilder() 
       ->select('town,city') 
       ->from('PersonalSiteBundle:Town', 'town') 
       ->leftJoin('town.city','city'); 

     foreach($orderBy as $oKey => $oVal) 
     { 
      $towns->orderBy($oKey, $oVal); 
     } 

     $result = $towns->getQuery() 
      ->getResult(); 

     return $result; 
    } 

    function getSingle($where = array(), $hydrateMode = null) 
    { 
     $content = 
      $this->_em 
       ->createQueryBuilder() 
       ->select('town,city') 
       ->from('PersonalSiteBundle:Town', 'town') 
       ->leftJoin('town.city', 'city'); 

     foreach($where as $condKey => $condVal) 
     { 
      $parameterKey = 'town_' . $condKey; 

      $content->andWhere("town.{$condKey} = :{$parameterKey}"); 
      $content->setParameter($parameterKey, $condVal); 
     } 

     $result = $content->getQuery(); 

     if($hydrateMode) 
      return $result->getSingleResult(Query::HYDRATE_ARRAY); 

     return $result->getSingleResult(); 
    } 

} 

TownType.php

<?php 

namespace Personal\SiteBundle\Form; 

use Personal\SiteBundle\Repository\CityRepository; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 
use Personal\SiteBundle\Entity\City; 

class TownType extends AbstractType 
{ 
    private $_cityrepository; 
    public function __construct(CityRepository $cityRepository) 
    { 
     $this->_cityrepository = $cityRepository; 
    } 

    /** 
    * @param FormBuilderInterface $builder 
    * @param array $options 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder 
      ->add('title', 'text', array(
       'label' => 'İlçe Adı', 
       'horizontal_label_class' => 'col-lg-2', 
       'horizontal_input_wrapper_class' => 'col-lg-6', 
       'widget_type' => 'inline' 
      )) 
      ->add('slug') 
      ->add('city', 'entity', array(
       'empty_value' => 'Şehir Seçiniz', 
       'class' => 'PersonalSiteBundle:City', 
       'query_builder' => function(){ 
        return $this->_cityrepository->getAll(); 
       }, 
       'property' => 'title', 
       'label' => 'Şehir', 
       'horizontal_label_class' => 'col-lg-2', 
       'horizontal_input_wrapper_class' => 'col-lg-3', 
      )) 
     ; 
    } 

    /** 
    * @param OptionsResolverInterface $resolver 
    */ 
    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'Personal\SiteBundle\Entity\Town' 
     )); 
    } 

    /** 
    * @return string 
    */ 
    public function getName() 
    { 
     return 'personal_sitebundle_town'; 
    } 
} 

感谢您的帮助。

+0

你在service.yml定义的“personalsite.baserepository” beeing构建时总是需要“@memcache”服务为第二个参数,你显然在某些时候缺少 – jahller

+0

@jahller对不起,我加BaseRepository.php –

+0

错误消息是因为Doctrine 2试图获得常规的Doctrine Repository。你的BaseRepository不会扩展我认为是设计的DoctrineRepository?如果是这样,则从您的实体中移除存储库类名,以便Doctrine不会尝试使用它们。但我怀疑你确实希望BaseRepository扩展DoctrineRepository。如果是这样,我可以告诉你需要为你的services.yml – Cerad

回答

0

所以你的BaseRepository需要扩展DoctrineReposotory。 Doctrine使用工厂getRepository方法创建存储库。有没有简单的方法来哄它传递memcache。相反,我们需要使用setter注入。

use Doctrine\ORM\EntityRepository; 
class BaseRepository extends EntityRepository 
{ 
    // No constructor needed 

    // Setter injection 
    setMemcachedProvider(Memcache $memcachedProvider) 
    { 
     $this->_memcacheProvider = $memcachedProvider; 
    } 

在你services.yml文件摆脱BaseRepository服务,然后编辑你的资料库服务:

personalsite.cityrepository: 
    class: Personal\SiteBundle\Repository\CityRepository 
    factory_service: 'doctrine.orm.default_entity_manager' 
    factory_method: 'getRepository' 
    arguments: 
     - 'Personal\SiteBundle\Entity\City' 
    calls: 
     - [setMemcachedProvider, ['@memcache']] 

这应该做的伎俩。

我对你为什么注入memcache有点好奇。我假设你有一些使用它的自定义存储库代码?教义会忽略它。如果您尝试配置Doctrine以使用memcache,那么这完全是一个不同的过程。