wjb / rewire-bundle
使用对象生成路由
v1.0.4
2018-05-25 09:20 UTC
Requires
- doctrine/annotations: ^1.0
- symfony/framework-bundle: ~3.2|~4.0
- symfony/property-access: ~3.2|~4.0
Requires (Dev)
- phpunit/phpunit: ^5.0
- symfony/phpunit-bridge: ^3.4|^4.0
README
使用对象生成路由
假设你有一个具有如下路由的博客应用
/** * @Route("/{id}", name="post_detailed") */ public function indexAction(Post $post) {...}
那么你的模板将会有这个
<a href="{{ path('post_detailed', {'id': new_post.id}) }}">View post</a>
对于这个简单的情况,ParamConverter会被自动应用。
问题
现在想象一下,你想将URL中的{id}
改为{slug}
。更新控制器很简单,但更新所有模板就不那么简单了。
解决方案
这个bundle充当ReverseParamConverter。查看这个示例
/** * @Route("/{id}", name="post_detailed") * @RewireParams(requires={"post"}, rewire={"id"="post.id"}) */ public function indexAction(Post $post) {...}
和模板
<a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>
现在你不再需要使用new_post.id
,你可以直接使用对象本身,这个bundle将会使用它来生成需要的路由{id}
。
所以如果你想路由中使用slug而不是id,只需更新你的控制器
/** * @Route("/{slug}", name="post_detailed") * @RewireParams(requires={"post"}, rewire={"slug"="post.slug"}) */ public function indexAction(Post $post) {...}
这样就完成了,模板不需要任何更改。
注意
如果你安装了这个bundle,你不需要立即更改所有模板。所以这两种组合仍然有效
<a href="{{ path('post_detailed', {'id': new_post.id}) }}">View post</a> <a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>
复杂路由
上面的例子很简单,让我们尝试一个更复杂的例子。为了这个,想象我们想在URL中添加{category_slug}
以改善SEO。
旧方法
/** * @Route("/{category_slug}/{slug}", name="post_detailed") */ public function indexAction(Post $post) {...}
<a href="{{ path('post_detailed', {'category_slug': new_post.category.slug, 'slug': new_post.slug}) }}">View post</a>
对于这个虚构的博客应用,生成的路由可能类似于/conspiracy-theories/why-they-suck
。你可以看到更新模板可能是个问题。
使用这个bundle
/** * @Route("/{category_slug}/{slug}", name="post_detailed") * @RewireParams(requires={"post"}, rewire={"category_slug"="post.category.slug", "slug": post.slug}) */ public function indexAction(Post $post) {...}
你的模板不需要任何更改,它会保持不变
<a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>
用法
@RewireParams注解有两个属性
- requires:这是你的参数名称。在所有示例中都使用了
post
。 - rewire:一组键值对,其中键是在你的@Route注解中使用的名称,值是PropertyAccess规则,用于从对象中读取。
性能
虽然性能会有所下降,但在拥有106个路由(我拥有的最大数量)的页面上,我没有注意到任何性能下降。这可能是太小而无法察觉,但需要更多的测试。
程序通过缓存@RewireParams注解并在稍后使用它们在Router装饰器类中来工作。鉴于这个bundle是一天内构建的,我相信可以进行改进。
安装
composer require wjb/rewire-bundle
如果你使用的是Symfony4,你不需要做任何其他事情。对于Symfony3,在AppKernel中启用这个bundle。
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
...
new wjb\RewireBundle\wjbRewireBundle(),
...