最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

functions - Use author author display name in permalink structure for pages and posts

programmeradmin1浏览0评论

I need to add the author name as a subdirectory prefix for all user's posts and pages.

For example:

example/johndoe/ //The author page for John Doe
example/johndoe/category/test-post/ //Test post by user John Doe
example/johndoe/test-page/ //Test page by user John Doe

If I change the permalink structure to: /%author%/%category%/%postname%/ this works fine for displaying a user's post but not a user's page.

However I'm not sure if there is something I can do in .htaccess or functions.php that will allow me to get the pages to work in the same manner.

I understand this can be accomplished with Multisite, however I'm trying to avoid using this because the client doesn't want to use it.

I need to add the author name as a subdirectory prefix for all user's posts and pages.

For example:

example/johndoe/ //The author page for John Doe
example/johndoe/category/test-post/ //Test post by user John Doe
example/johndoe/test-page/ //Test page by user John Doe

If I change the permalink structure to: /%author%/%category%/%postname%/ this works fine for displaying a user's post but not a user's page.

However I'm not sure if there is something I can do in .htaccess or functions.php that will allow me to get the pages to work in the same manner.

I understand this can be accomplished with Multisite, however I'm trying to avoid using this because the client doesn't want to use it.

Share Improve this question edited May 4, 2016 at 16:07 bigmike7801 asked May 4, 2016 at 15:55 bigmike7801bigmike7801 2635 silver badges16 bronze badges 15
  • You say "this works fine". So what is wrong ? – Random Commented May 4, 2016 at 16:03
  • It works fine for posts, but not for pages. I'll edit the question to make this more clear. – bigmike7801 Commented May 4, 2016 at 16:06
  • 1 Will every user have the same set of "pages"? It would be helpful if you would outline the desired complete solution in more detail, but it seems offhand that you might do better with a programmatic solution involving categories or other taxonomies, or custom post types and custom taxonomies, than by relying on Pages. – CK MacLeod Commented Mar 10, 2017 at 6:28
  • 1 Oops, got snookered by the revived old question syndrome. What I get for StackExchanging on my phone. I'm going to assume this question is dead until further notice... – CK MacLeod Commented Mar 10, 2017 at 6:29
  • 1 With that said: utility is for informational purposes and rarely changed, almost static data specific to the "user" or "author" in this case; archival is the data the "user" has input over time. – Nathan Powell Commented Mar 10, 2017 at 6:38
 |  Show 10 more comments

2 Answers 2

Reset to default 1

By the looks of it, there's a plugin to achieve exactly this, so save you rolling your own for it.

The plugin is: https://wordpress/plugins/permalinks-customizer/

I installed it to test that it does what you're looking for. Here's a screenshot that shows what you'd do:

Tested with Wordpress 5.0.4

The first problem to solve it's the post_name value for pages that would share the same slug (e.g. about-me).

The simpler solution I found is to add the author nicename (beware: in my solution it should not contain a hyphen!) as the first part of the slug:

about-me page post_name for john: john-about-me
about-me page post_name for mary: mary-about-me

This could be achieved using the wp_insert_post_data filter hook (see wp_insert_post() function defined in wp-includes/post.php) when creating the page:

// about-me => <author_name>-about-me

add_filter( 'wp_insert_post_data', 'custom_wp_insert_post_data', 99, 2);

function custom_wp_insert_post_data($data, $postarr)
{
    if(($data["post_type"] == "page") && ($data["post_status"] != "auto-draft"))
    {
        $author_name = get_the_author_meta( 'user_nicename', $data["post_author"] );

        // insert
        if($postarr['hidden_post_status'] == "draft") {         
            $data["post_name"] = $author_name . "-" . $data["post_name"];               
        }
        // update
        else {
            list($author, $slug) = explode("-", basename($data["post_name"]), 2 );

            // wrong permalink -> prepend the author
            if($author != $author_name) { 
                $data["post_name"] = $author_name . "-" . $data["post_name"];
            }
        }
    }

    return $data;   
}

Next step it will be to change the wp rewrite rules to reflect our desires (you need also to update the settings > permalinks):

add_filter('page_rewrite_rules', 'custom_page_rewrite_rules');

function custom_page_rewrite_rules($page_rewrite) 
{   
    // remove : john/about-me  => index.php?pagename=john/about-me
    unset($page_rewrite["(.?.+?)(?:/([0-9]+))?/?$"]);   

    // add: john/about-me  => index.php?pagename=john-about-me
    $page_rewrite["(.?.+?)/(.+?)/?$"] = "index.php?pagename=\$matches[1]-\$matches[2]";

    return $page_rewrite; 
}

add_filter('post_rewrite_rules',  'custom_post_rewrite_rules'); 

// posts have the /%author%/%category%/%postname% permalink structure
function custom_post_rewrite_rules($post_rewrite) 
{   
    // remove: john/about-me  => index.php?category_name=about-me&author_name=john
    unset($post_rewrite["([^/]+)/(.+?)/?$"]);

    return $post_rewrite; 
}

Last step it will be to change the value returned when the code asks for a page permalink (e.g. in menus).
To do that we have to use the page_link filter hook (located in get_page_link() function defined in wp-includes/link-template.php)..

// http://www.example/john-about-me => http://www.example/john/about-me
add_filter('page_link', 'custom_page_link', 99, 3);

function custom_page_link( $link, $ID, $sample ) 
{
    list($author, $slug) = explode("-", basename($link), 2 );

    return ( site_url() . "/" . $author . "/" . $slug  );   
}

..but it won't work if you don't set to false the use_verbose_page_rules property of $wp_rewrite global instance; this will stop parse_request() to check if a "wrong" matched pagepath exixts:

add_action('init', 'disable_verbose_page_rule');

function disable_verbose_page_rule()
{
    global $wp_rewrite;

    $wp_rewrite->use_verbose_page_rules = false;            
}

That's all.. Well, to be honest this is the main part, but it will be some other work to do, like change the rewrite rules also for all the attachment/comments/feed/embed stuff linked to a page and may be something else that I didn't have enough time to discover.

This is my first post; I hope it will help someone, like many others helped me.

发布评论

评论列表(0)

  1. 暂无评论