php - 为我自己的 PHP 框架制作我自己的参数解析器

标签 php web-services rest symfony symfony-http-foundation

我决定制作我自己的迷你 PHP 框架,我将在现实生活中使用它,为社交应用程序创建 Web 服务。

我从 Fabien Potencier 的指南开始在 Symfony 的组件之上创建自己的框架 - http://symfony.com/doc/current/create_framework/index.html . 我非常喜欢他的 classLoader 和 http-foundation 库,并决定将它们集成。

我阅读了整个教程,但我决定停止集成 Symfony 的组件,直到教程的第 5 部分,他介绍了 Symfony http 内核、路由匹配器和 Controller 解析器(不包括那些)。

有问题的我的框架的前端 Controller 和路由映射器文件。

front.php(前端 Controller )

<?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 的组件,我该如何做这样的事情:

在我的路由文件中,我想添加一个 URL,如“/hello”和 Controller - Hello Controller 和参数名称、年龄、性别,这将对应于浏览器中的请求 GET www.base/hello/samuel/11/male .

并且在 HelloController 中有一个 indexAction($name, $age, $gender) { ... }。我曾尝试查看 Symfony 的源代码,但到目前为止它让我望而却步(我花了很多时间浏览库的源代码)。我将进一步模块化和分离前端 Controller 和解析 Controller 的功能,但我想把它写下来。

啊,还有任何关于进一步构建我的框架的建议都将受到欢迎(我正在为 REST 创建一个框架 - 就像 Web 服务一样,需要可扩展和快速并且可能每秒处理数万个请求)。

最佳答案

如果您想知道 Symfony 如何将其自己的路由格式(例如:'/path/to/{id}' 转换为正则表达式),您必须为您的路由定义正则表达式并将它们与请求进行匹配,请参阅 RouteCompiler::编译模式。这超出了这个问题的范围,我不会为此提供任何代码。

您的示例路由的正则表达式类似于 ^/hello/(\w*)/(\d*)/(\w*)/$,这将匹配 '/hello/any string/any number/any string/' 例如:/hello/samuel/11/male(不要忘记 ^$,它们匹配字符串的开头和结尾)。

您必须为每个路由提供一个正则表达式,并对所有路由(直到一个匹配),而不是 isset($sitemap[$path]) 如果返回 false,路由不匹配。否则你必须像这样为你的 Controller 获取参数:

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 与默认参数合并并调用 Controller 。


参见 UrlMatcher::matchCollection() 关于 Symfony 如何将每个路由与正则表达式进行匹配,并构造参数。

关于php - 为我自己的 PHP 框架制作我自己的参数解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31798306/

相关文章:

php - 如何使用 PHP GD 库将 PNG 转换为 8 位 PNG

php - 如何在mysql中为按日期分组的最大日期选择相应的列

php - Symfony 3.3.3 - 默认 Controller 和容器

java - 如何设置 Web 服务客户端的请求时间(java)

java - 使用 ZipOutPutStream Java 压缩(zip)文件列表

javascript - 编辑表中的行时添加验证

c# - 在 .NET Web 服务上使用/生成 ArrayOfInt 的 int[] insted 方法签名

iphone - iPhone 和 ASP.NET WS (XML/JSON) 之间的身份验证

java - mockMvc POST Junit 测试因 HttpMessageNotReadableException 失败

java - Jersey 2.26 REST API - Json 返回不起作用