124

Is it possible to get a page's permalink from the slug alone? I'm aware that you can get the page's permalink from the ID using get_page_link():

<a href="<?php echo get_page_link(40); ?>">Map</a>

I'm curious if there is any way to do the same with the slug of a page - like this:

<a href="<?php echo get_page_link('map'); ?>">Map</a>
201

You're talking about Pages right? Not Posts.

Is this what you looking for:

  1. get_permalink( get_page_by_path( 'map' ) )
  2. get_permalink( get_page_by_title( 'Map' ) )
  3. home_url( '/map/' )
| improve this answer | |
  • 4
    Did you mean get_permalink(get_page_by_path('contact')->ID));? – Sampson Dec 7 '10 at 22:22
  • 1
    hmmm nope? What's with the ID? – zeo Dec 8 '10 at 1:52
  • 3
    get_page_by_path() returns an array of all page information. get_permalink() takes a page ID as the first argument. I thought I'd have to explicitly pass the ID value. – Sampson Dec 8 '10 at 4:47
  • 10
    @Jonathan: It's not always documented, but many WP functions accept both numeric ID's and full post objects as the argument. – Jan Fabry Dec 8 '10 at 7:18
  • 1
    It seems that get_page_by_path() can be quite complicated to use when dealing with child pages... – Kaaviar Nov 14 '11 at 14:57
10

I think this could be better:

function get_page_by_slug($page_slug, $output = OBJECT, $post_type = 'page' ) {
    global $wpdb;
    $page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s", $page_slug, $post_type ) );
    if ( $page )
            return get_page($page, $output);
    return null;
}

following the pattern of "original" get_page_by_title of wordpress. (line 3173)

rgds

| improve this answer | |
  • 11
    Why would that be better? Can you explain? – julien_c Apr 11 '12 at 13:11
  • Last comment - I think that sql needs to have one more condition: function get_page_by_slug($page_slug, $output = OBJECT, $post_type = 'page' ) { global $wpdb; $page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s AND post_status = 'publish'", $page_slug, $post_type ) ); if ( $page ) return get_page($page, $output); return null; } – user25790 Jan 9 '13 at 14:27
  • Why? It doesn't generate a complete post object just to get the ID. – s_ha_dum Jan 9 '13 at 14:53
  • @webcitron I think just because is following original pattern of Wordpress getting post by 'title', just changing for 'slug'. (check the link) – Matheus Eduardo May 13 '13 at 11:08
  • This is a good answer. This bypasses the possiblity of a rogue plugin masking your page or incorrectly filtering it. If you return the id from the post table, then you can create an instance of \WP_Post from it, and that resolves directly in all of the wordpress functions that check for other values. \WP_Post also provides methods directly to find most related data about the post. – mopsyd Mar 23 '18 at 3:53
6

This is a method published by Tom McFarlin on his blog:

/**
 * Returns the permalink for a page based on the incoming slug.
 *
 * @param   string  $slug   The slug of the page to which we're going to link.
 * @return  string          The permalink of the page
 * @since   1.0
 */
function wpse_4999_get_permalink_by_slug( $slug, $post_type = '' ) {

    // Initialize the permalink value
    $permalink = null;

    // Build the arguments for WP_Query
    $args = array(
        'name'          => $slug,
        'max_num_posts' => 1
    );

    // If the optional argument is set, add it to the arguments array
    if( '' != $post_type ) {
        $args = array_merge( $args, array( 'post_type' => $post_type ) );
    }

    // Run the query (and reset it)
    $query = new WP_Query( $args );
    if( $query->have_posts() ) {
        $query->the_post();
        $permalink = get_permalink( get_the_ID() );
        wp_reset_postdata();
    }
    return $permalink;
}

It works with custom post types and built-in post types (such as post and page).

| improve this answer | |
2

the accepted answer is wrong because hierarchical pages don't work like that. Simply put, the slug is not always the path of the page or post. E.g. your page has a child etc. the path will be parent-slug/child-slug and get_page_by_path will fail to find child-slug this way. The proper solution is this:

function mycoolprefix_post_by_slug($the_slug, $post_type = "page"){
 $args = array(
   'name'        => $the_slug,
   'post_type'   => $post_type,
   'post_status' => 'publish',
   'numberposts' => 1
 );
 $my_page = get_posts($args)[0];
 return $my_page;
}

<a href="<?php echo mycoolprefix_post_by_slug('map'); ?>">Map</a>
| improve this answer | |
1

Try This:

<a href="<?php echo get_page_link( get_page_by_path( 'map' ) ); ?>">Map</a>

get_page_by_path( 'path' ) returns page/post object which can be then used by get_page_link() as it accepts post/page object and returns permalink.

| improve this answer | |
  • 2
    Please edit your answer, and add an explanation: why could that solve the problem? – fuxia Feb 26 '18 at 13:27
0
    function theme_get_permalink_by_title( $title ) {

    // Initialize the permalink value
    $permalink = null;

    // Try to get the page by the incoming title
    $page = get_page_by_title( strtolower( $title ) );

    // If the page exists, then let's get its permalink
    if( null != $page ) {
        $permalink = get_permalink( $page->ID );
    } // end if

    return $permalink;

} // end theme_get_permalink_by_title

Use this function by

if( null == theme_get_permalink_by_title( 'Register For This Site' ) ) {
  // The permalink doesn't exist, so handle this however you best see fit.
} else {
  // The page exists, so do what you need to do.
} // end if/else
| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.