今天,我们将介绍Symfony路由组件,该组件可让您在PHP应用程序中设置路由。
什么是Symfony路由组件?
Symfony路由组件是一种非常流行的路由组件,可以通过多种框架进行修改,如果您希望在PHP应用程序中设置路由,则可以提供很大的灵活性。
如果您已经构建了一个自定义PHP应用程序,并且正在寻找功能丰富的路由库,那么Symfony Routing Component绝对值得一看。 它还允许您以YAML格式为应用程序定义路由。
从安装和配置开始,我们将通过实际示例演示该组件用于路由配置的各种选项。 在本文中,您将学习:
- 安装和配置
- 如何设置基本路线
- 如何从YAML文件加载路由
- 如何使用多合一路由器
安装与配置
在本节中,我们将安装在PHP应用程序中设置路由所需的库。 我假设您已经在系统中安装了Composer,因为我们需要它来安装Packagist上可用的必要库。
安装Composer后,请继续并使用以下命令安装核心“路由”组件。
$composer require symfony/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路由组件设置路由通常需要完成以下一系列步骤。
- 为每个应用程序路由初始化
Route
对象。 - 将所有
Route
对象添加到RouteCollection
对象。 - 初始化保存当前请求上下文信息的
RequestContext
对象。 - 初始化
UrlMatcher
通过使对象RouteCollection
对象和RequestContext
对象。
初始化不同路线的路线对象
让我们继续定义一个非常基本的foo
路由。
$foo_route = new Route(
'/foo',
array('controller' => 'FooController')
);
Route
构造函数的第一个参数是URI路径,第二个参数是要匹配此特定路由时要返回的自定义属性的数组。 通常,它将是请求此路由时要调用的控制器和方法的组合。
接下来,让我们看一下参数化的路由。
$foo_placeholder_route = new Route(
'/foo/{id}',
array('controller' => 'FooController', 'method'=>'load'),
array('id' => '[0-9]+')
);
上面的路由可以匹配foo/1
, foo/123
类的URI。 请注意,我们仅将{id}
参数限制为数字值,因此,由于{id}
参数是作为字符串提供的,因此它与foo/bar
类的URI不匹配。
将所有路由对象添加到RouteCollection对象
下一步是将我们在上一节中初始化的路由对象添加到RouteCollection
对象。
$routes = new RouteCollection();
$routes->add('foo_route', $foo_route);
$routes->add('foo_placeholder_route', $foo_placeholder_route);
如您所见,这非常简单,因为您只需要使用RouteCollection
对象的add
方法来添加路由对象。 add
方法的第一个参数是路由的名称,第二个参数是路由对象本身。
初始化RequestContext
对象
接下来,我们需要初始化RequestContext
对象,该对象保存当前的请求上下文信息。 初始化UrlMatcher
对象时,将需要该对象, UrlMatcher
我们将进行介绍。
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
初始化UrlMatcher
对象
最后,我们需要初始化UrlMatcher
对象以及路由和上下文信息。
// Init UrlMatcher object
$matcher = new UrlMatcher($routes, $context);
现在,我们拥有了所有可以与之匹敌的路线。
如何匹配路线
这是UrlMatcher
对象的match
方法,它允许您将任何路由与一组预定义的路由进行匹配。
match
方法将URI作为其第一个参数,并尝试将其与预定义的路由进行匹配。 如果找到该路由,它将返回与该路由关联的自定义属性。 另一方面,如果没有与当前URI关联的路由,它将引发ResourceNotFoundException
异常。
$parameters = $matcher->match($context->getPathInfo());
在我们的例子中,我们通过从$context
对象获取当前URI来提供它。 因此,如果您访问http://your-domain/basic_routes.php/foo URL,则$context->getPathInfo()
context- $context->getPathInfo()
返回foo
,并且我们已经为foo
URI定义了一条路由,因此应该返回以下内容。
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
加载程序从route.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
);
有了它,您可以立即使用Router对象的match
方法进行路由映射。
$parameters = $router->match($requestContext->getPathInfo());
另外,您将需要使用Router对象的getRouteCollection
方法来获取路由。
$routes = $router->getRouteCollection();
结论
继续探索“路由”组件中可用的其他选项,我很想听听您的想法!
今天,我们探索了Symfony路由组件,该组件使在PHP应用程序中轻松实现路由成为可能。 在此过程中,我们创建了一些示例来演示路由组件的各个方面。
希望您喜欢这篇文章,并随时使用下面的提要发表您的想法!