dousong3760 2014-02-26 10:36
浏览 18
已采纳

Zend 2最佳实践 - 控制器外侧的服务定位器

Im new to Zend 2 and have this situation. Would like to know whats the best way to handle the situation.

Inside the Application module i have these classes

namespace Application\Foo;

class Base {
    protected $this->services; //service locator
    public function myFunc() {
        //needs service locator here
        $this->services;
    }
}

namespace Application\Foo;

class A extends Base {
    //can have some method that uses $this->services;
}

namespace Application\Foo;

class B extends Base {

}

As you can see i need the service locator inside my Base class. and then i want to use the A,B... extended classes in my controllers.

Thanks in advice


Update

According to jmleroux's suggestion i updated the code to look like this

namespace Application\Foo;

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

class Base implements ServiceLocatorAwareInterface {
    protected $this->services; //service locator

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

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


    public function myFunc() {
        //needs service locator here
        $this->services;
    }
}

module.conf.php

service_manager => array(
    'invokables' => array(
        'my_ser' => 'Application\Foo\Base'
    )
)

in my controller

$this->serviceLocator->get('my_ser'); 

returns the base class with service locator loaded

now my question is how to get my extended classes(A, B...) with the service locator loaded. since

$x = new \Application\Foo\A(); 

does not have the service locator loaded. do i have to add all my extended classes to module config as invokables? or is there a better alternative.

Thanks again.


Update 2

Thanks all (@jmleroux specially) for the support. Found these solutions and im adding them here thinking it will help some one else

NOTE: Just a general idea. namespaces and class names are not accurate

Solution 1 (recommended) - with ServiceLocatorAwareInterface / ServiceLocatorAwareTrait for php 5.4+

each class implements ServiceLocatorAwareInterface and add it to the service manager

namespace Application\Foor;

class A implements ServiceLocatorAwareInterface {
protected $services;

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

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

class B implements ServiceLocatorAwareInterface {
    use ServiceLocatorAwareTrait;
}

module.conf.php (or inside the Module getServiceConfig() function )

'service_manager' => array(
    'invokables' => array(
        'my_ser_a' => 'Application\Foo\A',
        'my_ser_b' => 'Application\Foo\B',
        ......
    )
)

call the service by name inside controllers


Solution 2 - with AbstractFactoryInterface

create a factory class

class MyFac implements AbstractFactoryInterface {
    public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
        if (class_exists($requestedName)){ \\eg. check Application\Foo\A exists
            return true;
        }

        return false;
    }

    public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
        $class = new $requestedName;   \\eg. creates an instance of Application\Foo\A
        $class->setServiceLocator($locator); \\make sure your class has this method 
        return new $class;
    }
}

module.conf.php (or inside the Module getServiceConfig() function )

'service_manager' => array(
    'abstract_factories' => array(
        'Application\Foo\MyFac'
    )
)

in controllers call

$this->getServiceLocator()->get('Application\Foo\A');

Thanks.

展开全部

  • 写回答

1条回答 默认 最新

  • douketangyouzh5219 2014-02-26 10:58
    关注

    In order to access the service locator, your base class need to be declared as an invokable service implementing ServiceLocatorAwareInterface.php

    If you are on PHP 5.4+, you can use ServiceLocatorAwareTrait.php

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部