9

ich ein ZF2 System bin zu entwickeln und es funktioniert sehr gut, aber nachdem ich das Repository in anderen Computern klonen haben diese veralteten Fehler aufgetreten:Veralten: Abrufen von Service-Locator in funktionsfähigen System - ZF2

Sie sind Abrufen des Service-Locators aus der Klasse Module \ Controller \ Controller. Bitte beachten Sie, dass ServiceLocatorAwareInterface veraltet ist und in Version 3.0 zusammen mit dem ServiceLocatorAwareInitializer entfernt wird. Sie müssen Ihre Klasse aktualisieren, um alle Abhängigkeiten bei der Erstellung entweder über Konstruktorargumente oder Setter zu akzeptieren, und eine Factory zum Ausführen der Injektionen verwenden. in /home/path/project/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php on line 258

Die composer.json:

"require": { 
    "php": ">=5.5", 
    "ext-curl": "*", 
    "ext-json": "*", 
    "ext-mbstring": "*", 
    "zendframework/zendframework": "~2.5", 
    "doctrine/doctrine-orm-module": "0.*", 
    "hounddog/doctrine-data-fixture-module": "0.0.*", 
    "imagine/Imagine": "~0.5.0" 

Der Fehler erscheint, wenn ich abrufen der Dienst in meinem Controller (Erweiterung Zend \ Mvc \ Regler \ AbstractActionController):

$this->getServiceLocator()->get("Module\Service\Service"); 

im Zend Kern bei Zend \ Mvc \ Regler \ AbstractController ist wie folgt:

012.
public function getServiceLocator() 
{ 
    trigger_error(sprintf(
     'You are retrieving the service locator from within the class %s. Please be aware that ' 
     . 'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along ' 
     . 'with the ServiceLocatorAwareInitializer. You will need to update your class to accept ' 
     . 'all dependencies at creation, either via constructor arguments or setters, and use ' 
     . 'a factory to perform the injections.', 
     get_class($this) 
    ), E_USER_DEPRECATED); 

    return $this->serviceLocator; 
} 

Vor war nur das:

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

ich alles versucht habe, jemand weiß, was ich zu tun habe?

+0

Es ist genau dort in der Nachricht: 'Sie müssen Ihre Klasse aktualisieren, um alle Abhängigkeiten bei der Erstellung zu akzeptieren, entweder über c Sie können auch eine Fabrik verwenden, um die Injektionen durchzuführen. " –

+0

Ich habe diese Nachricht nicht gut verstanden," muss Ihre Klasse aktualisieren ", aber welche Klasse? –

+0

Mögliches Duplikat von [PHP Veraltet: Sie rufen den Service Locator aus der Klasse ZFTool \ Controller \ ModuleController ab (http://stackoverflow.com/questions/35933113/php-deprecated-you-are-retrieving-the-service -locator-from-in-the-class-zft) –

Antwort

10

Sie müssen nichts tun, noch. Wenn Sie auf ZF3 aktualisieren, müssen Sie ändern, wie die Controller-Klasse ihre Abhängigkeiten empfängt.

ZF2 unterstützt zwei Abhängigkeitsinjektionsmuster: nach Service Locator und nach Konstruktor. ZF3 entfernt "nach Dienstort" und benötigt "nach Konstruktor". All dies bewirkt effektiv, dass Abhängigkeiten aufgelöst werden und die Auflösung von "just in time" auf "at construction" verschoben wird.

Statt der Lage zu sein, einen Dienst von überall zu bekommen, erhalten Sie statt sie bei Bau. Aktualisieren Sie Ihren Code entlang der folgenden Zeilen:

namespace Module\Controller; 

class Controller { 
    public function __construct(\Module\Service\Service $service) { 
     $this->service = $service; 
    } 
} 

Verwenden $this->service, wo Sie es in der Klasse Methoden benötigen.

dann einen Controller Factory verwenden, um Ihre Controller zu erstellen, etwa so:

function ($controllers) { 
    $services = $controllers->getServiceLocator(); 
    return new \Module\Controller\Controller($services->get('Module\Service\Service')); 
} 

Die Veränderung der Issue 5168 diskutiert wird, und this blog post diskutiert, warum Service Injektion mit einem Service-Locator ein Anti-Muster ist.

+0

Können Sie eine Lösung für einen Controller empfehlen, bei der verschiedene Aktionen unterschiedliche Dienste erfordern? Zum Beispiel erfordert meine indexAction den Benutzerdienst, viewAction erfordert den Benutzerservice und den Produktdienst, und my aboutUsAction benötigt möglicherweise überhaupt keine Dienste. Mein Punkt ist, dass es für einen solchen Controller nicht sinnvoll wäre, alle Services im Konstruktor für jede Anfrage instanziieren und übergeben zu müssen. –

+3

@helloworld Sie haben Recht, wenn Sie all diese Dienste einspeisen würden, würde das keinen Sinn ergeben, und ich denke, genau das ist der Sinn dieser Änderung: Entwickler dazu zu drängen, das Prinzip der einheitlichen Verantwortlichkeit zu berücksichtigen. Für mich klingt es so, als hätten Sie einen "fetten" Controller, und die Lösung besteht darin, separate Controller für diese Aktionen zu erstellen. Wenn Sie ein bestimmtes Beispiel an [codereview SE] (codereview.stackexchange.com) senden, können Sie noch spezifischeres Feedback erhalten. – bishop

+0

Vielen Dank für das Feedback. Ich werde daran arbeiten, Controller dazu zu bringen, SRP einzuhalten. –

1

Sie einen Controller Service-Plugin erstellen() (aber es ist eine schlechte Praxis, bevorzugen FactoryInterface)

module.config.php

'controller_plugins' => [ 
    'factories' => [ 
     'service' => YourNamespace\Mvc\Controller\Plugin\Service\ServiceFactory::class, 
    ], 
], 

YourNamespace \ Mvc \ Controllers \ Plugin \ Service \ ServiceFactory.php

<?php 

namespace YourNamespace\Mvc\Controller\Plugin\Service; 

use Interop\Container\ContainerInterface; 
use YourNamespace\Mvc\Controller\Plugin\Service; 
use Zend\ServiceManager\Factory\FactoryInterface; 

class ServiceFactory implements FactoryInterface 
{ 
    /** 
    * @param ContainerInterface $container 
    * @param string $requestedName 
    * @param array $options 
    * @return Service 
    */ 
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null) 
    { 
     $plugin = new Service(); 
     $plugin->setServiceLocator($container); 
     return $plugin; 
    } 
} 

YourNamespace \ Mvc \ Controllers \ Plugin \ service.php

<?php 

namespace YourNamespace\Mvc\Controller\Plugin; 

use Interop\Container\ContainerInterface; 
use Zend\Mvc\Controller\Plugin\AbstractPlugin; 

/** 
* Plugin: $this->service(); 
*/ 
class Service extends AbstractPlugin 
{ 
    /** 
    * @var ContainerInterface 
    */ 
    protected $serviceLocator; 

    /** 
    * @return ContainerInterface 
    */ 
    public function getServiceLocator() 
    { 
     return $this->serviceLocator; 
    } 

    /** 
    * @param ContainerInterface $serviceLocator 
    * @return Service 
    */ 
    public function setServiceLocator(ContainerInterface $serviceLocator) 
    { 
     $this->serviceLocator = $serviceLocator; 
     return $this; 
    } 

    /** 
    * @param string $name 
    * @return object|bool 
    */ 
    public function __invoke($name = null) 
    { 
     $sl = $this->getServiceLocator(); 
     if (!$name) { 
      return $sl; 
     } 
     if (!$sl->has($name)) { 
      return false; 
     } 
     return $sl->get($name); 
    } 
} 
+0

Wie wäre es mit FactoryInterface? –

+0

Wie 'ServiceFactory' aber mit' $ controller = new YourController(); $ controller-> setService ($ container); ' –

Verwandte Themen