简体   繁体   English

Phalcon中子控制器结构的路由问题

[英]Routing issues with subcontroller structure in Phalcon

I've implemented a router , securityplugin (for ACL) and notfoundplugin . 我已经实现了一个routersecurityplugin (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: 该网站分为以下主要部分:

  • Index 指数
  • Admin 管理员
    • Tickets 门票
  • Account 帐户

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: 额外的信息:

  • Phalcon 3.0.3 菲尔康3.0.3
  • PHP 5.6 PHP 5.6

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM