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



我正在使用前控制器设计模式构建一个应用程序,并且只有一页index.php,所有用户请求都以参数(与常规设计中的不同页面/控制器相比)。

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

例如。我有两个不同的动作:

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

当前,我有一个array,其中系统接受(以及预期参数),并且我将action参数从URL与此数组的key进行比较,然后检查此操作所需的参数。

//1 = optional, 2=required
$systemActions = [
      "userLogin" => [
            "login" => 2,
            "password" => 2
                     ],
      "displayUsersTable" => []
                 ];

显然,随着系统的成长,这将成为怪物阵列。

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

,因为代码为"固定"(即未从数据库驱动),则无需泵入数组(以及所有需要的处理/内存开销。,可以改进。

,但是有很多选择,具体取决于项目的增长。

最简单

最简单的是"如果"语句或开关。我从那里开始以保持简单。

更复杂的

您说其他项目有不同的页面/控制器 - 但有原因。当您要求改进时,尤其是如果您期望该项目成长到要优化的程度,那么您确实应该考虑这些原因(并分为文件)。

在刻度的另一端,您可以将所有调用分为文件/类并自动加载文件/类。

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

示例(从我目前正在使用此方法的项目中简化了大量简化):

1)创建一个"基础"基类。所有动作都将从。您可以添加常见功能,例如清洁/预处理参数,记录,验证标头等。

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)通过扩展基本操作来创建"动作"类。将这些保存在单个文件中(因此其他人可以在项目上进行协作而不会干扰)。

// put in 'actions/userLogin.php
class userLogin extends baseAction {
    protected $aExpectedParams = [
            'login' => ['type' => 'string', 'required' => true]
            'password' => ['type' => 'string', 'required' => true]  // NOTE: you should never actually pass password unencrypted through "get" as they'll get stuck in user logs!
                    ];
    public function execute() {
        // Do Whatever
    }
}

// put in 'actions/displayUsersTable.php
class displayUsersTable extends baseAction {
    public function execute() {
        // Do Whatever
    }
}

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"是检查某人没有请求某人,例如"对象"等常见的PHP类;如果您更安全,则应命名空间或添加额外的验证。这只是一个示例!)

相关内容

  • 没有找到相关文章