webfactory / object-routing
基于对象生成路由的库。
Requires
- php: >= 8.1
- jms/metadata: ^2.6.1
- symfony/expression-language: ^3.4|^4.0|^5.0|^6.0|^7.0
- symfony/property-access: ^3.4|^4.0|^5.0|^6.0|^7.0
Requires (Dev)
- doctrine/common: ^2.2
- phpunit/phpunit: ^9.6
- symfony/phpunit-bridge: >5.0
- symfony/routing: ^2.2|^3.0|^4.0
- symfony/yaml: ^3.0|^4.0|^5.0
- twig/twig: ^2.0|^3.0
Conflicts
- twig/twig: ^1.0
Replaces
- jms/object-routing: <= 1.0.0
README
这个库允许根据对象创建路由。这有助于减少每次使用路由时从对象中读取相同参数时的重复代码模式,并且通过支持多态性开辟了新的可能性。
此存储库是基于jms/object-routing的分支,原始文档在http://jmsyst.com/libs/object-routing。
此库与任何具体的路由实现无关。它附带了Symfony路由器的适配器。
安装
通过composer安装此库作为webfactory/object-routing
。
对于Symfony项目,还需要安装webfactory/object-routing-bundle。
用法
声明对象路由的首选和推荐方式是通过PHP属性,尽管PHP、XML和YAML驱动程序也是可用的。有关如何使用这些驱动的说明,请参阅原始库的文档。
此库的1.x版本支持通过注解进行配置。在2.0版本中已移除注解支持。
<?php use JMS\ObjectRouting\Attribute\ObjectRoute; // multiple `#[ObjectRoute]` attributes are possible for different `type`s #[ObjectRoute(type: 'view', name: 'the-actual-route-name', params: ['slug' => 'slug']) class BlogPost { public function getSlug(): string { // ... } }
此代码示例声明了一个名为view
的对象路由。相应的Symfony控制器可能如下所示
<?php use Symfony\Component\Routing\Attribute\Route; // ... class BlogPostController { #[Route('/blog-posts/{slug}', name: 'the-actual-route-name')] public function viewAction(BlogPost $post): Response { // ... } }
您使用对象路由器生成给定对象的给定type
的URL或路径。该type
将用于选择对象的类的正确对象路由,对象路由的name
反过来确定最终将使用的路由的名称。
在对象路由中声明的params
将作为给定对象的Symfony PropertyAccess表达式进行评估,并将得到的值传递给底层的路由器。
您还可以使用名为paramExpressions
的配置设置来支持表达式语言;请参阅下面的章节。
extraParams
可以传递给对象路由器,并且将以原始形式传递到底层路由器。
$objectRouter->generate('view', $blogPost); // equivalent to $router->generate('the-actual-route-name', ['slug' => $blogPost->getSlug()]);
此示例表明,当您需要从对象中读取数据并将其传递给路由器时,使用对象路由器可以生成更简洁的表达式,从而隐藏这些细节,避免重复。
Twig支持
对于Twig,此库还提供了两个新函数
{{ object_path('view', blogPost) }} {# equivalent to #} {{ path('the-actual-route-name', {'slug': blogPost.slug}) }} {{ object_url('view', blogPost) }} {# equivalent to #} {{ url('the-actual-route-name', {'slug': blogPost.slug}) }}
多态性支持
给定type
的对象路由可以在不同的类中定义不同。
例如,您可能有一个“会议网站”应用程序,该应用程序显示日程项的详细信息,但用于显示“研讨会”或“演讲”详细页面的路由不同。
use JMS\ObjectRouting\Attribute\ObjectRoute; #[ObjectRoute(type: 'detail', name: 'app_talk_detail', params: ['id' => 'id']) class Talk { // ... } #[ObjectRoute(type: 'detail', name: 'app_workshop_detail', params: ['slug' => 'slug']) class Workshop { // ... }
在此示例中,您可以使用相同的Twig表达式object_path('detail', schedule_item)
根据它是一个Talk
还是一个Workshop
来生成正确的路由,并且适当的参数(无论是id
还是slug
)也将自动传递。
表达式语言支持
在#[ObjectRoute]
声明中,您还可以使用paramExpressions
键来使用Symfony表达式语言表达式。
表达式可以访问两个变量:this
是生成路由的对象,而 params
可以访问传递给对象路由的所有 extraParams
以及通过属性路径表达式从对象中读取的值。
extraParams
的键表示参数名。键前加上 ?
表示如果表达式计算结果为 null
,则不应设置该值。
一个激励的使用案例是您可能有一个可以存档的 BlogPost
对象。当您链接到这样的博客文章时,您需要将文章的年份包含在额外的 URL 参数中:?year=....
。
仅使用属性访问路径无法实现此功能,但可以通过表达式语言支持来实现。
#[ObjectRoute(..., paramExpressions: ['?year' => 'this.isArchived ? this.year : null'])]
在这种情况下,当 BlogPost::isArchived()
方法返回 true
时,从 BlogPost::getYear()
返回的值将被包含在路由的 year
参数中。当它返回 false
时,省略 year
参数。
许可证
代码在 Apache2 许可证 下发布。
文档受 署名-非商业-禁止演绎 3.0 未本地化 许可证的约束。