插件无法在控制器

时间:2016-07-05 02:11:24

标签: php zend-framework2

我正在使用骨架教程构建我的第一个Zend Framework 2应用程序。但每当我尝试从任何控制器调用任何插件时,我都会收到错误消息:

  

在插件管理器中找不到名为“ PLUGIN_NAME ”的插件   的Zend \的mvc \控制器\插件管理

不幸的是,我不知道代码的哪一部分可以帮助你。我发布了一些我认为可能很重要的文件。

配置/ modules.config

return [
    'Zend\Router',
    'Zend\Validator',
    'Zend\Form',
    'Album',
    'Application',
    'User',
];

模块/用户/ SRC / Module.php

<?php

namespace User;

use User\Model\User;
use User\Model\UserTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

class Module
{
    const VERSION = '1.0.0dev';

    public function getAutoloaderConfig()
    {
        return array(
            'Zend\Loader\ClassMapAutoloader' => array(
                __DIR__ . '/autoload_classmap.php',
            ),
            'Zend\Loader\StandardAutoloader' => array(
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                ),
            ),
        );
    }

    public function getConfig()
    {
        return include __DIR__ . '/../config/module.config.php';
    }

    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'User\Model\UserTable' =>  function($sm) {
                    $tableGateway = $sm->get('UserTableGateway');
                    $table = new UserTable($tableGateway);
                    return $table;
                },
                'UserTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new User());
                    return new TableGateway('user', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        );
    }
}

模块/用户/配置/ module.config.php

<?php

namespace User;

use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\Router\Http\Segment;

return [
    'controllers' => [
        'factories' => [
            Controller\UserController::class => InvokableFactory::class,
        ],
        'invokables' => [
            'User\Controller\User' => 'User\Controller\UserController',
        ],
    ],

    'router' => [
        'routes' => [
            'user' => [
                'type'    => Segment::class,
                'options' => [
                    'route'    => '/user[/:action[/:id]]',
                    'constraints' => [
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ],
                    'defaults' => [
                        'controller' => Controller\UserController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
        ],
    ],

    'view_manager' => [
        'template_path_stack' => [
            'user' => __DIR__ . '/../view',
        ],
    ],
];

我正试图通过控制器操作调用我的插件:

$this->flashMessanger()->...
$this->identity();
$this->getServiceLocator();

因为我真的需要服务定位器,所以我发现了一种解决方法,我认为这不太好,但对我有用:

$sm = $this->getEvent()->getApplication()->getServiceManager();

但我猜这里有些不对劲。

修改

为了更好地再现我所做的事情(我再次安装了Zend Framework,它仍然给我同样的错误):

  1. 本安装指南(https://framework.zend.com/manual/2.4/en/ref/installation.html)安装了Zend Framework(2.4我猜?)。我使用以下命令安装它:

    composer create-project -sdev --repository-url =“https://packages.zendframework.com”zendframework / skeleton-application

  2. 在安装时,当我被问到是否要安装最低安装时,我选择了“否”。接下来的每个问题我都回答“是”(安装程序要求安装很多模块,我安装了所有模块)。

  3. 安装程序询问我要在哪个配置中注入“ZendDeveloperTools”。我回答了2(config / development.config.php.dist)。对于其他所有人,我选择了1(config / modules.config.php)。
  4. 我通过在浏览器中调用url测试了骨架应用程序,它运行了。
  5. 我在这里从GitHub下载了相册模块(https://github.com/Hounddog/Album)。
  6. 我将相册模块复制到我的模块文件夹中。
  7. 我将条目'Album'添加到我的config / modules.config.php文件
  8. 我浏览了专辑页面
  9. 我收到错误:
  10.   

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

    我认为这个错误的原因是AlbumController中的getAlbumTable()方法

    public function getAlbumTable()
    {
        if (!$this->albumTable) {
            $sm = $this->getServiceLocator();
            $this->albumTable = $sm->get('Album\Model\AlbumTable');
        }
        return $this->albumTable;
    }
    

2 个答案:

答案 0 :(得分:1)

the ZF2 docs for controller plugins中,您可以看到您的控制器必须实施以下方法:setPluginManagergetPluginManagerplugin。你也可以阅读:

  

为方便起见,AbstractActionControllerAbstractActionController都有__call()个实现,允许您通过方法调用检索插件:

     

$plugin = $this->url();

您的控制器是否会延长AbstractActionControllerAbstractActionController
如果是的话,它应该像文档中提到的那样工作(所以你在问题中提到的那些方法应该有效)。 由于您没有共享任何控制器代码,因此很难说这是否是问题......

更新

您获得的错误与ControllerPluginManager的配置无关,但是您收到此错误的原因是:

$sm = $this->getServiceLocator();

由于方法getServiceLocator不存在,因此会执行魔术__call()方法,这会导致错误。

这是因为在ZF2的最新版本中,控制器类不再&#39;服务定位器识别&#39; 意味着您无法通过调用{{1}来检索ServiceManager }}

相反,您必须将$this->getServiceLocator()服务注入工厂内的控制器类:

1)向控制器类添加构造函数方法:

Album\Model\AlbumTable

2)为您的控制器创建工厂:

public function __construct(AlbumTable $albumTable){
    $this->albumTable = $albumTable;
}

3)<?php namespace Album\Controller\Factory; use Album\Controller\AlbumController; class AlbumControllerFactory implements FactoryInterface { /** * @param ServiceLocatorInterface $serviceLocator * @return AlbumController */ public function createService(ServiceLocatorInterface $serviceLocator) { $controllerPluginManager = $serviceLocator; $serviceManager = $controllerPluginManager->get('ServiceManager'); $albumTable = $serviceManager->get('Album\Model\AlbumTable'); return new AlbumController($albumTable); } }

中注册您的控制器工厂
module.config.php

答案 1 :(得分:0)

函数getAlbumTable()在ZF2教程中使用,但在ZF3中,它被成员table取代。

deleteAction()中的AlbumController.php功能更改为:

public function deleteAction()
{
    $id = (int) $this->params()->fromRoute('id', 0);
    if (!$id) {
        return $this->redirect()->toRoute('album');
    }

    $request = $this->getRequest();
    if ($request->isPost()) {
        $del = $request->getPost('del', 'No');

        if ($del == 'Yes') {
            $id = (int) $request->getPost('id');
            $this->table->deleteAlbum($id);
        }

        // Redirect to list of albums
        return $this->redirect()->toRoute('album');
    }

    return array(
        'id'    => $id,
        'album' => $this->table->getAlbum($id)
    );
}

请注意阅读$this->table->...而不是$this->getAlbumTable()->...

的两行