Zend 框架 - 在控制器中获取配置

spa*_*mix 1 php zend-framework zend-framework3

我正在使用它来构建 zend 应用程序。http://github.com/zendframework/ZendSkeletonApplication

我正在尝试获取我放在里面config/autoload/global.phpconfig/local.php.dist底线的配置数据,但它返回

Zend\ServiceManager\Exception\ServiceNotFoundException

并且

在插件管理器 Zend\Mvc\Controller\PluginManager 中找不到名为“getServiceLocator”的插件

知道如何获得配置吗?

$config = $this->getServiceLocator()->get('config');
Run Code Online (Sandbox Code Playgroud)

小智 5

ZendSkeletonApplication的 Master 分支目前使用 Zend Framework 3。getServiceLocator()在Zend Framework 3中已经删除了控制器 所以,如果你想从服务传递一些变量到控制器,你应该创建一个工厂。并在工厂实例化控制器时传递变量。

例子:

您的控制器名称IndexController来自ApplicationModule。而工厂类是IndexControllerFactory.

应用程序\控制器\索引控制器工厂

<?php
namespace Application\Controller;

use Zend\ServiceManager\Factory\FactoryInterface;
use Interop\Container\ContainerInterface;

class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $config = $container->get("Config");
        return new IndexController($config);
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序\控制器\索引控制器

<?php
namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    private $config;

    public function __construct(array $config)
    {
        $this->config = $config;
    }

    public function indexAction()
    {
        // use $this->config here
    }
}
Run Code Online (Sandbox Code Playgroud)

和这里的配置 module.config.php

'controllers' => [
        'factories' => [
            Controller\IndexController::class => Controller\IndexControllerFactory::class
        ],
    ],
Run Code Online (Sandbox Code Playgroud)

希望这有帮助


unc*_*exo 5

这是为了澄清

ZF3 中,如果您要在应用程序中创建任何需要的类,请使它们可用,并通过ServiceManager使它们在您的应用程序中可用。ServiceManager实现了一个存储注册服务的容器。那怎么样?ZF 使用一种称为工厂的方法(简而言之,它创建对象)。它有助于将服务存储到容器中。然后我们可以使用ServiceManager从该容器中提取服务。让我们看看如何?

ServiceManager本身就是一个服务。

因此,使用工厂让我们在控制器(例如,IndexController)中提供ServiceManager实例。这样我们就可以使用它获得任何服务。

应用程序\控制器\索引控制器工厂

<?php
namespace Application\Controller;

// This is the container 
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = NULL)
    {   
        $serviceManager = $container->get('ServiceManager');
        return new IndexController($serviceManager);
    }    
}
Run Code Online (Sandbox Code Playgroud)

让我们注册IndexControllerFactory的一个工厂的IndexController这样我们就可以使用它。在module.config.php 中进行以下更改

'controllers' => [
    'factories' => [
        Controller\IndexController::class => Controller\IndexControllerFactory::class,
    ],
],
Run Code Online (Sandbox Code Playgroud)

一旦IndexControllerIndexControllerFactory实例化(通过上述配置),ServiceManager实例就可以通过 IndexController 的构造函数使用。

<?php
namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\ServiceManager\ServiceManager;

class IndexController extends AbstractActionController
{
    protected $serviceManager;

    public function __construct(ServiceManager $serviceManager) 
    {
        // Here we set the service manager instance 
        $this->serviceManager = $serviceManager;
    }

    public function indexAction()
    {
        // Use this as you want
        $config = $this->serviceManager->get('config');

        return new ViewModel();
    }
Run Code Online (Sandbox Code Playgroud)

如果我们需要来自另一个类中的配置服务而不是控制器的东西怎么办?例如,我们要将图像上传到特定目的地。那么我们如何修复上传路径呢?请参阅以下示例。

我们将通过RenameUpload过滤器上传图片。它有一个名为target的选项,用于指定上传路径的目的地。让我们为上传过滤器创建另一个工厂

Application\Controller\Form\Filter\UploadFilterFactory

<?php
namespace Application\Form\Filter;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Form\Filter\UploadFilter;

class UploadFilterFactory implements FactoryInterface
{

    public function __invoke(ContainerInterface $container, $requestedName, array $options = NULL)
    { 
        $config = $container->get('config');

        // Look! here we fix the upload path
        $uploadPath = $config['module_config']['upload_path'];

        // Here we're injecting that path
        return new UploadFilter($uploadPath);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要,请对UploadForm执行相同操作。这将是UploadFormFactory

将以下两个片段放在module.config.php 中。这是针对UploadFilterFactory 的

'service_manager' => [
    'factories' => [
        // UploadForm::class => UploadFormFactory::class, 
        UploadFilter::class => UploadFilterFactory::class,
    ],

    // Make an alias so that we can use it where we need
    // it could be uploadAction() inside any controller
    // $inputForm = $this->serviceManager->get('UploadForm');
    // $inputFilter = $this->serviceManager->get('UploadFilter');
    // $uploadForm->setInputFilter($inputFilter), for example
    'aliases' => [
        // 'UploadForm' => UploadForm::class,
        'UploadFilter' => UploadFilter::class,
    ],
],
Run Code Online (Sandbox Code Playgroud)

这个是你想上传的上传路径

'module_config' => [
    // Set the path as you want
    'upload_path' => __DIR__ . '/../data/upload',
],
Run Code Online (Sandbox Code Playgroud)

这是Application\Form\Filter\UploadFilter

<?php
namespace Application\Form\Filter;

use Zend\InputFilter\InputFilter;
use Zend\Filter\File\RenameUpload;

class UploadFilter extends InputFilter
{
    protected $uploadPath;

    public function __construct(string $uploadPath)
    { 
        // We're assigning here so that we can use it
        // on the filter section.
        $this->uploadPath = $uploadPath;

        $this->prepareFilters();
    }

    public function prepareFilters()
    { 
        $this->add(array(
            'name' => 'image',
            'required' => true,
            'filters' => array(
                array(
                    'name' => RenameUpload::class,
                    'options' => array(
                        // Thus here we use it
                        'target' => $this->uploadPath,
                        'overwrite' => true,
                        'randomize' => true,
                        'use_upload_extension' => true,
                    ),        
                ),
            ),
            'validators' => array(),
        ));
    }
}
Run Code Online (Sandbox Code Playgroud)

这是使事情变得可服务的一种方式。那么为什么是ServiceManager呢?这是为了停止分散的对象使用。它删除了隐藏的依赖项。这使代码干净且易于理解。原则是好的设计