質問

In two words: I need to get access to the service manager (locator) from external class.

Details:

I have next structure in my ZF2 project:

project structure

Api.php is the class, I use in SOAP server, which is created in Controller:

class IncomingInterfaceController extends AbstractActionController
{

    ...

    public function indexAction()
    {
        if (isset($_GET['wsdl']))
            $this->handleWSDL();
        else
            $this->handleSOAP();

        return $this->getResponse();
    }

    private function handleWSDL()
    {
        $autodiscover = new AutoDiscover();
        $autodiscover->setClass('\Application\Api\Api')->setUri($this->getURI());
        $autodiscover->handle();
    }

In this Api.php class I need to get access to services.

I need something like this in my Api.php class:

public function OnNewDeal($uid)
{
     $error_log=$this->getServiceLocator()->get('error_log'); // this doesn't work!

     $error_log->write_error('error_text');
}
役に立ちましたか?

解決 2

In controller where you do $this->handleSOAP(); use setObject with already created instance instead setClass.

You should pass into Api __construct $this->getServiceLocator() and handle it there.

class IncomingInterfaceController extends AbstractActionController
{
    private function handleSOAP()
    {
        $soap = new Server(null, array('wsdl'=>$this->getWSDLURI()));
        $soapClass = new \Application\Api\Api($this->getServiceLocator());
        $soap->setObject($soapClass);

        $soap->handle();
    }

In Api class, handle serviceManager instance and use as you wish:

class Api
{
    protected $serviceManager;
    public function __construct($serviceManager)
    {
        $this->serviceManager = $serviceManager;
    }

    public function OnNewDeal($uid)
    {
        $this->serviceManager->get('error_log')->write_error('SOAP ERROR');
    }
....
}

他のヒント

In Module.php

public function getServiceConfig() {
    return array(
        'invokables' => array(
            'Application\Api\Api' => 'Application\Api\Api'           
        )
    );
}

In Api.php

class Api implements ServiceLocatorAwareInterface{

    protected $services;

    public function OnNewDeal($uid){
        $this->getServiceLocator()->get('error_log')->write_error('SOAP ERROR');
    }
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator){
        $this->services = $serviceLocator;
    }

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

In IncomingInterfaceController.php

class IncomingInterfaceController extends AbstractActionController{

    ...
    protected $api;

    public function indexAction()
    {
        if (isset($_GET['wsdl']))
            $this->handleWSDL();
        else
            $this->handleSOAP();

        return $this->getResponse();
    }

    private function handleWSDL()
    {
        $autodiscover = new AutoDiscover();
        $autodiscover->setClass('\Application\Api\Api')->setUri($this->getURI());
        $autodiscover->handle();
    }

    public getApi(){
        if(!$api){
            $this->api = $this->getServiceLocator()->get('Application\Api\Api');
        }
        return $this->api;
    }

Perhaps your API could implement ServiceLocatorAwareInterface like:

  class Api implements ServiceLocatorAwareInterface

and add

  class Api implements ServiceLocatorAwareInterface
  {
      protected $serviceManager;
  }

Then the service manager would be available

UPDATED

module.config.php example

      <?php
      return array(
            'service_manager' => array(
                'factories' => array(
                      'Api' => 'Namespace\Api'
             ),
                'shared' => array(
                       'Api' => false
                )
            ),
       )
       ?>

Injecting the Service Manager instance to an user defined "service locator aware class" should responsibility of the framework's itself (via initializers, invokables or user defined factories) not a specific controller's handleSOAP() method.

Yes, @SirJ's solution will work too but that's not a good practice. ZF2 provides ready-to-use Traits and Interfaces exactly for requirements like this. Just use them!

Your very own API class should seem like this:

<?php
namespace Application\Api;

use Zend\ServiceManager\ServiceLocatorInterface;

class Api implements ServiceLocatorInterface
{
    // Here is the trait. (php >= 5.4)
    use \Zend\ServiceManager\ServiceLocatorAwareTrait;

    public function OnNewDeal($uid)
    {
        $this->getServiceLocator()->get('error_log')->write_error('SOAP ERROR');
    }
}

And you should add this key to your module.config.php

<?php
return array(
    'service_manager' => array(
        'invokables' => array(
            'api-service' => 'Application\Api\Api',
        )
    );

Thats all! Now you can:

<?php
...
$soap = new Server(null, array('wsdl'=>$this->getWSDLURI()));
$soapClass = $this->getServiceLocator()->get('api-service');
$soap->setObject($soapClass);
...
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top