简体   繁体   English

在php中创建一个before filter方法

[英]Create a before filter method in php

Just as a learning exercise I'm trying to build my own mini MVC in PHP. 就像学习练习一样,我正在尝试用PHP构建自己的迷你MVC。

What I want to achieve is a method that can be called before cetain other methods (similar to the before_filter method in ruby on rails) 我想要实现的是一个可以在cetain其他方法之前调用的方法(类似于rails上的ruby中的before_filter方法)

For example; 例如; given the below controller class a user must have permission to do certain activities, so say I wanted to call checkPermissions() from BaseController before the create() , update() and delete() . 鉴于以下控制器类,用户必须具有执行某些活动的权限,因此我想在create()update()delete()之前从BaseController调用checkPermissions() delete()

class HomeController extends BaseController {

    beforeFilter(checkPermissions,['create','update','delete']);

    function index(){}

    function create(){}

    function update(){}

    function delete(){}

}

Can anyone give me any guidance on how to achieve this? 任何人都可以给我任何指导如何实现这一目标? or enlighten me on the PHP way of doing this sort of task. 或者启发我做PHP这种任务的方式。 I'm relatively new to PHP so please be gentle. 我对PHP比较陌生,所以请保持温和。

You should make use of the magic method __call 你应该使用魔术方法__call

That magic method is called every time you call any function within your class. 每次调用类中的任何函数时,都会调用该魔术方法。

That way you should be able to do the following: 这样你应该能够做到以下几点:

class HomeController extends BaseController {

    public function __call($method, $arguments)
    {
        if (method_exists($this, $method))
        {
            if (in_array($method, ['create', 'update', 'delete']) && !$this->checkPermissions())
            {
                return null; // Permission is wrong, do something
            }

            return call_user_func_array([$this, $method], $arguments);
        }
    }

    protected function index() {}

    protected function create() {}

    protected function update() {}

    protected function delete() {}

}

Please note that this only works for private or protected methods, not public ones. 请注意,这仅适用于私有或受保护的方法,而不适用于公共方法。

If you want to use this on public methods, you should apply a decorator pattern like the following example: 如果要在公共方法上使用它,则应该应用以下示例中的装饰器模式:

class HomeController extends BaseController {

    public function index() {}

    public function create() {}

    public function update() {}

    public function delete() {}

}

class ControllerDecorator {

    private $controller;

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

    public function __call($method, $arguments)
    {
        if (method_exists($this->controller, $method))
        {
            if (in_array($method, ['create', 'update', 'delete']) && !$this->checkPermissions())
            {
                return null; // Permission is wrong, do something
            }

            return call_user_func_array([$this->controller, $method], $arguments);
        }
    }

    private function checkPermissions() {}
}

$homeController = new HomeController();
$decoratedHomeController = new ControllerDecorator($homeController);

$decoratedHomeController->update(); // Will check for permissions

I hope it helps :) 我希望它有帮助:)

There are several ways to accomplish this, here's one way to do it: 有几种方法可以实现这一点,这是一种方法:

Create a beforeFilter method in your controller: 在控制器中创建一个beforeFilter方法:

// In HomeController:
public function beforeFilter($action = 'index') {
    if (in_array($action, ['create', 'update', 'delete'])) {
        return checkPermissions(); // where checkPermissions() returns true/false
    }

    return true;
}

I assume you have some sort of dispatcher in your framework that knows that for a certain URI, it needs to call the create action of your HomeController . 我假设您的框架中有某种调度程序,它知道对于某个URI,它需要调用HomeControllercreate动作。 Before it calls that, you can call beforeFilter if it exists: 在调用之前,如果存在则可以调用beforeFilter

// In your dispatcher class:
public function dispatch($uri) {
    // determine which $controller and $action to call

    $mayProceed = true;
    if (method_exists($controller, 'beforeFilter')) {
        $mayProceed = $controller->beforeFilter($action);
    }

    // note: because we're checking if the method exists, your
    // controller doesn't *need* to have a beforeFilter method.
    // If it doesn't, $mayProceed will simply be true.

    if ($mayProceed) {
        $controller->$action();
    } else {
        throw new Exception("Dispatcher: beforeFilter told me you can't access this page");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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