2012-10-21 26 views
5

Câu hỏi của tôi ngắn gọn: Tôi có thể sử dụng một Nhà máy duy nhất cho nhiều bộ điều khiển không?Nhà máy đơn lẻ cho nhiều bộ điều khiển?

Thông tin chi tiết:

Tôi có một số cài đặt cụ thể phi mô-đun trên toàn cầu trong /config/autoload/global.php mà trông như thế này:

return array(
    'settings' => array(
     'setting_a' => 'foo', 
     'setting_b' => 'bar' 
    ), 

    // More ZF default configuration ... 
); 

Bây giờ tôi muốn thực hiện các thiết lập này có thể truy cập trong mọi bộ điều khiển mà không phải gọi số $this->getServiceLocator()->get('config') mọi lúc.

Vì vậy, ý tưởng của tôi là giới thiệu thuộc tính lớp $settings trong số AbstractController thuộc tính được tiêm vào mảng cấu hình. Tôi đã cố gắng tìm nạp cấu hình trực tiếp trong hàm tạo của AbstractController. Tuy nhiên getServiceLocator() dường như không sẵn sàng vào thời điểm đó và trả về NULL.

tôi có thể xây dựng nhà máy điều khiển cho mỗi bộ điều khiển và tiêm các thiết lập như thế này:

class ControllerFactory implements FactoryInterface 
{ 
    public function createService(ServiceLocatorInterface $serviceLocator) { 
     $config = $serviceLocator->get('config'); 
     return new \MyModule\Controller\MyController($config['settings']); 
    } 
} 

Nhưng nó sẽ là như nhau hơn và hơn nữa. Vì vậy, câu hỏi của tôi là: Tôi có thể sử dụng một Nhà máy duy nhất cho nhiều bộ điều khiển không?

Trong module.config.php tôi tôi có thể xác định một lớp nhà máy duy nhất cho nhiều bộ điều khiển:

return array(
    'controllers' => array(
     'factories' => array(
      'MyModule\Controller\MyControllerA' => 'MyModule\Factory\ControllerFactory', 
      'MyModule\Controller\MyControllerB' => 'MyModule\Factory\ControllerFactory', 
      'MyModule\Controller\MyControllerC' => 'MyModule\Factory\ControllerFactory', 
     ) 
    ), 
); 

Nhưng trong nhà máy Tôi cần phải trả lại đối tượng điều khiển thực tế bằng tay (xem ví dụ ở trên) mà tất nhiên chỉ hoạt động với một Nhà máy trên mỗi Bộ điều khiển.

Hy vọng, tôi đã giải quyết vấn đề của mình rõ ràng.

CẬP NHẬT 2013/03/24:

Mặc dù đầu tiên tôi đi theo giải pháp gợi ý bằng cách tạo ra một khởi tạo, tôi không bao giờ thực sự thích sử dụng nó chỉ dành riêng cho việc tiêm cấu hình.

Vì vậy, tôi tiếp tục tìm hiểu và tạo ra một Plugin điều khiển để nhận cài đặt.

Mã cho plugin trông như thế này:

use Zend\Mvc\Controller\Plugin\AbstractPlugin; 

class Settings extends AbstractPlugin 
{ 
    protected $settings; 

    public function __invoke() 
    { 
     $config = $this->getController()->getServiceLocator()->get('Config'); 

     if (isset($config['settings']) && is_array($config['settings'])) { 
      $this->settings = $config['settings']; 
     } 

     return $this->settings; 
    } 
} 

Sau khi thêm plugin trong module.config.php với

'controller_plugins' => array(
    'invokables' => array(
     'settings' => 'My\Controller\Plugin\Settings', 
    ) 
), 

tôi có thể dễ dàng truy cập các thiết lập của tôi trong một bộ điều khiển bằng chỉ cần gọi số $this->settings(). Hy vọng điều này sẽ giúp bất cứ ai.

Trả lời

6

Bạn có thể thử gắn bộ khởi tạo, khi bộ điều khiển được tạo, thể hiện được kiểm tra với bộ khởi tạo đã biết. Nếu cá thể khớp với một giao diện hoặc lớp trừu tượng đã cho, thì bạn có thể áp dụng một số logic chung.

Tôi đã không thử nghiệm phương pháp này với bộ điều khiển nhưng cho rằng ControllerLoader là một loại ServiceManager/ServiceLocator nó nên trong lý thuyết làm việc.

'controllers' => array (
    'initializers' => array(
     'MyApplication\Controller\Initializer' 
    ) 
), 

Sau đó Initalizer sẽ giống như thế:

class Initializer implements InitializerInterface 
{ 
    public function initialize($instance, ServiceLocatorInterface $serviceLocator) 
    { 
     if (!$instance instanceof MyControllerInterface) 
     { 
      return; 
     } 

     // Do something for this instance 
    } 
} 
+0

Cám ơn ý tưởng của bạn. Trình tự khởi tạo hoạt động giống như bạn mô tả, tuy nhiên khi tôi thêm nó vào mảng 'bộ điều khiển', ánh xạ điều khiển bằng cách nào đó bị mất và tôi nhận được lỗi nói * "Bộ điều khiển được yêu cầu không thể ánh xạ tới lớp bộ điều khiển hiện có." dường như cả 'invokables' và 'initializers' trong 'controllers' đều cắn nhau. Bạn có đề nghị nào không? – Rob

+0

Tôi sẽ tua lại chỉ để invokables sau đó áp dụng initializer - sau đó gỡ lỗi nếu initializer là nhận được một ví dụ. Thông báo lỗi được đưa ra có thể do một số lý do, đảm bảo tất cả các định nghĩa sử dụng đều chính xác và không có lỗi. Để khai thác sâu hơn, tôi cũng sẽ xem xét \ Zend \ Mvc \ Service \ ControllerLoaderFactory.php và làm theo nó thông qua \ Zend \ Mvc \ Controller \ ControllerManager.php - Tôi hy vọng điều đó sẽ giúp ích cho bạn. – DrBeza

+0

Tìm ra nguyên nhân: Đó là cuộc gọi '$ serviceLocator-> get ('Config')' trong Initializer :: initialize() mà ném một * dịch vụ không tìm thấy ngoại lệ *. Vì vậy, có vẻ như cấu hình chưa sẵn sàng ở giai đoạn khởi tạo. Và tôi vẫn không thể có được các thiết lập của tôi vào bộ điều khiển :-(Sẽ thử một cách giải quyết ngay bây giờ – Rob

1

Không chắc cách bạn đã làm một bản cập nhật trong tương lai "UPDATE 2013/03/24";)

Tại sao bạn không chỉ sử dụng bộ điều khiển như bạn đề xuất nhưng đặt mã bạn muốn trong tất cả các bộ điều khiển vào một nhà máy trừu tượng mà sau đó bạn kế thừa, ví dụ:

abstract class AbstractControllerFactory implements FactoryInterface 
{ 
    protected function initialise(ServiceLocatorInterface $serviceLocator, $controller) { 
     $config = $serviceLocator->get('config'); 
     $controller->setConfig($config); 
    } 
} 

class ControllerFactory extends AbstractControllerFactory implements FactoryInterface 
{ 
    public function createService(ServiceLocatorInterface $serviceLocator) { 
     $controller = new \MyModule\Controller\MyController(); 
     $this->initialise($serviceLocator, $controller); 
     return $controller; 
    } 
} 
1

hoặc thậm chí sạch hơn: thêm bộ điều khiển của bạn như invokables để cấu hình, sau đó làm một cái gì đó như thế này mà biến điều khiển của bạn vào một lớp lót:

abstract class AbstractControllerFactory implements FactoryInterface 
{ 
    protected $controllerKey; 

    public function createService(ServiceLocatorInterface $serviceLocator) { 
     $config  = $serviceLocator->get('config'); 
     $controller = $serviceLocator->get($this->controllerKey); 
     $controller->setConfig($config); 
     return $controller; 
    } 
} 

class ControllerFactory extends AbstractControllerFactory implements FactoryInterface 
{ 
    protected $controllerKey = 'mymodule_controller_mycontroller'; 
} 
Các vấn đề liên quan