Automatically prepending ‘#’ to slug in child page permalinks

Problem

I’d like to have any child page url like http://www.foo.com/fooparent/foochild automatically turns into http://www.foo.com/fooparent/#foochild

Read More

Could this be done with htaccess rewrite rules or any kind of WordPress hook?

Use case

I have the parent pages loading all the child pages content in the template. It’s utilizing a onepage layout with anchor links scrolling down the page to each section as you navigate. There are cases where permalinks of the child pages are exposed and that would break the onepage functionality. A child permalink should just load it’s parent page and add use its slug as a an #anchor in the URL.

Related posts

Leave a Reply

2 comments

  1. I am looping through all the categories, getting the link, and if it is a subcategory I use a regular expression to replace the last / with a #.

    # Code to display category links
    foreach(wp_list_categories() as $category) {
        $name = $category->name;
        $link = get_category_link($category->term_id);
    
        if($category->parent) {
            // Parent isn't 0, lets change this link to have an anchor
            $link = preg_replace('~/([^/]+)/?$~', '#$1', $link);
        }
    
        // Output $name/$link
    }
    

    The regex /([^/]+)/?$ matches a /, followed by any non / characters in a capture group (the anchor), followed by an optional trailing slash and the end of the string ($). We can replace this match with a pound and the anchor saved in our first capture group (#$1).


    Update:

    As a prefix, I can’t tell from the documentation whether or not get_the_category() gets the current category for a category template..but let us assume it does. Then you can do something like this:

    # Code to redirect away from subcategory pages
    $category = get_the_category(); // not sure if this works
    
    // We are directly accessing a child category, redirect
    if($category->parent) {
        $link = get_category_link($category->term_id);
        $link = preg_replace('~/([^/]+)/?$~', '#$1', $link);
    
        header("HTTP/1.1 301 Moved Permanently"); 
        header("Location: $link");
        exit;
    }
    

    Links:

  2. Hashes are not seen or processed by the .htaccess, they are resolved client side–you don’t have access to them in the request on the server. Therefore, you won’t be able to detect it in wordpress. Refer to this more general question: Can I read the hash portion of the URL on my server-side application (PHP, Ruby, Python, etc.)?

    Even if you build the new link on the server side, when someone clicks on the link, wordpress won’t get anything after the hash to use for looking up the content. So it wouldn’t be able to lookup the child page.

    However, if you’re not trying to rewrite incoming requests, but instead modify links you’re displaying, you could do that manually in PHP (wordpress) when you generate the links but before you display them. See the comment to your OP Sam indicated for a rough regular expression replacement example.