[英]Routing issues with subcontroller structure in Phalcon
I've implemented a router
, securityplugin (for ACL)
and notfoundplugin
. 我已经实现了一个
router
, securityplugin (for ACL)
和notfoundplugin
。
I want my site to be set up with a subcontroller structure: Link 我希望使用子控制器结构来设置我的网站: 链接
The website is set up in the following main parts: 该网站分为以下主要部分:
The issues I have: 我遇到的问题:
When calling: domain/admin/actionofadmin
致电时:domain / admin / actionofadmin
Returns custom 404: "Page doesn't exist" instead of the normal action result
返回自定义404:“页面不存在”,而不是常规操作结果
When calling: domain/admin/actionofadmin.
调用时:domain / admin / actionofadmin。 (<-- mind the dot at the end)
(<-注意结尾处的点)
Returns index action of index controller instead of the normal action result
返回索引控制器的索引操作,而不是正常操作结果
Why does the router return theses results? 路由器为什么返回这些结果? How can they be fixed?
如何解决?
Extra questions: 额外问题:
How does Phalcon know where to find a view and link it to the correct controller? Phalcon如何知道在哪里可以找到视图并将其链接到正确的控制器? Example: A dashboardController resides in a folder "admin" inside the folder "controllers".
示例:dashboardController驻留在文件夹“ controllers”内的文件夹“ admin”中。
How does Phalcon know that in the SecurityPlugin ACL it needs to search for the correct controller while it doesn't get a namespace? Phalcon如何知道在SecurityPlugin ACL中它需要在没有名称空间的情况下搜索正确的控制器? Example: When I want to allow controller Tickets of namespace app\\controllers\\admin to be only viewed by admin users.
示例:当我要允许命名空间app \\ controllers \\ admin的控制器票证仅由admin用户查看时。
Extra information: 额外的信息:
Let me know if you need any more information / files or if I should post it somewhere else for ease of reading. 让我知道您是否需要更多信息/文件,或者是否应该将其张贴在其他地方以便于阅读。
Files: 档案:
/app/controllers/AdminController.php /app/controllers/AdminController.php
<?php
namespace Ontrack\Controllers;
class AdminController extends ControllerBase
{
public function indexAction(){
}
public function testAction(){
echo "test";
}
}
/app/config/services.php Excerpt /app/config/services.php 摘录
//This makes sure the routes are correctly handled for authorized/unauthorized
/**
* MVC dispatcher
*/
$di->set("dispatcher", function () use ($di) {
// Create an events manager
$eventsManager = $di->getShared('eventsManager');
/**
*Check if the user is allowed to access certain action using the SecurityPlugin
*Listen for events produced in the dispatcher using the Security plugin
*/
$eventsManager->attach("dispatch:beforeDispatch", new SecurityPlugin());
// Handle exceptions and not-found exceptions using NotFoundPlugin
$eventsManager->attach("dispatch:beforeException", new NotFoundPlugin());
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Ontrack\Controllers');
// Assign the events manager to the dispatcher
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
}
);
/app/config/loader.php /app/config/loader.php
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
[
$config->application->controllersDir,
$config->application->modelsDir,
$config->application->pluginsDir
]
)->register();
$loader->registerNamespaces(
[
'Ontrack\Controllers' => APP_PATH . '/controllers/',
'Ontrack\Controllers\Admin' => APP_PATH . '/controllers/admin',
'Ontrack\Models' => APP_PATH . '/models/'
]
)->register();
/app/config/routes.php /app/config/routes.php
<?php
$router = new Phalcon\Mvc\Router(false);
$router->setDefaults(
[
"controller" => "index",
"action" => "index",
]
);
$router->add('/:controller/:action/:params', [
'namespace' => 'Ontrack\Controllers',
'controller' => 1,
'action' => 2,
'params' => 3,
]);
$router->add('/:controller/:action', [
'namespace' => 'Ontrack\Controllers',
'controller' => 1,
'action' => 2,
]);
$router->add('/:controller', [
'namespace' => 'Ontrack\Controllers',
'controller' => 1,
]);
$router->add('/admin/:controller/:action/:params', [
'namespace' => 'Ontrack\Controllers\Admin',
'controller' => 1,
'action' => 2,
'params' => 3,
]);
$router->add('/admin/:controller/:action', [
'namespace' => 'Ontrack\Controllers\Admin',
'controller' => 1,
'action' => 2,
]);
$router->add('/admin/:controller', [
'namespace' => 'Ontrack\Controllers\Admin',
'controller' => 1,
]);
$router->removeExtraSlashes(true);
return $router;
/app/plugins/SecurityPlugin.php /app/plugins/SecurityPlugin.php
<?php
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Adapter\Memory as AclList;
use Phalcon\Acl\Resource;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
class SecurityPlugin extends Plugin
{
/**
* Returns an existing or new access control list
*
* @returns AclList
*/
public function getAcl()
{
if (!isset($this->persistent->acl)) {
$acl = new AclList();
$acl->setDefaultAction(Acl::DENY);
// Register roles
$roles = [
'admins' => new Role(
'admins',
'Website administrators'
),
'users' => new Role(
'users',
'Member privileges, granted after sign in.'
),
'guests' => new Role(
'guests',
'Anyone browsing the site who is not signed in is considered to be a "Guest".'
)
];
foreach ($roles as $role) {
$acl->addRole($role);
}
//Private area resources
$privateResources = array(
'account' => array('*')
);
$privateResourcesAdmin = array(
'admin' => array('*'),
'tickets' => array('*')
);
//Public area resources
$publicResources = array(
'index' => array('*'),
'register' => array('*'),
'errors' => array('show401', 'show404', 'show500'),
'register' => array('*'),
'login' => array('*'),
'logout' => array('*')
);
foreach ($privateResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
foreach ($privateResourcesAdmin as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
foreach ($publicResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
//Grant access to public areas to users, admins and guests
foreach ($roles as $role) {
foreach ($publicResources as $resource => $actions) {
foreach ($actions as $action){
$acl->allow($role->getName(), $resource, $action);
}
}
}
//Grant access to private area to role Users
foreach ($privateResources as $resource => $actions) {
foreach ($actions as $action){
$acl->allow('users', $resource, $action);
}
}
foreach ($privateResourcesAdmin as $resource => $actions) {
foreach ($actions as $action){
$acl->allow('admins', $resource, $action);
}
}
//The acl is stored in session, APC would be useful here too
$this->persistent->acl = $acl;
}
return $this->persistent->acl;
}
/**
* This action is executed before execute any action in the application
*
* @param Event $event
* @param Dispatcher $dispatcher
* @return bool
*/
public function beforeDispatch(Event $event, Dispatcher $dispatcher){
$auth = $this->session->has('auth');
if (!$auth){
$role = 'guests';
} else {
$authSession = $this->session->get("auth");
if($authSession['account_type'] == 99){
$role = 'admins';
} else {
$role = 'users';
}
}
$controller = $dispatcher->getControllerName();
$action = $dispatcher->getActionName();
$acl = $this->getAcl();
if (!$acl->isResource($controller)) {
$dispatcher->forward([
'controller' => 'errors',
'action' => 'show404'
]);
return false;
}
$allowed = $acl->isAllowed($role, $controller, $action);
if (!$allowed) {
if($controller === 'admin'){
$dispatcher->forward(array(
'controller' => 'errors',
'action' => 'show404'
));
} else {
$dispatcher->forward(array(
'controller' => 'errors',
'action' => 'show401'
));
}
return false;
}
}
}
/app/plugins/NotFoundPlugin.php /app/plugins/NotFoundPlugin.php
<?php
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Dispatcher;
use Phalcon\Mvc\Dispatcher\Exception as DispatcherException;
use Phalcon\Mvc\Dispatcher as MvcDispatcher;
/**
* NotFoundPlugin
*
* Handles not-found controller/actions
*/
class NotFoundPlugin extends Plugin
{
/**
* This action is executed before execute any action in the application
*
* @param Event $event
* @param MvcDispatcher $dispatcher
* @param Exception $exception
* @return boolean
*/
public function beforeException(Event $event, MvcDispatcher $dispatcher, Exception $exception)
{
error_log($exception->getMessage() . PHP_EOL . $exception->getTraceAsString());
if ($exception instanceof DispatcherException) {
switch ($exception->getCode()) {
case Dispatcher::EXCEPTION_HANDLER_NOT_FOUND:
case Dispatcher::EXCEPTION_ACTION_NOT_FOUND:
$dispatcher->forward(array(
'controller' => 'errors',
'action' => 'show404'
));
return false;
}
}
$dispatcher->forward(array(
'controller' => 'errors',
'action' => 'show500'
));
return false;
}
}
When calling: domain/admin/actionofadmin
(as i understand domain is for example www.google.pl
) phalcon is expecting ActionofadminController
according to your routes. 致电时:
domain/admin/actionofadmin
(据我所知,域是例如www.google.pl
),Phalcon希望根据您的路线选择ActionofadminController
。 Are you sure there is such controller? 您确定有这样的控制器吗? Don't sure why with with dot it's hitting index controller and index action though.
不确定为什么使用dot会打中索引控制器和索引动作。
How does Phalcon know where to find a view and link it to the correct controller? Example: A dashboardController resides in a folder "admin" inside the folder "controllers".
It's getting this info from dispatcher. 它是从调度程序获取此信息的。 Mvc application if you don't render view your self is implicit automatically rendering.
Mvc应用程序如果不渲染视图,您的自身就是隐式的自动渲染。 Check this source: https://github.com/phalcon/cphalcon/blob/master/phalcon/mvc/application.zep#L348 And other view classes.
检查此源: https : //github.com/phalcon/cphalcon/blob/master/phalcon/mvc/application.zep#L348和其他视图类。
About Acl Plugin - it doesn't check for namespace at all. 关于Acl插件-它根本不检查名称空间。 So if you have two controllers with same name but other namespace this wil cause obviously a problem.
因此,如果您有两个名称相同但名称空间不同的控制器,则显然会引起问题。 You just need to change security plugin to your needs.
您只需要更改安全性插件即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.