wjb/rewire-bundle

Use objects to generate routes

Installs: 98

Dependents: 0

Suggesters: 0

Security: 0

Stars: 5

Watchers: 2

Forks: 0

Open Issues: 0

Type:symfony-bundle

v1.0.4 2018-05-25 09:20 UTC

This package is auto-updated.

Last update: 2024-04-10 22:50:47 UTC


README

SensioLabsInsight

Use objects to generate routes

Let's say you have a blog application with route like this:

/**
 * @Route("/{id}", name="post_detailed")
 */
public function indexAction(Post $post)
{...}

then your templates will have this:

<a href="{{ path('post_detailed', {'id': new_post.id}) }}">View post</a>

For this simple case, ParamConverter is automatically applied.

The problem

Now imagine you want to change it to use {slug} instead of {id} in your URL. Updating controller is simple, but updating all the templates is not so.

The solution

This bundle acts as ReverseParamConverter. Check this example:

/**
 * @Route("/{id}", name="post_detailed")
 * @RewireParams(requires={"post"}, rewire={"id"="post.id"})
 */
public function indexAction(Post $post)
{...}

and the template:

<a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>

Now instead of new_post.id you can use object itself and this bundle will use it to generate {id} needed for route.

So if you want to slug instead of id in your route, just update your controller:

/**
 * @Route("/{slug}", name="post_detailed")
 * @RewireParams(requires={"post"}, rewire={"slug"="post.slug"})
 */
public function indexAction(Post $post)
{...}

and that's all, template doesn't require any changes.

Note

If you install this bundle, you don't have to change all your templates immediatelly. So both these combinations would still work:

<a href="{{ path('post_detailed', {'id': new_post.id}) }}">View post</a>

<a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>

Complex routes

The above example is pretty simple so let's try something more complex. For this, imagine we wanted to add {category_slug} to URL for better SEO.

The old way:

/**
 * @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>

For this fictional blog application, generated route would be something like /conspiracy-theories/why-they-suck. You can see why updating templates can be a problem.

With this 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)
{...}

your template doesn't require any changes, it would remain the same:

<a href="{{ path('post_detailed', {'post': new_post}) }}">View post</a>

Usage

The @RewireParams annotation has 2 properties:

  • requires: these are names of your parameters. post is used in all examples.
  • rewire: a set of key=>value pairs where key is the name used in your @Route annotation and value is PropertyAccess rule for reading objects.

Perfomance

While there is perfomance hit, I didn't notice any on page with 106 routes (largest I have). It is probably too small to spot it but more testing is needed.

Program works by caching @RewireParams annotations and later using it in Router decorator class. Given this bundle is built in a day, I am sure improvements can be made.

Installation

composer require wjb/rewire-bundle

If you are on Symfony4, you don't have to do anything else. For Symfony3, enable the bundle in your AppKernel:

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            ...
            new wjb\RewireBundle\wjbRewireBundle(),
            ...