• Resolved SurfSD

    (@surfsd)


    (Permalink settings set to /%postname%/ of course)

    Issue: theme’s custom post type for a “portfolio” generates a url of /portfolio/item for portfolio items, we need a different structure. In using WordPress rewrites, $matches variables in add_rewrite_rules() are all empty.

    This theme rewrites portfolio single items like so.

    /portfolio/porfolio-item

    That is not what we need for SEO. We have a gallery page with subcategories, and we need the structure

    gallery/[paint-medium]/[painting-title]

    Attempts to rename the “portfolio” as “gallery” did the obvious – gave 404’s because we can’t have a slug “gallery” for a page and the same slug “gallery” for the portfolio. They need to be different.

    The gallery page is fine, the sub pages are fine, they all generate the thumbnail blocks properly and I got it to output links for item details like so:

    /gallery/oil-paintings/item-1
    /gallery/watercolor/item-7

    Being well versed in mod_rewrite, my thought was to internally rewrite /gallery/medium/item name to portfolio/medium/item-name using mod_rewrite. Simple solution, right? This rule should work in .htaccess:

    RewriteRule ^gallery/([^/]+)/(.*)$ /portfolio/$2 [NC,L]

    (rewrite anything with gallery/medium/item to portfolio/item)

    This rule and many like it has worked on the hundreds of sites I’ve worked on . . . including other sites on this very same server . . . but it does not on this one. After hours messing around with the host who has no clue, I gave up and turned to looking at WordPress rewrites.

    So far I’ve managed to add the rewrites to functions.php using add_rewrite_rules(), but the $matches variables are all empty. Example code:

    if (! function_exists('add_my_portfolio_rules')) {
       function add_my_portfolio_rules() {
         $arr = Array('oil-paintings', 'watercolor');
         foreach ($arr as $type) {
           add_rewrite_rule(
             "gallery/$type/([^/]+)/?$",
             "index.php?post_type=portfolio&post_name=$matches[1]",
             "top");
             // other rewrite rules for attachments, etc
         }
       }
       add_action( 'init', 'add_my_portfolio_rules');
    }

    Which gives me, in the wp_rewrite->rules array,

    [gallery/watercolor/[^/]+/([^/]+)/?$/?] => index.php?post_type=portfolio&post_name=

    Note the empty $matches, compared to the original portfolio rule,

    [portfolio/([^/]+)(?:/([0-9]+))?/?$] => index.php?portfolio=$matches[1]&page=$matches[2]

    As you can see $matches is empty. It will obviously never work . . .

    You might say I should set index.php?portfolio=…. I had previously tried

    "index.php?portfolio=$matches[1]",

    … and it was also empty, so I gave the post type/name a try without result. $matches is empty in either case.

    I have flush_rules hard coded into functions.php **temporarily**, I’m aware it has to be used sparingly, but every time the rules change (will remove it if I can get it to work.)

    Every tutorial/article/codex page I could find says it should be fine in functions.php, any advice how I can resolve this simple task turned disaster? 🙂

Viewing 2 replies - 1 through 2 (of 2 total)
  • Thread Starter SurfSD

    (@surfsd)

    Ha. Came on my own unanswered post trying to solve this after FIVE DAYS.

    The above is only partly incorrect: “post_name” should be “name.” Still broken though.

    What is happening here is the .htaccess rewrites work fine. When Worpdress gets ahold of it, it ignores REDIRECT_URI and uses the original REQUEST_URI. So that was a waste.

    I’ve tried a hack hooked to init that captures $_SERVER[‘REQUEST_URI’] and modifies it. WordPress seems to accept that . . . but does a literal redirect to /portfolio/post_name (uri needs to stay at /gallery/watercolor/post_name].)

    So back to add_rewrite_rules we go. I’m not using any custom query vars for this query, so the ones out of the box are fine:

    // $type = literal, from original for loop, above: watercolor, oil-painting, etc.
    add_rewrite_rule(
      "gallery/$type/([^/]+)/?$",
      "index.php?post_type=portfolio&name=$matches[1]",
      "top"
    );

    (In every instance, index.php?post_type=portfolio&name=[the post post_name value] works perfectly.)

    When it gets to query_vars, it finds post_type just FINE but name is empty:

    Array
    (
      [name] =>
      [post_type] => portfolio
    // etc.
    )

    And of course, the rule is still empty for $matches when I dump $wp_rewrite:

    [gallery/watercolor/([^/]+)/?$] => index.php?post_type=portfolio&name=

    If I escape, like \$matches[1], I can get the literal $matches[1] like the rest of the wp_rewrite, but I don’t think that’s the problem. I think $matches[1] is being set, it’s just being set to empty.

    I could list all the tries that didn’t work, but don’t think that would be helpful. A little help here would be appreciated. I’m about to nuke the whole thing and rewrite it myself. :-\

    Thread Starter SurfSD

    (@surfsd)

    Got it. Sheesh.

    I had previously tried escaping matches but apparently something ELSE was wrong at that point. With the latest iteration of changes, it turns out the most basic coding knowledge was overlooked.

    Double quoted strings are interpolated. I double quoted because I needed to interpolate the $type variable, and also did so in the second params for consistency.

    In the context of add_my_portfolio_rules, $matches is undefined. I overlooked it because that **should** have issued a PHP warning, and somewhere in this mess of code warnings are disabled. That’s my story and I’m sticking to it. 😛

    By escaping $matches,

    "index.php?post_type=portfolio&name=\$matches[1]",

    or single-quoting it,

    'index.php?post_type=portfolio&name=$matches[1]',

    The rewrites now work and I can move on to finishing the cleanup.

    Thanks for all the responses, you have all been very helpful. 😀

    At least, this may help someone else . . .

Viewing 2 replies - 1 through 2 (of 2 total)

The topic ‘Rewrites with Custom Post Type’ is closed to new replies.