2017-10-16 19 views
2

나는 그것을 알아 냈습니다. 답변은입니다. 질문과 모든 처리 내용을 여기에 남겨두면 누군가가 같은 것을 나중에 도출하는 데 도움이 될 수 있습니다.하지만 대부분은 대답에 의해 중복됩니다.ZF2 + Doctrine 2 - 공장을 사용하여 Doctrine SQLFilter를 작성하십시오 - 어떻게?


입니다 난 할 노력하고있어, 사용자가 (User#company)과 연결되어 있는지 회사를 기반으로 데이터를 필터링.

나는이 시나리오에 대한 몇 가지 엔티티가 :

  • 사용자
  • 회사
  • 주소
  • 시나리오는 데이터,이 경우 Address 엔티티 객체에 의해 생성되는 것을

User 엔티티. 각 User에는 속한 Company 엔터티가 있습니다. 따라서 각 Address에는 Address#createdByCompany 속성이 있습니다.

Doctrine docs - "Working with Filters"에 설명 된대로 SQLFilter 확장을 만들려고합니다.

class CreatedByCompanyFilter extends SQLFilter 
{ 
    /** 
    * @var Company 
    */ 
    protected $company; 

    /** 
    * @param ClassMetadata $targetEntity 
    * @param string $targetTableAlias 
    * @return string 
    * @throws TraitNotImplementException 
    */ 
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) 
    { 
     // Check if Entity implements CreatedByCompanyAwareInterface, if not, return empty string 
     if (!$targetEntity->getReflectionClass()->implementsInterface(CreatedByCompanyInterface::class)) { 

      return ''; 
     } 

     if (!array_key_exists(CreatedByCompanyTrait::class, $targetEntity->getReflectionClass()->getTraits())) { 

      throw new TraitNotImplementException(
       ($targetEntity->getReflectionClass()->getName()) . ' requires "' . CreatedByCompanyTrait::class . '" to be implemented.' 
      ); 
     } 

     return $targetTableAlias . '.created_by_company = ' . $this->getCompany()->getId(); 
    } 

    /** 
    * @return Company 
    */ 
    public function getCompany(): Company // Using PHP 7.1 -> explicit return types 
    { 
     return $this->company; 
    } 

    /** 
    * @param Company $company 
    * @return CreatedByCompanyFilter 
    */ 
    public function setCompany(Company $company): CreatedByCompanyFilter 
    { 
     $this->company = $company; 
     return $this; 
    } 
} 

이 필터를 사용하려면,이 모듈 부트 스트랩 (onBootstrap)에로드 할 설정 및 설정에 등록되어 :

나는 다음과 같은 클래스를 만들었습니다. 지금까지 그렇게 좋았습니다. 위의 내용이 사용되었습니다.

그러나 위 패턴은 공장 패턴을 통해 사용되지 않습니다. 또한 addFilterConstraint(...)$this->getCompany()->getId()을 사용하지만 $this->setCompany()은 아무 곳에서도 호출되지 않으므로 null 값으로 함수 호출을 생성합니다.

어떻게 팩토리를 사용하여 ZF2 ServiceManager의 일반 경로를 사용하거나 Doctrine 자체의 등록을 통해이 클래스를 만들 수 있습니까? 이미 해결책을 찾기 위해 노력하고, 지난 몇 시간 동안 많은 Google'ing하는

다음을 시도했다


, 나는 또한 다음

을 시도했습니다 1 - ZF2 공장

공장에서 구성을 등록하는 기본 ZF2 방법을 사용하면 작동하지 않습니다.

'service_manager' => [ 
    'factories' => [ 
     CreatedByCompanyFilter::class => CreatedByCompanyFilterFactory::class, 
    ], 
], 

공장은 결코 간단히 호출되지 않습니다. 이것은 실행의 순서와 관련이있을 수 있습니다. ServiceManager가 완전히 실행되기 전에 Doctrine SQLFilters가 설정되었다고 생각하고 있습니다. 시나리오를 수행하려고 할 때를 대비해 일부 역할 기반 항목 (또는 "company-stuff")을 기반으로 사용자 데이터를 필터링합니다. 이 경우).

2 -이 작업을하는 동안 Ocramius's ZF2 Delegator Factories

나는 Ocramius의 위임자의 공장을 발견했다. 매우 흥미로운 것들, 확실히 읽을 가치가 있고 멋지게 작동합니다. 그러나, 내 시나리오 아닙니다. 나는 그의 가이드를 따라 CreatedByCompanyFilterDelegatorFactory을 만들었습니다. 이것은 내가 config에 등록했지만 결과가 없으므로 실제 Factory는 결코 호출되지 않습니다.

는 (죄송합니다, 제거 코드 이미)


공장은 내가

class CreatedByCompanyListenerFactory implements FactoryInterface 
{ 
    // NOTE: REMOVED DOCBLOCKS/COMMENTS FOR LESS CODE 
    public function createService(ServiceLocatorInterface $serviceLocator) 
    { 
     $authService = $serviceLocator->get('zfcuser_auth_service'); 
     $user = $authService->getIdentity(); 

     $listener = new CreatedByCompanyListener(); 
     $listener->setCompany($user->getCompany()); 

     return $listener; 
    } 
} 

이하 '현재 시도'를 참조
*ListenerFactory으로 업데이트를 실행하기 위해 노력하고있어

현재 tr ying

나는 Gedmo Extensions와 Doctrine Events 지침서에서 한 페이지를 가져와 loadClassMetadata 이벤트에 Listener를 연결하는 형식을 사용할 수 있다고 생각했습니다. 다음

그래서 내가 생각
'eventmanager' => [ 
    'orm_default' => [ 
     'subscribers' => [ 
      SoftDeleteableListener::class, 
     ], 
    ], 
], 
'configuration' => [ 
    'orm_default' => [ 
     'filters' => [ 
      'soft-deleteable' => SoftDeleteableFilter::class, 
     ], 
    ], 
], 

, 지옥의 그 시도하자 및 설정 :

'eventmanager' => [ 
    'orm_default' => [ 
     'subscribers' => [ 
      CreatedByCompanyListener::class, 
     ], 
    ], 
], 
'configuration' => [ 
    'orm_default' => [ 
     'filters' => [ 
      'created-by-company' => CreatedByCompanyFilter::class, 
     ], 
    ], 
], 
'service_manager' => [ 
    'factories' => [ 
     CreatedByCompanyListener::class => CreatedByCompanyListenerFactory::class, 
    ], 
], 
예를 들어

, Gedmo의 SoftDeleteable은 다음과 그것이 작동되도록하는 교리의 설정에서 설정을 가지고

인증 목적의 User 엔티티를 *Listener에 가져 오기 위해 *ListenerFactory을 사용하는 것이 목적입니다. *ListenerUser과 연결된 CompanyCreatedByCompanyFilter에 전달 된 EventArgs으로 전달합니다. 이론적으로는 그 객체를 사용할 수 있어야합니다.

CreatedByCompanyLister 다음, 지금이다 : 그러나,이 *ListenerFactory에 사용되는 Zend\Authentication\AuthenticationService에 갇히지있어

class CreatedByCompanyListener implements EventSubscriber 
{ 
    //NOTE: REMOVED DOCBLOCKS/HINTS FOR LESS CODE 
    protected $company; 

    public function getSubscribedEvents() 
    { 
     return [ 
      Events::loadClassMetadata, 
     ]; 
    } 

    public function loadClassMetadata(EventArgs $eventArgs) 
    { 
     $test = $eventArgs; // Debug line, not sure on what to do if this works yet ;) 
    } 

    // $company getter/setter 
} 

, 그것은 User의 정체성을 얻으려고 노력 예외가 발생합니다 $user = $authService->getIdentity();.

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for doctrine.entitymanager.orm_default

어떻게 든 전화 (PhpStorm에서 Xdebug는)를 통해 스테핑 :

는 내부적으로이 기능은 getMapper()에 던지고, 그것은 충돌 ZfcUser\Authentication\Storage\Db 클래스, 라인 (70), ($identity = $this->getMapper()->findById($identity);)로 계속 그것은 조금 더 (wtf의 비트에 대한 계속 ...)하지만 다음 예외 :

An exception was raised while creating "zfcuser_user_mapper"; no instance returned

라는 "* 예외 * 이전"으로 :

Circular dependency for LazyServiceLoader was found for instance Doctrine\ORM\EntityManager

자주적으로 내가 알고있는 모든 이러한 오류의 의미는 없지만 같은 함수 호출 (->getMapper())에 의해 throw 된 모든 것을 본 적이 없습니다. b efore. 어떤 아이디어?

답변