2013-02-07 82 views
1

我目前想知道如何使ZF2模塊可複製從一個項目到另一個項目,如果我有相互引用的doctrine2實體,那麼這是一個好方法避免兩個模塊中的實體之間的循環依賴關係

我現在的情況是這樣的:我有一個實體User,我希望能夠訪問該用戶說的所有語言。

當然,Language不是Authentication模塊的組件,因爲我可能也想將其用於其他目的。

namespace Authentication\Entity; 

class User { 
    public function getSpokenLanguages(); 
} 

和:

namespace Application\Entity; 

class Language { 
    public function getUsersWhoSpeakThisLanguage(); 
} 

的問題是,我希望我的Authentication模塊是從具體項目模塊Application完全獨立。

也可把這些關係我的實體或可能從Application模塊注入他們的好辦法?也許也給我的語言Language[]特定UserUserService(在Application模塊)會是個好主意嗎?我可以這樣稱呼它:

$userService->getUsersLanguages($user); 

我認爲,特別是注射可能是一個ZF2的解決方案,但我不知道,如何擴展Doctrine2實體一樣,從另一個模塊。

回答

1

我覺得你說話更多的語義問題,而不是一個特定的ZF2。閱讀你的問題,我認爲你的語言變得更像是一個管理層,你可以很容易地與工廠和DI交流 - 幸運的是ZF2擁有所有正確的工具。考慮這樣的事情,作爲一個解決一個潛在的草案:

創建LanguageAbstractFactory

namespace Your\Namespace; 

use Zend\ServiceManager\AbstractFactoryInterface, 
    Zend\ServiceManager\ServiceLocatorInterface; 

class LanguageAbstractFactory implements AbstractFactoryInterface 
{ 
    /** 
    * Determine if we can create a service with name 
    * 
    * @param ServiceLocatorInterface $serviceLocator 
    * @param       $name 
    * @param       $requestedName 
    * @return bool 
    */ 
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) 
    { 
     return stristr($requestedName, 'Namespace\Language') !== false; 
    } 


    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) 
    { 
     $filter = new $requestedName(); 
     $filter->setServiceLocator($locator); 
     return $filter; 
    } 

} 

然後,在同一個命名空間創建您的語言,因爲語言的子類,實現ServiceLocatorAwareInterface(給你數據庫訪問等)。上述工廠裏的代碼注入的服務定位器(而這也正是你調整它注入其他善良,以滿足您的語言體系結構):

namespace Your\Namespace; 

use Zend\ServiceManager\ServiceLocatorAwareInterface, 
    Zend\ServiceManager\ServiceLocatorInterface; 


class Language implements ServiceLocatorAwareInterface 
{ 

    protected $serviceLocator; 


    public function setServiceLocator(ServiceLocatorInterface $serviceLocator) 
    { 
     $this->serviceLocator = $serviceLocator; 
    } 

    public function getServiceLocator() 
    { 
     return $this->serviceLocator; 
    } 

    // ... other things your factory knows, that this class may not go here 
} 

一個語言實現,那麼可能看起來像:

namespace Your\Namespace\Language; 

class English extends \Your\Namespace\Language 
{ 

    public function getUsersWhoSpeakThisLanguage() 
    { 
     $sm = $this->getServiceManager(); 
     // get your entities or w/e using the SM 
    } 
} 

通過getServiceConfig調整你的模塊Module.php工廠連接:

公共職能getServiceConfig(){ 回報陣列(

 'abstract_factories' => array(
      // this one generates all of the mass email filters 
      'Your\Namespace\LanguageAbstractFactory', 
     ), 

    ); 
} 

這使您能夠使用服務管理器輕鬆獲得服務感知型語言。例如從服務感知類:

$sm->getServiceManager()->get('\Your\Namespace\Language\English'); 

因爲配置的,並且該工廠能夠滿足要求,你的工廠將自動配置與您建立到它在一個非常時尚便攜任何邏輯的英語實例。

如果這是工廠的入門書 - 如果您安裝了服務可以用來與您的用戶類對話的接口類,則可以將控制反轉爲來自用戶的語言服務。讓您的用戶實現LanguageAware(例如),其中包含Language服務可以使用的類應該在幾步之外。

希望這會有所幫助。有可能有15種方法來剝皮這隻貓;這種方法是我用來解決類似問題的方法,例如「過濾」數據。過濾器可以過濾信息,信息可以通過過濾器進行過濾。

祝你好運!

+0

我在從服務定位器調用語言的新實例時遇到問題,無法理解工廠如何調用。我看不到它的一個規則。還有一個更大的問題:我看不出它如何幫助我擺脫用戶 - >應用程序依賴。我仍然有一個硬編碼的方法'getStuffFromOtherModule()',不是嗎?猜猜這是因爲我完全不習慣使用DI和ServiceLocators。 – Aufziehvogel

+0

@Aufziehvogel檢查http://blog.evan.pro/introduction-to-the-zend-framework-2-servicemanager – Ocramius