首頁  >  文章  >  後端開發  >  使用Symfony路由組件在PHP應用程式中設定路由

使用Symfony路由組件在PHP應用程式中設定路由

王林
王林原創
2023-09-03 22:37:061144瀏覽

使用Symfony路由組件在PHP應用程式中設定路由

什麼是 Symfony 路由元件?

Symfony 路由元件是一個非常流行的路由元件,它由多個框架改編而成,如果您希望在 PHP 應用程式中設定路由,它可以提供很大的靈活性。

如果您已經建立了自訂 PHP 應用程式並正在尋找功能豐富的路由庫,那麼 Symfony 路由元件是最佳候選之一。它還允許您以 YAML 格式定義應用程式的路由。

從安裝和配置開始,我們將透過實際範例來示範該元件用於路由配置的各種選項。在本文中,您將了解:

  • Symfony 路由元件的安裝與設定
  • #如何設定基本路線
  • #如何從 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 class="brush:php;toolbar:false">';
    print_r($parameters);
 
    echo 'Generated URL: ' . $url;
    exit;
}
catch (ResourceNotFoundException $e)
{
  echo $e->getMessage();
}

使用 Symfony Routing 元件設定路由通常要經歷以下列出的一系列步驟。

  • 為每個應用程式路由初始化 Route 物件。
  • 將所有 Route 物件新增至 RouteCollection 物件。
  • 初始化 RequestContext 對象,該對象保存目前請求上下文資訊。
  • 透過傳遞 RouteCollection 物件和 RequestContext 物件來初始化 UrlMatcher 物件。

初始化不同路由的路由物件

讓我們繼續定義一個非常基本的 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/1foo/123 等類似的 URI。請注意,我們將{id} 參數限制為僅限數字值,因此它不會符合foo/bar 這樣的URI,因為{id}參數以字串形式提供。

將所有路由物件新增至 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 对象时,我们将需要这个对象,因为我们稍后会详细介绍它。

$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 来提供它。因此,如果您访问 https://your-domain/basic_routes.php/foo URL,则 $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 方法查找路由。

除此之外,您还可以使用路由组件在应用程序中生成链接。提供了 RouteCollectionRequestContext 对象,UrlGenerator 允许您为特定路由构建链接。

$generator = new UrlGenerator($routes, $context);
$url = $generator->generate('foo_placeholder_route', array(
  'id' => 123,
));

generate 方法的第一个参数是路由名称,第二个参数是数组,如果是参数化路由,则可以包含参数。上面的代码应该生成 /basic_routes.php/foo/123 URL。

从 YAML 文件加载路由

在上一节中,我们使用 RouteRouteCollection 对象构建了自定义路由。事实上,路由组件提供了不同的方式供您选择来实例化路由。您可以从各种加载器中进行选择,例如 YamlFileLoaderXmlFileLoaderPhpFileLoader

在本节中,我们将通过 YamlFileLoader 加载器来了解如何从 YAML 文件加载路由。

路由 YAML 文件

继续创建包含以下内容的 routes.yaml 文件。

foo_route:
    path:     /foo
    controller: App\Controller\FooController::index
    methods:    GET
 
foo_placeholder_route:
    path:     /foo/{id}
    controller: App\Controller\FooController::load
    methods:    GET
    requirements:
        id: '[0-9]+'

示例文件

接下来,继续使用以下内容创建 load_routes_from_yaml.php 文件。

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 '
';
    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 class="brush:php;toolbar:false">';
    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();

将路由创建为注释:推荐方式

在本节中,我们将讨论如何实现基于注释的路由。它正在成为在不同框架之间定义路由的最流行的方法之一。

在我们继续实现基于注释的路由之前,我们需要安装几个软件包。让我们快速完成此操作,如以下代码片段所示。

$composer require symfony/framework-bundle
$composer require doctrine/annotations
$composer require doctrine/cache

如您所见,我们安装了三个不同的组件。

在您的 composer.json 文件中,添加以下内容:

"autoload": {
    "psr-4": {
        "App\\": "app/"
    }
}

现在,运行以下命令。

$composer dump-autoload

现在,我们准备好文件了。

继续创建包含以下内容的 index.php 文件。

load(__DIR__ . '/src/Controller/');
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());

$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match($context->getPathInfo());

$controllerInfo = explode('::',$parameters['_controller']);

$controller = new $controllerInfo[0];
$action = $controllerInfo[1];

$controller->$action();

现在,让我们在 src/Controller/FooController.php 中创建包含以下内容的控制器文件。

<?php
namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;

class DefaultController
{
    /**
     * @Route("/",name="index")
     */
    public function index()
    {
        echo "Index action";
    }

    /**
     * @Route("/hello",name="hello")
     */
    public function hello()
    {
        echo "Hello action";
    }
}

您可能已经注意到,我们以注释的形式为每个方法定义了路由。这种方法的好处是,它允许您在与这些路由关联的控制器的代码旁边定义路由。

继续访问 https://your-domain/index.php/ URL。根据以下路由配置,它应该调用 index 方法。

/**
 * @Route("/",name="index")
 */

另一方面,如果您尝试访问 http://your-domain/index.php/hello URL,它应该调用 DefaultController 控制器的 hello 方法类。

这就是基于注释的路由的工作原理!

结论

继续探索路由组件中可用的其他选项。

今天,我们探索了 Symfony 路由组件,它使得在 PHP 应用程序中实现路由变得轻而易举。在此过程中,我们创建了一些示例来演示路由组件的各个方面。

以上是使用Symfony路由組件在PHP應用程式中設定路由的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn