If you're an advanced developer, then you may want to skip directly to the code.

As soon as you begin working on an advanced plugin or an application in which you try to maintain some form of solid cohesion (or even an API), then you end finding that there’s a function you need that isn’t available in the Codex.

This isn’t unique to WordPress. Any programming language that has a rich API ultimately has a set of solid features that allow you to build upon them to write more power functions.

For me, I try to publish most of my helper functions here on the site. It makes things searchable, available, and even available for code review for the more critical readers :).

Case in point: In a recent project, I needed to find the permalink by slug in WordPress and there wasn’t a function available to do exactly that, so here’s what I ended up doing.

Getting The Permalink By Slug

I’ll discussing the following function in more detail after the code snippet, but the short of it is this:

  • Pass the function the slug of the post
  • Optionally provide post type
  • The function will return said permalink
 * 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 example_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 ) );
	} // end if

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

	return $permalink;

} // end example_get_permalink_by_slug

The code comments should provide as much information as you need, but in order to be as clear as possible, here’s how the function works:

  • After receiving the slug and the optional post type, the function initializes the value that will eventually be returned as the permalink. Initializing it to null makes it easier for external functions to determine if the functioned returned a value or a not.
  • Next, an array of arguments is created and merged with the post type if it’s been specified
  • An instance of WP_Query is initialized and executed. If a result is found, the permalink is returned; otherwise, null is returned.

Simple enough, right?

From an external perspective, you could call this function like this:

if( null != ( $permalink = example_get_permalink_by_slug( 'my-example-slug' ) ) {
   // Do work with $permalink

Or like this:

if( null != ( $permalink = example_get_permalink_by_slug( 'my-example-slug', 'article' ) ) {
   // Do work with $permalink

And that’s all there is to it.


Join the conversation! 10 Comments

  1. Is there a reason you opted not to clone get_page_by_title and change it to a slug? I would think a raw SQL statement would be faster since it’s not calling a full Query. You could then call get_permalink. get_page_by_title already takes a post_type argument even.

    • The above code came largely out of two things:

      1. I usually try to avoid using raw SQL. This is because WP_Query maps to SQL and will likely generate a more optimal query than I’d be able to do ;).
      2. It’s also because of so much stuff that we’ve done with Standard has undergone Automattic’s review and in placed where I did have raw SQL, they’ve asked it to be replaced with WP_Query so it’s become habit.

      All that to say, I think what you’ve mentioned is still a good (and a fast) solution – just a different.

  2. Wouldn’t using get_page_by_path() be enough in that case? For example: http://erikt.tumblr.com/post/278953342/get-a-wordpress-page-id-with-the-slug

    Also I think that wp_reset_postadata() is sufficient enough, no need to call wp_reset_query()

    • wp_reset_postdata() is enough. That was a typo on my part so thanks for pointing it out – fixed that in the post above.

      Also, get_page_by_path is just as useful, but I think that a case can be made for the context of the function in the application. That is, example_get_permalink_by_slug() is what happens to work in the project I’m working on; however, what you’ve provided works just as well – though it’s clear that it’s intended purpose is to get the page ID, rather than the slug.

      That said, it’s definitely possible to use the ID from the slug from your function to grab the permalink.

      Either way, thanks for sharing!

      • Hey,

        Thanks for the fixture.

        I’m not sure what do you mean by ‘. That is, example_get_permalink_by_slug() is what happens to work in the project I’m working on; however, what you’ve provided works just as well – though it’s clear that it’s intended purpose is to get the page ID, rather than the slug.’

        Aren’t you doing the same above? Essentially I’d rather reduce the amount of DB calls and doing a separate query might be less optimized than something built in. I haven’t investigated or debugged the code so I’m not sure about that :P

        Thank you ! Always nice to check out the tips you provide :)

        • All I meant was that when I was building the project and writing the function that needed to return the permalink given a slug, this was the function that I ended up writing.

          Generally speaking, I agree with you – I’m a fan of using what’s built-in and I’m certainly not above refactoring my own code to use what’s more efficient, but I covered here why I used the approach I did.

          If, in fact, using the native methods proved more efficient, then I’d be all for changing it.

          Would be a fun experiment if i can find the time to do it :).

  3. Awesome buddy ! save my time.

  4. I’d note that wp_reset_postdata is always called in this function, even when there is no postdata to reset. Moving it inside the if statement so that it’s only called when the_post is called would improve this function

    • Man, this is an old post. I should seriously refactor some of this code for readability and for standards purposes.

      Regardless, until then, I’ve updated this as per your comment. Thanks Tom!

Leave a Reply