9

sto sviluppando un sistema ZF2 e funzionava molto bene, ma dopo che ho clonare il repository in un altro computer è apparso questo errore Deprecated:deprecato: Recupera locator servizio nel sistema funzionale - ZF2

Sei recupero del localizzatore di servizio dalla classe Module \ Controller \ Controller. Si tenga presente che ServiceLocatorAwareInterface è deprecato e verrà rimosso nella versione 3.0, insieme a ServiceLocatorAwareInitializer. Sarà necessario aggiornare la classe per accettare tutte le dipendenze alla creazione, tramite argomenti del costruttore o setter e utilizzare una fabbrica per eseguire le iniezioni. in /home/path/project/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php on line 258

Il 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" 

L'errore appare quando a recuperare il servizio nel mio controller (che si estende Zend \ Mvc \ controller \ AbstractActionController):

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

nel nucleo Zend a Zend \ Mvc \ controller \ AbstractController è come questo:

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; 
} 

Prima era solo questo:

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

Ho provato di tutto, qualcuno sa che cosa ho a che fare?

+0

È proprio lì nel messaggio: "Dovrai aggiornare la tua classe per accettare tutte le dipendenze alla creazione, sia via c argomenti o setter di onstructor e utilizzare una fabbrica per eseguire le iniezioni. –

+0

Non ho capito molto bene questo messaggio, "è necessario aggiornare la classe" ma quale classe? –

+0

Possibile duplicato di [PHP Deprecato: stai recuperando il localizzatore di servizio dalla classe ZFTool \ Controller \ ModuleController] (http://stackoverflow.com/questions/35933113/php-deprecated-you-are-retrieving-the-service -locator-from-the-class-zft) –

risposta

10

Non devi fare nulla, eppure. Quando si esegue l'aggiornamento a ZF3, sarà necessario modificare il modo in cui la classe di controller riceve le sue dipendenze.

ZF2 supporta due modelli di iniezione delle dipendenze: dal localizzatore di servizio e dal costruttore. ZF3 rimuove "per posizione di servizio" e richiede "per costruttore". Tutto ciò, in effetti, è il cambiamento su come si risolvono le dipendenze, spostando la risoluzione da "just in time" a "at construction".

Invece di essere in grado di ottenere un servizio da qualsiasi luogo , voi invece li ricevete a costruzione. Aggiornare il codice secondo le seguenti linee:

namespace Module\Controller; 

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

Usa $this->service dove serve nei metodi della classe.

Quindi utilizzare una fabbrica di controllo per creare il controller, in questo modo:

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

Il cambiamento è discusso in Issue 5168, e this blog post discute perché l'iniezione di servizio con un localizzatore di servizio è un anti-modello.

+0

Potete consigliare una soluzione per un controller in cui azioni diverse richiedono servizi diversi? Ad esempio, la mia indexAction richiede il servizio utente, viewAction richiede il servizio utente e il servizio del prodotto e my AboutUsAction potrebbe non richiedere alcun servizio. Il mio punto è, per un tale controller, non avrebbe senso istanziare e passare tutti i servizi nel costruttore per ogni richiesta. –

+3

@helloworld Hai ragione, l'iniezione di tutti quei servizi non avrebbe senso, e penso che sia esattamente il punto di questo cambiamento: costringere gli sviluppatori a contemplare il Principio di Responsabilità Unica come si applica ai controllori. Per me, sembra che tu abbia un controller "grasso" e la soluzione è creare controller separati per queste azioni. Se pubblichi un esempio specifico su [codereview SE] (codereview.stackexchange.com), puoi ottenere un feedback ancora più specifico. – bishop

+0

Grazie per il feedback. Lavorerò per far sì che i controller rispettino l'SRP. –

1

È possibile creare un controller plug servizio() (ma è una cattiva pratica, preferiscono FactoryInterface)

module.config.php

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

YourNamespace \ Mvc \ Controller \ 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 \ Controller \ 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

Come sarebbe con FactoryInterface? –

+0

Come 'ServiceFactory' ma con' $ controller = new YourController(); $ Controller-> SetService ($ container); ' –