Php 前端控制器将参数链接到应用程序逻辑的最佳方式?

Php 前端控制器将参数链接到应用程序逻辑的最佳方式?,php,front-controller,Php,Front Controller,我正在使用Front Controller设计模式构建一个应用程序,其中只有一个页面index.php,所有用户请求都作为参数传递(与常规设计中的不同页面/控制器相比) 如何将这些参数连接到应用程序逻辑 e、 g.我有两种不同的行为: index.php?action=userLogin&username=admin&password=qwerty //process user login index.php?action=displayUsersTable //show re

我正在使用Front Controller设计模式构建一个应用程序,其中只有一个页面
index.php
,所有用户请求都作为参数传递(与常规设计中的不同页面/控制器相比)

如何将这些参数连接到应用程序逻辑

e、 g.我有两种不同的行为:

index.php?action=userLogin&username=admin&password=qwerty //process user login

index.php?action=displayUsersTable //show registered users
目前,我有一个
数组
,包含系统接受的所有操作(以及预期参数),我将
操作
参数从URL比较到此数组的
,然后检查此操作所需的参数

//1 = optional, 2=required
$systemActions = [
      "userLogin" => [
            "login" => 2,
            "password" => 2
                     ],
      "displayUsersTable" => []
                 ];
显然,随着系统的发展,这将成为一个怪物阵列

是否有更好的方法将发送到前端控制器的参数绑定到系统操作?

由于代码是“固定的”(即不是从数据库驱动的),因此无需注入阵列(以及它所需的所有处理/内存开销)。因此,是的,它可以得到改进

但根据项目的发展程度,有很多选择

最简单的

最简单的是简单的“if”语句,或者一个开关。我从这里开始让它保持简单

更复杂

<>你说其他项目有不同的页面/控制器-但是有一个原因。当你要求改进时,特别是如果你期望项目增长到你正在寻找优化的程度,那么你真的应该考虑这些原因(并分成文件)。 在刻度的另一端,您可以将所有调用拆分为文件/类,并自动加载文件/类

这样,您只需执行所需的代码(较小的文件大小),这是非常模块化的,并且易于协同工作。而且,如果您添加了新操作,则无需修改索引或数组,您只需修改正在处理的操作文件

示例(从我目前使用此方法进行的项目中大大简化):

1) 创建一个“baseAction”基类,所有操作都将从中扩展。您可以添加常见功能,如清理/预处理参数、日志记录、验证标头等

abstract class baseAction {
    protected $aExpectedParams = [];
    protected $aParams = [];
    protected $validParams = true;

    function __construct() {
        foreach (self::$aExpectedParams as $name=>$aParam) {
            if (isset($_GET[$name]))
                if ($aParam['type'] == 'string') {
                    self::$aParams[$name] = $_GET[$name];
                } elseif ($aParam['type'] == 'int') {
                    self::$aParams[$name] = (int)$_GET[$name];
                }
            } elseif ($aParam['required']) {
                self::$validParams = false;                
            }
        }
    }

    // This is the called function
    abstract function execute();

}
2) 通过扩展基本动作来创建“动作”类。将它们保存在单个文件中(以便其他人可以在不干扰的情况下就项目进行协作)

3) 创建一个自动加载器以拉入这些单独的文件

function myAutoloader($className) {
    if (file_exists(__DIR__ . '/actions/' . $className . '.php')) {
        require_once(__DIR__ . '/actions/' . $className . '.php');
    }
}
spl_autoload_register ('myAutoloader');
4) 那么您的index.php就像

$action = $_GET['action'] ?? '';
if (strlen($action) > 0 && class_exists($action) && method_exists($action, 'execute')) {
    $oAction = new $action();
    $oAction->execute();
} else {
    // Oopsie
}
(最后一个代码段的注释:“class_exists”触发自动加载器。“method_exists”用于检查是否有人请求了诸如“object”之类的普通php类;如果您更安全,则应该为其命名名称空间或添加额外的验证。这只是一个示例!)

function myAutoloader($className) {
    if (file_exists(__DIR__ . '/actions/' . $className . '.php')) {
        require_once(__DIR__ . '/actions/' . $className . '.php');
    }
}
spl_autoload_register ('myAutoloader');
$action = $_GET['action'] ?? '';
if (strlen($action) > 0 && class_exists($action) && method_exists($action, 'execute')) {
    $oAction = new $action();
    $oAction->execute();
} else {
    // Oopsie
}