插件在控制器中不起作用
Plugins not working in controller
我正在使用框架教程构建我的第一个 Zend Framework 2 应用程序。但是每当我尝试从任何控制器调用任何插件时,我都会收到错误消息:
A plugin by the name "PLUGIN_NAME" was not found in the plugin manager
Zend\Mvc\Controller\PluginManager
不幸的是,我不知道代码的哪一部分可以帮助你帮助我。我 post 一些我认为可能很重要的文件。
config/modules.config
return [
'Zend\Router',
'Zend\Validator',
'Zend\Form',
'Album',
'Application',
'User',
];
module/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/User/config/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,它仍然给我同样的错误):
通过此安装指南 (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
在安装上,当我被问到是否要安装最小安装时,我选择了"No"。我用 "Yes" 回答了下一个问题(安装程序要求安装很多模块,我都安装了它们)。
- 安装程序询问我要在哪个配置中注入 "ZendDeveloperTools"。我回答了 2 (config/development.config.php.dist)。对于所有其他人,我选择了 1 (config/modules.config.php).
- 我通过在浏览器中调用 url 测试了骨架应用程序,它有效。
- 我从 GitHub 此处 (https://github.com/Hounddog/Album) 下载了相册模块。
- 我将相册模块复制到我的模块文件夹中。
- 我将条目 'Album' 添加到我的 config/modules。config.php 文件
- 我浏览到相册页面
- 我遇到错误:
A plugin by the name "getServiceLocator" was not found in the plugin
manager 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;
}
在 the ZF2 docs for controller plugins 中,您可以了解到您的控制器必须实现以下方法:setPluginManager
、getPluginManager
和 plugin
。您还可以阅读:
For an extra layer of convenience, both AbstractActionController
and AbstractActionController
have __call()
implementations that allow you to retrieve plugins via method calls:
$plugin = $this->url();
您的控制器是否扩展 AbstractActionController
或 AbstractActionController
?
如果是,它应该像文档中提到的那样工作(所以你在问题中提到的那些方法应该工作)。
由于您没有共享任何控制器代码,所以很难说这是否是问题所在...
更新
您收到的错误与您的 ControllerPluginManager
的配置无关,但您收到此错误是因为您正在执行以下操作:
$sm = $this->getServiceLocator();
由于方法 getServiceLocator
不存在,因此执行了神奇的 __call()
方法,这导致了错误。
这是因为在最新版本的 ZF2 中,控制器 class 不再是 'service locator aware',这意味着您无法检索 ServiceManager
通过调用 $this->getServiceLocator()
.
相反,您必须将 Album\Model\AlbumTable
服务注入工厂内的控制器 class:
1) 添加一个构造器方法到你的控制器 class:
public function __construct(AlbumTable $albumTable){
$this->albumTable = $albumTable;
}
2) 为您的控制器创建工厂:
<?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);
}
}
3) 在 module.config.php
:
中注册你的控制器工厂
'factories' => [
`Album\Controller\AlbumController` => `Album\Controller\Factory\AlbumControllerFactory`,
],
函数getAlbumTable()
在ZF2教程中使用,但在ZF3中被成员table
取代。
将AlbumController.php
中的deleteAction()
函数改为:
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()->...
我正在使用框架教程构建我的第一个 Zend Framework 2 应用程序。但是每当我尝试从任何控制器调用任何插件时,我都会收到错误消息:
A plugin by the name "PLUGIN_NAME" was not found in the plugin manager Zend\Mvc\Controller\PluginManager
不幸的是,我不知道代码的哪一部分可以帮助你帮助我。我 post 一些我认为可能很重要的文件。
config/modules.config
return [
'Zend\Router',
'Zend\Validator',
'Zend\Form',
'Album',
'Application',
'User',
];
module/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/User/config/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,它仍然给我同样的错误):
通过此安装指南 (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
在安装上,当我被问到是否要安装最小安装时,我选择了"No"。我用 "Yes" 回答了下一个问题(安装程序要求安装很多模块,我都安装了它们)。
- 安装程序询问我要在哪个配置中注入 "ZendDeveloperTools"。我回答了 2 (config/development.config.php.dist)。对于所有其他人,我选择了 1 (config/modules.config.php).
- 我通过在浏览器中调用 url 测试了骨架应用程序,它有效。
- 我从 GitHub 此处 (https://github.com/Hounddog/Album) 下载了相册模块。
- 我将相册模块复制到我的模块文件夹中。
- 我将条目 'Album' 添加到我的 config/modules。config.php 文件
- 我浏览到相册页面
- 我遇到错误:
A plugin by the name "getServiceLocator" was not found in the plugin manager 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;
}
在 the ZF2 docs for controller plugins 中,您可以了解到您的控制器必须实现以下方法:setPluginManager
、getPluginManager
和 plugin
。您还可以阅读:
For an extra layer of convenience, both
AbstractActionController
andAbstractActionController
have__call()
implementations that allow you to retrieve plugins via method calls:
$plugin = $this->url();
您的控制器是否扩展 AbstractActionController
或 AbstractActionController
?
如果是,它应该像文档中提到的那样工作(所以你在问题中提到的那些方法应该工作)。
由于您没有共享任何控制器代码,所以很难说这是否是问题所在...
更新
您收到的错误与您的 ControllerPluginManager
的配置无关,但您收到此错误是因为您正在执行以下操作:
$sm = $this->getServiceLocator();
由于方法 getServiceLocator
不存在,因此执行了神奇的 __call()
方法,这导致了错误。
这是因为在最新版本的 ZF2 中,控制器 class 不再是 'service locator aware',这意味着您无法检索 ServiceManager
通过调用 $this->getServiceLocator()
.
相反,您必须将 Album\Model\AlbumTable
服务注入工厂内的控制器 class:
1) 添加一个构造器方法到你的控制器 class:
public function __construct(AlbumTable $albumTable){
$this->albumTable = $albumTable;
}
2) 为您的控制器创建工厂:
<?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);
}
}
3) 在 module.config.php
:
'factories' => [
`Album\Controller\AlbumController` => `Album\Controller\Factory\AlbumControllerFactory`,
],
函数getAlbumTable()
在ZF2教程中使用,但在ZF3中被成员table
取代。
将AlbumController.php
中的deleteAction()
函数改为:
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()->...