我决定制作我自己的PHP迷你框架,我将用于现实生活中的工作,为社交应用程序创建Web服务。
我开始使用Fabien Potencier的指南,在Symfony的组件之上创建自己的框架 - http://symfony.com/doc/current/create_framework/index.html。 我真的很喜欢他的classLoader和http-foundation库,并决定将它们集成在一起。
我阅读了整个教程,但我决定停止将Symfony的组件集成到教程的第5部分,他将访问Symfony http内核,路由匹配器和控制器解析器(不包括那些)。
我的框架的前端控制器和路由映射器文件有问题。
front.php(前端控制器)
<?php
require 'config/config.php';
require 'config/routing.php';
require 'src/autoloader.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$response = new Response();
$path = $request->getPathInfo();
if(isset($siteMap[$path])) {
call_user_func_array('src\Controllers' .'\\' . $siteMap[$path]['controller'] . '::' . $siteMap[$path]['action'], array($siteMap[$path]['arguments']));
} else {
$response->setStatusCode('404');
$response->setContent('Page not found');
}
$response->send();
?>
我的路由文件:
/*
Map of routes
*/
$siteMap = array('/' => array('controller' => 'IndexController', 'action' => 'indexAction', 'arguments' => ''),
'/categories' => array('controller' => 'CategoriesController', 'action' => 'indexAction', '
我现在想知道的是没有进一步使用Symfony的组件,我该怎么做这样的事情:
在我的路由文件中,我想添加一个像&#39; / hello&#39;使用Controller - Hello控制器和参数名称,年龄,性别,它们对应于浏览器中的请求GET www.base / hello / samuel / 11 / male。
在HelloController中有一个indexAction($ name,$ age,$ gender){...}。我已经尝试过查看Symfony的源代码,但到目前为止它还没有找到我(我花了很多时间去了解库的源代码)。我将模块化和分离前端控制器和控制器的功能进一步解决,但我想把它搞定。
啊,以及关于进一步构建我的框架的任何建议都会受到欢迎(我正在创建一个类似于REST的框架式Web服务,它需要可扩展且快速,并且每秒可处理数万个请求)。
答案 0 :(得分:3)
如果您想知道Symfony如何转换自己的路由格式,您必须为路由定义正则表达式并将其与请求进行匹配,例如:&#39; / path / to / {id}&#39;到正则表达式,请参阅RouteCompiler :: compilePattern。这超出了这个问题的范围,我将不提供任何代码。
示例路由的正则表达式将类似^/hello/(\w*)/(\d*)/(\w*)/$
,这将匹配&#39; / hello /任何字符串/任何数字/任何字符串/&#39;例如:/hello/samuel/11/male
(不要忘记^
和$
,它们会匹配字符串的开头和结尾。)
您必须为每个路由提供一个正则表达式,并对所有路由(直到一个匹配)执行preg_match(rawurldecode($request->getPathInfo(), $regex /* as created earlier*/, $matches)
,而不是isset($sitemap[$path])
如果返回false,则路由不匹配。否则你必须得到你的控制器的参数:
preg_match(rawurldecode($request->getPathInfo(), $regex /* as created earlier*/, $matches)
$args = array();
// we omit the first element of $matches, since it's the full string for the match
for($i = 1; $i < count($matches); $i++){
$args[] = $matches[$i];
}
现在您可以将$args
与默认参数合并并调用控制器。
请参阅UrlMatcher :: matchCollection(),了解Symfony如何根据正则表达式匹配每条路由,并构造参数。
答案 1 :(得分:0)
我想补充一些其他信息。在Symfony中,您可以将请求的参数提取到方法参数中:
public function fooAction($bar);
在这种情况下,它会在$request->attributes
中查找包含bar
的密钥。如果值存在,它会将此值注入您的操作。在Symfony 3.0及更低版本中,这是通过ControllerResolver::getArguments()
完成的。从Symfony 3.1开始,您将能够实现或扩展ArgumentResolver
。
使用ArgumentResolver
意味着您可以轻松地将自己的功能添加到解析中。 The existing value resolvers are located here