1

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

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.

Tom
  • 1,095
  • 2
  • 12
  • 30

2 Answers2

2

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:

Sam
  • 20,096
  • 2
  • 45
  • 71
  • I have the menu alerted to add the /# part fine, but there are some use cases where the original permalink is exposed and if someone were to be directed to that, the onepage layout would break. I'm trying to force the original permalink of child pages to add a '#' – Tom Apr 15 '14 at 21:31
  • @Tom You can't put any information Wordpress needs to know about after the hash. The PHP request won't get it to be able to lookup the child. Hash values aren't sent to the server. – Ray Apr 15 '14 at 21:34
  • @ray Maybe I should detect you landed on a child page with javascript and redirect to the parent URL with added anchor. It's really just a precaution that if someone wrote www.foo.com/parentfoo/childfoo it would redirect to parentfoo/ but with #childfoo added as an anchor. – Tom Apr 15 '14 at 21:36
  • @Tom so child foo is content on the parentfoo page? you would never request childfoo directly? Meaning these two urls should resolve to the same `www.foo.com/parentfoo == www.foo.com/parentfoo#childfoo` – Ray Apr 15 '14 at 21:39
  • @ray right. All the child page content is being ajax loaded into the parent pages. I'm just doing that for admin structure. I know it's confusing but for a user/client adding page content it makes sense. You are basically tricking wordpress into adding sections to the main category as one page. I'm using anchor links to scroll up and down the page. I just wanted the precaution that if someone left out the #anchor they woudldn't screw the whole thing up. – Tom Apr 15 '14 at 21:42
  • @Tom Got it. Sorry for the confusion. – Ray Apr 15 '14 at 21:43
  • You should be able to redirect users from the main subcategory URL to the main category URL with an anchor in the beginning of your category template. I'm not savvy with WP though and their documentation sucks.. – Sam Apr 15 '14 at 21:43
  • yeah I figured there's a way to do this with the API so I'll have to do a bit more digging. I just thought I'd post it on here for someone else to stress over about it... hahaha. jk. – Tom Apr 15 '14 at 21:45
  • @Tom I get it, you're just trying to enforce not pulling the child pages directly. – Ray Apr 15 '14 at 21:46
  • @ray and the ONLY time that might happen is from someone typing out the URL's from memory OR I have a plugin that you can put in a link to other pages into your content, but it pulls the actual permalink into it, which wouldn't be good to show. – Tom Apr 15 '14 at 21:47
  • @Tom check my update. I'm not sure if `get_the_category()` is the right way to get a category from the category archive (their documentation sucks), but pretty much I'm checking if WordPress thinks we are on a subcategory page. If we are, then 301 redirect to the new URL. – Sam Apr 15 '14 at 21:54
  • @sam the major problem with redirects like that is SEO. – Tom Apr 15 '14 at 21:54
  • @Tom that is a 301 redirect, which should tell Google that this page has **permanently** moved. Also, you will never be directly linking to that page. If you want to do what you are trying to do, this is the best way for SEO. – Sam Apr 15 '14 at 21:55
  • @sam I took what you wrote and modified it for my needs. I think this will do it. Thank you so much. I think I was looking at it a bit too complicated. `if ( is_page() && $post->post_parent > 0 ) { $link = get_permalink( $post->ID ); $link = preg_replace('~/([^/]+)/?$~', '#$1', $link); header("HTTP/1.1 301 Moved Permanently"); header("Location: $link"); exit; } ` I have no clue how to format this code in a comment. – Tom Apr 15 '14 at 22:10
  • Glad I could help :) Sorry it took the 3 of us a roundabout conversation to get here – Sam Apr 15 '14 at 22:25
0

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.

Community
  • 1
  • 1
Ray
  • 40,256
  • 21
  • 101
  • 138
  • I think he wants to change the links server-side before sending them to the client. I believe the category pages are already set up to have all the subcategories with anchors. (my interpretation) – Sam Apr 15 '14 at 21:22
  • 1
    @Sam yeah, I wasn't sure which side he was concerned with since he mentioned htaccess files. – Ray Apr 15 '14 at 21:24
  • Well within Wordpress, I think you can take edit how wordpress handles its own permalink/rewrite structure. Not directly editing the actual htaccess files though. – Tom Apr 15 '14 at 21:28
  • @Tom yes, there is a page to modify permalink format inside the WP admin panel. – Ray Apr 15 '14 at 21:30
  • @Tom The setting is under Settings->permalinks – Ray Apr 15 '14 at 21:32
  • @Sam I think even if Tom rewrite to use the hash structure he indicates, when someone click on one of the links, the hash is dropped and wordpress wouldn't be able to find the child content. – Ray Apr 15 '14 at 21:36