我正在使用Front Controller设计模式构建应用程序,并且只有一个页面index.php
,所有用户请求都通过该页面作为参数传递(与常规设计中的不同页面/控制器相对)。
如何将这些参数连接到应用程序逻辑?
e.g。我有两个不同的行动:
index.php?action=userLogin&username=admin&password=qwerty //process user login
index.php?action=displayUsersTable //show registered users
目前我有一个array
,其中包含系统接受的所有操作(以及预期的参数),我将action
param从URL与此数组的key
进行比较,然后检查所需的这个动作的参数。
//1 = optional, 2=required
$systemActions = [
"userLogin" => [
"login" => 2,
"password" => 2
],
"displayUsersTable" => []
];
显然,随着系统的发展,这将成为一个怪物阵列。
是否有更好的方法将发送到前端控制器的参数绑定到系统操作?
答案 0 :(得分:4)
由于代码是"固定" (即不是从数据库驱动)然后不需要泵入数组(以及它需要的所有处理/内存开销。所以是的,它可以改进。
但是根据项目的增长程度,有很多选择。
<强>最简单强>
最简单的就是简单&#34;如果&#34;陈述或开关。我会从那里开始保持简单。
更复杂
你说其他项目有不同的页面/控制器 - 但是有一个原因。当你要求改进时,特别是如果你期望项目增长到你正在寻找优化的程度,那么你真的应该考虑这些原因(并分成文件)
在比例的另一端,您可以将所有调用拆分为文件/类并自动加载文件/类。
这样,您只需执行所需的代码(较小的文件大小),非常模块化,易于协同工作。如果您添加新操作,则无需修改索引或数组 - 只需修改您正在处理的操作文件。
示例(从我目前使用此方法开展的项目中大大简化):
1)创建一个&#34; baseAction&#34;所有操作都将从中扩展的基类。您可以添加常用功能,例如清理/预处理参数,记录,验证标题等。
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)创建&#34;动作&#34;类,通过扩展基本Action。将它们保存在单个文件中(以便其他人可以在不干扰的情况下协作项目)。
// 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
}
(关于这最后一个片段的注释:&#34; class_exists&#34;触发自动加载器。&#34; method_exists&#34;是检查某人还没有请求一个常见的php类,如&#34; object&#34 ;;如果你更安全,你应该命名这个或添加额外的验证。这只是一个例子!)