今天,我们将介绍 symfony 路由组件,它允许您在 php 应用程序中设置路由。
什么是 Symfony 路由组件?
Symfony 路由组件是一个非常流行的路由组件,它由多个框架改编,如果您希望在 PHP 应用程序中设置路由,它提供了很大的灵活性。
如果您已经构建了一个定制的 PHP 应用程序并且正在寻找一个功能丰富的路由库,那么 Symfony 路由组件非常值得一看。它还允许您以 YAML 格式为您的应用程序定义路由。
从安装和配置开始,我们将通过真实世界的示例来演示该组件用于路由配置的各种选项。在本文中,您将学习:
安装和配置
如何设置基本路线
如何从 YAML 文件加载路由
如何使用多合一路由器
安装和配置
在本节中,我们将安装所需的库,以便在您的 PHP 应用程序中设置路由。我假设您已经在系统中安装了 Composer,因为我们需要它来安装 Packagist 上可用的必要库。
安装 Composer 后,继续使用以下命令安装核心路由组件。
$composer require symfony/routing
尽管 Routing 组件本身足以在您的应用程序中提供全面的路由功能,但我们将继续安装一些其他组件,以使我们的生活更轻松并丰富现有的核心路由功能。
首先,我们将继续安装 HttpFoundation 组件,它为 PHP 全局变量和响应相关函数提供了一个面向对象的包装器。它确保您不需要直接访问诸如$_GET,之类的全局变量。$_post
$composer require symfony/http-foundation
接下来,如果您想在 YAML 文件而不是 PHP 代码中定义您的应用程序路由,那么 YAML 组件可以帮助您将 YAML 字符串转换为 PHP 数组,反之亦然。
$composer require symfony/yaml
最后,我们将安装 Config 组件,它提供了几个实用程序类来初始化和处理在 YAML、INI、XML 等不同类型文件中定义的配置值。在我们的例子中,我们将使用它来加载路由来自 YAML 文件。
$composer require symfony/config
这就是安装部分,但你应该如何使用它呢?实际上,只需将 Composer 创建的autoload.php文件包含在您的应用程序中即可,如下面的代码片段所示。
<?php require_once './vendor/autoload.php'; // application code ?>
设置基本路线
在上一节中,我们完成了必要路由组件的安装。现在,您可以立即在 PHP 应用程序中设置路由。
让我们继续创建具有以下内容的basic_routes.php文件。
<?php require_once './vendor/autoload.php'; use Symfony\Component\Routing\matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Exception\ResourceNotFoundException; try { // Init basic route $foo_route = new Route( '/foo', array('controller' => 'FooController') ); // Init route with dynamic placeholders $foo_placeholder_route = new Route( '/foo/{id}', array('controller' => 'FooController', 'method'=>'load'), array('id' => '[0-9]+') ); // Add Route object(s) to RouteCollection object $routes = new RouteCollection(); $routes->add('foo_route', $foo_route); $routes->add('foo_placeholder_route', $foo_placeholder_route); // Init RequestContext object $context = new RequestContext(); $context->fromRequest(Request::createFromGlobals()); // Init UrlMatcher object $matcher = new UrlMatcher($routes, $context); // Find the current route $parameters = $matcher->match($context->getPathInfo()); // How to generate a seo URL $generator = new UrlGenerator($routes, $context); $url = $generator->generate('foo_placeholder_route', array( 'id' => 123, )); echo '<pre>'; print_r($parameters); echo 'Generated URL: ' . $url; exit; } catch (ResourceNotFoundException $e) { echo $e->getMessage(); }
使用 Symfony Routing 组件设置路由通常要经过一系列步骤,如下所示。
Route为每个应用程序路由初始化 对象。
将所有Route对象添加到RouteCollection对象。
初始化RequestContext保存当前请求上下文信息的对象。
UrlMatcher通过传递RouteCollection对象和对象来初始化RequestContext对象。
为不同的路由初始化路由对象
让我们继续定义一个非常基本的foo路线。
$foo_route = new Route( '/foo', array('controller' => 'FooController') );
Route const ructor的第一个参数是 URI 路径,第二个参数是您希望在匹配此特定路由时返回的自定义属性数组。通常,它将是您希望在请求此路由时调用的控制器和方法的组合。
接下来,我们来看看参数化路由。
$foo_placeholder_route = new Route( '/foo/{id}', array('controller' => 'FooController', 'method'=>'load'), array('id' => '[0-9]+') );
上面的路由可以匹配类似foo/1,foo/123和类似的 URI。请注意,我们仅将{id}参数设置为数值,因此它不会像 URI 那样匹配,foo/bar因为{id}参数是作为字符串提供的。
将所有路由对象添加到 RouteCollection 对象
下一步是将我们在上一节中初始化的路由对象添加到RouteCollection对象中。
$routes = new RouteCollection(); $routes->add('foo_route', $foo_route); $routes->add('foo_placeholder_route', $foo_placeholder_route);
如您所见,这非常简单,您只需要使用对象的add方法RouteCollection来添加路由对象即可。该add方法的第一个参数是路由的名称,第二个参数是路由对象本身。
初始化RequestContext对象
接下来,我们需要初始化RequestContext对象,该对象保存当前的请求上下文信息。当我们初始化对象时,我们将需要这个对象,UrlMatcher因为我们稍后会介绍它。
$context = new RequestContext(); $context->fromRequest(Request::createFromGlobals());
初始化UrlMatcher对象
最后,我们需要UrlMatcher连同路由和上下文信息一起初始化对象。
// Init UrlMatcher object $matcher = new UrlMatcher($routes, $context);
现在,我们拥有了可以匹配路线的所有东西。
如何匹配路线
它是允许您将任何路由与一组预定义路由匹配match的对象的方法。UrlMatcher
该match方法将 URI 作为其第一个参数,并尝试将其与预定义的路由进行匹配。如果找到路由,它会返回与该路由关联的自定义属性。另一方面,ResourceNotFoundException如果没有与当前 URI 关联的路由,它会抛出异常。
$parameters = $matcher->match($context->getPathInfo());
在我们的例子中,我们通过从对象中获取它来提供当前 URI。$context因此,如果您正在访问http://your-domain/basic_routes.php/foo URL,则$context->getPathInfo()返回foo,并且我们已经为fooURI 定义了一个路由,所以它应该返回以下内容。
Array ( [controller] => FooController [_route] => foo_route )
现在,让我们继续通过访问http://your-domain/basic_routes.php/foo/123 URL 来测试参数化路由。
Array ( [controller] => FooController [method] => load [id] => 123 [_route] => foo_placeholder_route )
如果您可以看到该id参数与适当的值绑定,它就会起作用123。
接下来,让我们尝试访问一个不存在的路由,例如http://your-domain/basic_routes.php/unknown-route,您应该会看到以下消息。
No routes found for "/unknown-route".
这就是您可以使用该match方法查找路线的方式。
除此之外,您还可以使用该Routing组件在您的应用程序中生成链接。提供RouteCollection和RequestContext对象,UrlGenerator允许您为特定路线建立链接。
$generator = new UrlGenerator($routes, $context); $url = $generator->generate('foo_placeholder_route', array( 'id' => 123, ));
该generate方法的第一个参数是路由名称,第二个参数是可能包含参数的数组,如果它是参数化的路由。上面的代码应该生成/basic_routes.php/foo/123 URL。
从 YAML 文件加载路由
在上一节中,我们使用 Route和RouteCollection对象构建了自定义路由。事实上,该Routing组件提供了不同的方式供您选择来实例化路由。您可以从各种加载程序中进行选择,例如YamlFileLoader、XmlFileLoader和PhpFileLoader.
在本节中,我们将通过YamlFileLoader加载器来了解如何从 YAML 文件中加载路由。
路由 YAML 文件
继续创建带有以下内容的routes.yaml文件。
foo_route: path: /foo defaults: { controller: 'FooController::indexAction' } foo_placeholder_route: path: /foo/{id} defaults: { controller: 'FooController::loadAction' } requirements: id: '[0-9]+'
示例文件
接下来,继续使用以下内容制作load_routes_from_yaml.php文件。
<?php require_once './vendor/autoload.php'; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\Loader\YamlFileLoader; use Symfony\Component\Routing\Exception\ResourceNotFoundException; try { // Load routes from the yaml file $fileLocator = new FileLocator(array(__DIR__)); $loader = new YamlFileLoader($fileLocator); $routes = $loader->load('routes.yaml'); // Init RequestContext object $context = new RequestContext(); $context->fromRequest(Request::createFromGlobals()); // Init UrlMatcher object $matcher = new UrlMatcher($routes, $context); // Find the current route $parameters = $matcher->match($context->getPathInfo()); // How to generate a SEO URL $generator = new UrlGenerator($routes, $context); $url = $generator->generate('foo_placeholder_route', array( 'id' => 123, )); echo '<pre>'; print_r($parameters); echo 'Generated URL: ' . $url; exit; } catch (ResourceNotFoundException $e) { echo $e->getMessage(); }
在这种情况下,唯一不同的是我们初始化路由的方式!
$fileLocator = new FileLocator(array(__DIR__)); $loader = new YamlFileLoader($fileLocator); $routes = $loader->load('routes.yaml');
我们使用YamlFileLoader加载器从routes.yaml文件加载路由,而不是直接在 PHP 本身中初始化它。除此之外,一切都是一样的,并且应该产生与basic_routes.php文件相同的结果。
多合一路由器
最后在本节中,我们将学习Router该类,它允许您使用更少的代码行快速设置路由。
继续使用以下内容制作all_in_one_router.php文件。
<?php require_once './vendor/autoload.php'; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Router; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\Loader\YamlFileLoader; use Symfony\Component\Routing\Exception\ResourceNotFoundException; try { $fileLocator = new FileLocator(array(__DIR__)); $requestContext = new RequestContext(); $requestContext->fromRequest(Request::createFromGlobals()); $router = new Router( new YamlFileLoader($fileLocator), 'routes.yaml', array('cache_dir' => __DIR__.'/cache'), $requestContext ); // Find the current route $parameters = $router->match($requestContext->getPathInfo()); // How to generate a SEO URL $routes = $router->getRouteCollection(); $generator = new UrlGenerator($routes, $requestContext); $url = $generator->generate('foo_placeholder_route', array( 'id' => 123, )); echo '<pre>'; print_r($parameters); echo 'Generated URL: ' . $url; exit; } catch (ResourceNotFoundException $e) { echo $e->getMessage(); }
一切都几乎相同,除了我们已经实例化了Router对象以及必要的依赖项。
$router = new Router( new YamlFileLoader($fileLocator), 'routes.yaml', array('cache_dir' => __DIR__.'/cache'), $requestContext );
有了这些,您可以直接使用matchRouter 对象的方法进行路由映射。
$parameters = $router->match($requestContext->getPathInfo());
此外,您将需要使用getRouteCollectionRouter 对象的方法来获取路由。
$routes = $router->getRouteCollection();
结论
继续探索路由组件中可用的其他选项 - 我很想听听您的想法!
今天,我们探索了 Symfony 路由组件,它使 PHP 应用程序中的路由实现变得轻而易举。在此过程中,我们创建了一些示例来演示路由组件的各个方面。
- 为不同的路由初始化路由对象
- 将所有路由对象添加到 RouteCollection 对象
- 初始化RequestContext对象
- 初始化UrlMatcher对象
- 如何匹配路线
- 路由 YAML 文件
- 示例文件