PHP 从头开始分层 MVC 设计?
PHP hierarchical MVC design from scratch?
背景
过去几个月我一直在学习各种教程,目前正在尝试理解 PHP 框架。
我这样做的方法之一是尝试从头开始设计我自己的非常简单的 MVC 框架。
我正在尝试重构一个应用程序(我已经使用意大利面条程序 PHP 构建了该应用程序)。此应用程序有一个供教师使用的前端和一个供管理员使用的后端。
我想分开顾虑并让 URL 像这样
http://example.com/{module}/{controller}/{method}/{param-1}/{param-2}
现在,到目前为止我拼凑的 MVC 框架不处理 'modules' 的路由(如果这不是正确的术语,我深表歉意),只有 controller/method/params.
所以我将 public_html 从应用程序逻辑中分离出来,并在 /app/ 文件夹中指定了两个文件夹,默认的 "learn module" 和 "admin module" 以便目录树如下所示:
显然这个设计模式是 "H"MVC?
我的解决方案
我基本上是利用if is_dir();
函数来检查是否有"module"目录(例如"admin"),然后取消设置第一个URL数组元素 $url[0]
并将数组重新索引为 0...然后我根据 URL 更改控制器路径...代码应该更清晰...
<?php
class App
{
protected $_module = 'learn'; // default module --> learn
protected $_controller = 'home'; // default controller --> home
protected $_method = 'index'; // default method --> index
protected $_params = []; // default paramatars --> empty array
public function __construct() {
$url = $this->parseUrl(); // returns the url array
// Checks if $url[0] is a module else it is a controller
if (!empty($url) && is_dir('../app/' . $url[0])) {
$this->_module = $url[0]; // if it is a model then assign it
unset($url[0]);
if (!empty($url[1]) && file_exists('../app/' . $this->_module . '/controllers/' . $url[1] . '.php')) {
$this->_controller = $url[1]; // if $url[1] is also set, it must be a controller
unset($url[1]);
$url = array_values($url); // reset the array to zero, we are left with {method}{param}{etc..}
}
// if $url[0] is not a module then it might be a controller...
} else if (!empty($url[0]) && file_exists('../app/' . $this->_module . '/controllers/' . $url[0] . '.php')) {
$this->controller = $url[0]; // if it is a controller then assign it
unset($url[0]);
$url = array_values($url); // reset the array to zero
} // else if url is empty default {module}{controller}{method} is loaded
// default is ../app/learn/home/index.php
require_once '../app/' . $this->_module . '/controllers/' . $this->_controller . '.php';
$this->_controller = new $this->_controller;
// if there are methods left in the array
if (isset($url[0])) {
// and the methods are legit
if (method_exists($this->_controller, $url[0])) {
// sets the method that we will be using
$this->_method = $url[0];
unset($url[0]);
} // else nothing is set
}
// if there is anything else left in $url then it is a parameter
$this->_params = $url ? array_values($url) : [];
// calling everything
call_user_func_array([$this->_controller, $this->_method], $this->_params);
}
public function parseUrl() {
// checks if there is a url to work with
if (isset($_GET['url'])) {
// explodes the url by the '/' and returns an array of url 'elements'
return $url = EXPLODE('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
}
}
}
到目前为止这似乎对我有用,但是.....
问题
我不确定这是否是此问题的首选解决方案。是否调用 is_dir()
检查每个页面请求是否会减慢我的应用程序?
你会如何设计解决方案或者我完全误解了这个问题?
非常感谢您的时间和考虑!
根据我的经验,我经常使用 .htaccess 文件将任何请求重定向到唯一的 index.php 文件,这两个文件都位于 public_html 文件夹中。
.htaccess 文件的内容如下(您的 apache 服务器应该启用 mod_rewrite):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
然后,在 index.php 文件中,您可以解析请求 url、定义配置、公共变量、路径等...并包含必要的其他 php 文件。
一个例子:
require( dirname( __FILE__ ) . '/your_routing.php' );
require( dirname( __FILE__ ) . '/your_configs.php' );
require( dirname( __FILE__ ) . '/admin/yourfile.php' );
...
背景
过去几个月我一直在学习各种教程,目前正在尝试理解 PHP 框架。
我这样做的方法之一是尝试从头开始设计我自己的非常简单的 MVC 框架。
我正在尝试重构一个应用程序(我已经使用意大利面条程序 PHP 构建了该应用程序)。此应用程序有一个供教师使用的前端和一个供管理员使用的后端。
我想分开顾虑并让 URL 像这样
http://example.com/{module}/{controller}/{method}/{param-1}/{param-2}
现在,到目前为止我拼凑的 MVC 框架不处理 'modules' 的路由(如果这不是正确的术语,我深表歉意),只有 controller/method/params.
所以我将 public_html 从应用程序逻辑中分离出来,并在 /app/ 文件夹中指定了两个文件夹,默认的 "learn module" 和 "admin module" 以便目录树如下所示:
显然这个设计模式是 "H"MVC?
我的解决方案
我基本上是利用if is_dir();
函数来检查是否有"module"目录(例如"admin"),然后取消设置第一个URL数组元素 $url[0]
并将数组重新索引为 0...然后我根据 URL 更改控制器路径...代码应该更清晰...
<?php
class App
{
protected $_module = 'learn'; // default module --> learn
protected $_controller = 'home'; // default controller --> home
protected $_method = 'index'; // default method --> index
protected $_params = []; // default paramatars --> empty array
public function __construct() {
$url = $this->parseUrl(); // returns the url array
// Checks if $url[0] is a module else it is a controller
if (!empty($url) && is_dir('../app/' . $url[0])) {
$this->_module = $url[0]; // if it is a model then assign it
unset($url[0]);
if (!empty($url[1]) && file_exists('../app/' . $this->_module . '/controllers/' . $url[1] . '.php')) {
$this->_controller = $url[1]; // if $url[1] is also set, it must be a controller
unset($url[1]);
$url = array_values($url); // reset the array to zero, we are left with {method}{param}{etc..}
}
// if $url[0] is not a module then it might be a controller...
} else if (!empty($url[0]) && file_exists('../app/' . $this->_module . '/controllers/' . $url[0] . '.php')) {
$this->controller = $url[0]; // if it is a controller then assign it
unset($url[0]);
$url = array_values($url); // reset the array to zero
} // else if url is empty default {module}{controller}{method} is loaded
// default is ../app/learn/home/index.php
require_once '../app/' . $this->_module . '/controllers/' . $this->_controller . '.php';
$this->_controller = new $this->_controller;
// if there are methods left in the array
if (isset($url[0])) {
// and the methods are legit
if (method_exists($this->_controller, $url[0])) {
// sets the method that we will be using
$this->_method = $url[0];
unset($url[0]);
} // else nothing is set
}
// if there is anything else left in $url then it is a parameter
$this->_params = $url ? array_values($url) : [];
// calling everything
call_user_func_array([$this->_controller, $this->_method], $this->_params);
}
public function parseUrl() {
// checks if there is a url to work with
if (isset($_GET['url'])) {
// explodes the url by the '/' and returns an array of url 'elements'
return $url = EXPLODE('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
}
}
}
到目前为止这似乎对我有用,但是.....
问题
我不确定这是否是此问题的首选解决方案。是否调用 is_dir()
检查每个页面请求是否会减慢我的应用程序?
你会如何设计解决方案或者我完全误解了这个问题?
非常感谢您的时间和考虑!
根据我的经验,我经常使用 .htaccess 文件将任何请求重定向到唯一的 index.php 文件,这两个文件都位于 public_html 文件夹中。 .htaccess 文件的内容如下(您的 apache 服务器应该启用 mod_rewrite):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
然后,在 index.php 文件中,您可以解析请求 url、定义配置、公共变量、路径等...并包含必要的其他 php 文件。 一个例子:
require( dirname( __FILE__ ) . '/your_routing.php' );
require( dirname( __FILE__ ) . '/your_configs.php' );
require( dirname( __FILE__ ) . '/admin/yourfile.php' );
...