Test-Driven Rewrite Rules

Matthew Boynes / @senyob / alleyinteractive.com

  • We are a full-service digital agency
  • WordPress.com VIP partner
  • Hiring!

Let's talk about you

Rewrite Rules Overview

What are they?

End Goal

/foo/bar/

index.php?post_type=foo&name=bar

How do we do that?

  • add_rewrite_rule()
  • add_rewrite_endpoint()
  • add_permastruct()

add_permastruct()

  • Create a block of related rewrite rules
  • Can add pagination, feeds, and other endpoints for you
  • Depends on rewrite tags and rewrite endpoints

Detour: Rewrite Tags

  • e.g. %my-taxonomy%
  • Tags represent rewrite fragments
  • %my-taxonomy%
    ([^/]+)
    my-taxonomy=$matches[n]

add_rewrite_endpoint()

  • Adds a fragment to the end of permastructs
  • e.g. Print views [url]/print/

add_rewrite_rule()

  • Most direct, concrete way to add rules
  • You provide the regex, the resulting query, and a relative position

In the end, one result

array(
  regex => query string,
  regex => query string,
  ...,
)

Example: Tags

'tag/([^/]+)/?$'

=>

'index.php?tag=$matches[1]'

Rewrite Rule Problems

Amongst others...

  • Easy to mess up (a-hem, regex)
  • Conflicts are easy
  • Fragile

Test-Driven Development (TDD)

  1. Write (failing) tests
  2. Write your code
  3. ... until the tests pass
  4. Sleep soundly

TDD and Rewrites

  1. List out the URL structure you want
  2. Write a test that confirms it doesn't work
  3. Build your rewrites
  4. Automated tests will tell you when you've succeeded

Rewrite Testing Plugin

https://wordpress.org/plugins/rewrite-testing/

https://github.com/alleyinteractive/rewrite-testing/

Putting it all Together

Let's say we're building a recipe site

URLs

  • /recipes/
  • /recipes/eggplant/
  • /recipes/eggplant/eggplant-parmesan/

Data Structures

  • Post Type: Recipe
  • Taxonomy: Primary Ingredient

URL Structures

  • /recipes/
  • /recipes/%primary-ingredient%/
  • /recipes/%primary-ingredient%/%recipe%/

Write the tests

Filter: rewrite_testing_tests

Filters an array of test groups

Test URL => Passing match

'/recipes/' => 'index.php?post_type=recipe'

All together


function wcnyc_rewrite_tests( $tests ) {
  $tests['Recipes'] = array(
    '/recipes/' => 'index.php?post_type=recipe',
    '/recipes/eggplant/' => 'index.php?post_type=recipe&primary-ingredient=$matches[1]',
    '/recipes/eggplant/eggplant-parmesan/' => 'index.php?primary-ingredient=$matches[1]&recipe=$matches[2]&page=$matches[3]',
  );
  return $tests;
}
add_filter( 'rewrite_testing_tests', 'wcnyc_rewrite_tests' );
						

Play time!

exit();


Are you a good developer who wants to be a great developer?
We're hiring.

hiring@alleyinteractive.com

@alleydev