我正在编写自己的php mvc框架(仅用于训练)。问题是当请求的控制器不存在时如何处理异常?我应该调用 404 类还是创建并显示来自路由器的新视图?如果您对我有任何建议,我会很高兴! 这是我的自动加载.php:
function __autoload($class)
{
$filename = __DIR__ . '/' . str_replace('\', DIRECTORY_SEPARATOR, $class) . '.php';
if (file_exists($filename))
{
require $filename;
}
else
{
throw new Exception('The file doesn't exists!');
}
}
和路线.php:
namespace App;
class Route
{
public static function start ()
{
$controller_name = 'News';
$controller_action = 'Index';
if (isset($_GET['furl']))
{
// Getting rid of spaces
$url = str_replace(' ', '', $_GET['furl']);
if (substr($url, -1) == '/')
{
$url = substr($url, 0, count($url) - 2);
}
$arr = explode('/', $url);
foreach($arr as &$value)
{
$value = strtolower($value);
$value = ucfirst($value);
}
$controller_action = $arr[count($arr) - 1];
unset($arr[count($arr) - 1]);
$controller_name = implode('\', $arr);
}
$controller_name = 'AppControllers\' . $controller_name;
try
{
$controller = new $controller_name();
}
catch (Exception $e)
{
//HELP ME PLS!
}
$controller->action($controller_action);
}
}
不管已经有多少Web框架,路由器,自动加载机等:继续做你认为适合你并且适合你暂时理解水平的事情,以便学习。实际上,通过面对在实现应用程序不同部分的过程中出现的问题,您不仅有机会学习和发现新事物,而且还会学习如何以及在现有框架的设计中学习什么。
研究 PHP 标准建议(标记为"已接受"的建议)。尤其是PSR-1,2,4,7。它们被许多框架和PHP项目使用。阅读常见问题解答以了解有关项目本身的更多信息。
自动加载机:
PSR-4 在文档末尾提供了示例链接。
@mike建议,您应该使用作曲家自动加载器。我同意他的观点,我也强烈推荐给你。但我建议您仅在正确实现并使用自己的自动加载机(符合 PSR-4 标准)后才执行此操作。为什么?您绝对需要了解自动加载过程的工作原理。在将来的某些情况下,您仍然需要自己的自动加载器实现,即使在 Composer 安装并运行之后也是如此。
另请注意,您不得从自动加载器本身引发任何异常!
路由器:
顺便说一句,你的类应该被称为"路由器"。
路由器不应负责验证控制器类/文件和操作,也不应负责调用操作。这些任务是"前端控制器"职责的一部分。您的路由器应该只返回解析后产生的组件,例如"爆炸"请求 URI($_GET['furl']
),以某种形式(作为 Route 对象(作为属性),作为数组等)。这些组件是控制器名称、操作名称、操作参数列表(注意:操作参数不是查询字符串参数)。前端控制器进一步使用它们来验证/访问控制器类/文件及其操作并调用操作。
但请注意,路由器实际上以其他方式工作。简而言之:它将请求方法(GET,POST等)和请求URI与现有的(例如由您预定义的)路由定义列表进行匹配(例如比较)。路由定义包含与特定控制器、操作等相关的信息。如果 HTTP 方法和请求 URI"对应"到其中一个路由定义,则路由器将匹配定义的组件返回到前端控制器(以某种形式:作为对象、作为数组等)。
有关此原则的更多详细信息,请参阅:
- 如何在类似MVC的页面中根据漂亮的URL加载类?
- 快速路线
- 光环路由器
前端控制器:
它可以是一个类,但它也可以只是应用入口点(index.php、bootstrap.php等)中的香草代码。在后一种情况下,前端控制器代码应驻留在应用的文档根目录之外的文件中。例如,在引导.php文件中,该文件仅包含在索引中.php而索引.php驻留在文档根目录中。
"找不到控制器/操作"特定处理:
如果找不到控制器或操作/无效,则调用预定义Error
控制器的预定义操作(例如displayError
),该操作通知用户,对于其请求的特定部分(实际上是他提供的请求 URI),未找到任何资源。
例如,假设用户提供了请求 URIwww.example.com/books/show/12
。符合应用工作流,控制器Book
,操作(例如控制器的方法)show
,操作参数12
(值作为参数传递给show
方法,并定义为其中$bookId
参数)。但是,如果未定义控制器类,或者不存在控制器文件,则前端控制器应调用Error
控制器的操作displayError
,该控制器应显示类似No resource found for your 'book' request
的消息。当尚未在Book
控制器中定义show
方法时,应显示类似的信息。
请注意,如果Error
控制器或其操作未找到/无效,则 PHP 引擎会引发相应的错误/异常。如果您按照我提供的下一个链接进行操作,您最终将实现三个自定义错误/异常处理函数(分别由 set_error_handler、set_exception_handler 和 register_shutdown_function 引用)。他们将正确捕获并处理所描述的情况。
阅读:管理框架的错误
MVC 中的常规错误/异常处理:
这里有一些很好的资源:
- 再次:管理框架的错误
- 错误记录,以流畅的方式
- 错误报告基础知识
- 尝试的(不)正确使用..抓住
其他 MVC 相关资源:
- 构建一个 PHP MVC 应用程序(只是为了开始...)
- PHP 中的依赖注入和依赖反转
- 面向高级 PHP 开发人员的 MVC(更多资源列表)
- 汤姆·巴特勒的编程博客。MVC, PHP, 最佳实践
- 干净、高质量的代码
PS:避免使用static
s,global
s,singleton
s.为什么?例如,阅读此处和此处。
祝你好运。