0

I am building some frontend forms so that users can manage some data held in custom post types. I would like to minimize the number of pages and templates I need to create to display the correct forms in the correct contexts. I am thinking this would be done by parsing the query string, or, better yet, a prettified URL.

Starting points:

  • I set up a custom post type of data to hold the data management pages (this might be totally unnecessary)
  • The base path to access the data management would be site.local/data
  • The custom post types to be managed are neighborhood, project, and property
  • The possible actions a user can execute are add, edit, and delete

What I'd like to have happen is that a user can go to a URL such as site.local/data/neighborhood/add to add a project, site.local/data/project/edit would provide a list of projects to select and edit, site.local/data/property/edit/123 would allow them to edit a property with an ID of 123, and so on.

The less-pretty version would be using a query string, say site.local/data?data_type=neighborhood&data_action=edit&data_id=123. But I'm struggling to get either method working.

Once I'm able to access these pieces of the URL or query string, I hope to be able to select which forms and fields to display under given conditions in a single template file.

The method I'm hoping to avoid is creating pages and/or templates for each scenario:

  • /data
    • /data/neighborhood
      • /data/neighborhood/add
      • /data/neighborhood/edit
    • /data/project
      • /data/project/delete
    • etc., etc.

I was attempting to get a rewrite rule working like so, but I'm spinning my wheels with it:

function wpse_rewrite_data_management_urls() {
    add_rewrite_rule(
        '^data/([a-z0-9-]+)/([a-z0-9-]+)/([a-z0-9-]+)/?$',
        '/index.php?data_type=$matches[1]&data_action=$matches[2]&data_post_id=$matches[3]',
        'top'
    );
}

add_action( 'init', 'wpse_rewrite_data_management_urls' );

function wpse_data_management_query_vars( $vars ) {
    $vars[] = 'data_type';
    $vars[] = 'data_action';
    $vars[] = 'data_post_id';
    return $vars;
}

add_filter( 'query_vars', 'wpse_data_management_query_vars' );

[Edited to add:] The result is a 404, but here's the pertinent parts of what comes out of $wp_query->query_vars when I go to site.local/data/project/edit/123:

[page] => 123
[data] => project/edit
[post_type] => data
[name] => edit
[pagename] => edit

Any specific help with this or suggestions on how to approach this differently are appreciated.

7
  • 2
    note that a WP rewrite rule lets you map a pretty permalink, on to an ugly permalink, it's not a general URL rewriting feature, this means that those URL parameters are not GET parameters, they're query parameters and they will be stripped out if they're not valid/added to the list. This also assumes that your rewrite rule matches the URL, and it also assumes that if successful you have code that reads these and picks up on it. Remember WP won't know to load your page or templates as those aren't mentioned or queried for in your rule. Commented Jul 6 at 0:03
  • Also, when you say you can't get it working, what happens? Commented Jul 6 at 0:04
  • 1
    do the url with data_type=neighborhood&data_action=edit&data_id=123 already work ? it's the first step before to make url rewriting. Commented Jul 6 at 3:14
  • @TomJNowell I added some missing context and the result above. I also forgot to indicate that I (tried to) set those query vars. Thank you for reminding me that it's a very specific type of rewrite rule, not an all-purpose tool. For now, I'm just trying to determine which parameters I can access and manipulate when creating the template. I'm hoping to see my added query_vars in the list, but no such luck. Commented Jul 6 at 3:14
  • @mmm Yes, using that query string works as expected. Commented Jul 6 at 3:18

1 Answer 1

0

you have a little error in the call of add_rewrite_rule with an extra slash before index.php.

with this correction, your system works without a CPT like data. you can try that :

add_action('init', function () {
    
    add_rewrite_rule(
        '^data/([a-z0-9-]+)/([a-z0-9-]+)/([a-z0-9-]+)/?$',
        'index.php?data_type=$matches[1]&data_action=$matches[2]&data_post_id=$matches[3]',
        'top'
    );
    
});


add_action("template_redirect", function () {
    
    $data = [];
    
    foreach (["data_type", "data_action", "data_post_id"] as $key) {
        $data[$key] = $GLOBALS["wp_query"]->query_vars[$key] ?? "";
    }
    
    
    if (    in_array($data["data_type"], ["neighborhood", "project", "property"])
        &&  in_array($data["data_action"], ["add", "edit", "delete"])
    ) {
        // special handling
        status_header(200);
        
        $template_file = "...";
        
        require $template_file;
        exit();
        
    }
    
    
});


function wpse_data_management_query_vars( $vars ) {
    $vars[] = 'data_type';
    $vars[] = 'data_action';
    $vars[] = 'data_post_id';
    return $vars;
}

add_filter( 'query_vars', 'wpse_data_management_query_vars' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.