WordPress.org

Make WordPress Core

Opened 10 years ago

Last modified 5 months ago

#12726 assigned enhancement

Add get_post_by_*() functions

Reported by: mikeschinkel Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch needs-testing dev-feedback
Focuses: Cc:
PR Number:

Description

Current there are get_page_by_path() and get_page_by_title() function but they hardcode the post_type of 'page'. With support for new custom post types I'm finding a need for functionality to look up posts of custom post types:

$args = array('post_type','my_custom_post_type');
$path = 'foo-bar';
$post = get_post_by_path($path,$args);
$title = 'Foo Bar'
$post = get_post_by_title($title,$args);

Another option would be a simple get_post_by():

$args = array('post_type','my_custom_post_type');
$path = 'foo-bar';
$post = get_post_by('path',$path,$args);
$title = 'Foo Bar'
$post = get_post_by('title',$title,$args);

This code is not hard to write but looking at the functions in post.php there's not one consistent style so I'm not sure what the best approach would be to write it. Further, I don't completely understand the significance of all the code in get_page_by_path() so wouldn't want to start with it (although I could see it being modified to use the more generic functions that I propose.)

I can make these updates if I get enough direction from the core team, or I'd happily just see them get done. :)

Attachments (3)

post.patch (4.6 KB) - added by sorich87 9 years ago.
12726.patch (4.6 KB) - added by Utkarsh 9 years ago.
12726-2.patch (6.4 KB) - added by MikeSchinkel 4 years ago.
Added get_post_by() function, revised for 4.4.0

Download all attachments as: .zip

Change History (16)

#1 @mikeschinkel
10 years ago

  • Keywords post function removed

#2 @nacin
9 years ago

  • Keywords needs-patch added
  • Milestone changed from Unassigned to Future Release

get_post_by() seems like a good idea.

Related, #12727 and #12743.

#3 @kevinB
9 years ago

  • Cc kevinB added

@sorich87
9 years ago

#4 @sorich87
9 years ago

  • Cc sorich87@… added
  • Keywords has-patch added; needs-patch removed

I added a patch which adds get_post_by().
Should we deprecate get_page_by_path(), get_page_by_title()?

#5 @sorich87
9 years ago

  • Owner set to sorich87
  • Status changed from new to accepted

Related #10865

#6 @Utkarsh
9 years ago

  • Cc admin@… added
  • Keywords needs-testing added

@Utkarsh
9 years ago

#7 @Utkarsh
9 years ago

Attached patch fixes a typo, and saves an sql query when $field is name.

#8 @WraithKenny
7 years ago

  • Cc Ken@… added
  • Keywords changed from has-patch, needs-testing to has-patch needs-testing

#9 @jlambe
6 years ago

  • Cc julien@… added

Hi,

what is the difference between this function and using the WP_Query($args) ?

Or maybe we could attach those functions to the WP_Query object and get eveything centralized ? (just a thought)

Last edited 6 years ago by jlambe (previous) (diff)

#10 @ericlewis
6 years ago

get_page_by_path() and get_page_by_title() have both allowed $post_type to be passed as an argument since r13774 and r13899. I don't see a lot of benefit here, as there aren't any other unique identifying fields for posts other than ID and post_name (making get_page_by_title() problematic in my eyes, since it returns the first post with the given title, ignoring multiple posts).

I'd say worksforme here, unless there are some good use cases I'm missing.

Last edited 6 years ago by ericlewis (previous) (diff)

#11 @MikeSchinkel
6 years ago

Replying to ericlewis:

get_page_by_path() and get_page_by_title() have both allowed $post_type to be passed as an argument since r13774 and r13899. I don't see a lot of benefit here, as there aren't any other unique identifying fields for posts other than ID and post_name (making get_page_by_title() problematic in my eyes, since it returns the first post with the given title, ignoring multiple posts).

You make some great points, and 4 years since I posted this ticket I would agree.

Except for two (2) things; one major and the other nice-to-have. Ironically I ran across the former issue within the past month but I'll start with explaining the latter:

  1. get_page_by_path() has semantics for post_type=page so it is harder to discover when people are looking for a get_post_*() function, and confusing for people who do not yet understand that it can be used to access other post types. Offering a get_post_by() would thus clean up the API in that respect and possibly allow for deprecating get_page_by_*() and maybe some other functions.
  1. More importantly there are some things get_page_by_path() just cannot do. It was designed with post_type=page in mind and that's where the problems derive. While there may be other page-specific issues most notably get_page_by_path() cannot lookup a child post if the child post type is different from the parent post type. I could elaborate, but probably best to let code to the talking (see the comments to discover the issues):
/* 
 * To test, place this code in a standalone 
 * .php page on your web server, i.e. /test.php
 */
require( __DIR__ . '/wp-load.php' );
class Limits_of_Get_Page_By_Slug {

  function __construct() {
    add_action( 'init', array( $this, 'init' ) );
  }
  
  function init() {
    /* 
     * Archetype of a defined course, e.g. 'Econ 101'
     */
    register_post_type( 'ex_course', array(
      'label' => 'Courses',
      'public' => true,
    ));
    /* 
     * Specific offerings of a defined course, e.g. 'Econ 101, Spring 2014'
     */
    register_post_type( 'ex_class', array(
      'label' => 'Classes',
      'public' => true,
    ));
  }

   /* 
    * This function exposes the problem with get_post_by_slug().
    */
  function expose() {
    $course_id = get_page_by_path( 'econ-101', OBJECT, 'ex_course' );

    if ( ! $course_id ) {
      $course_id = wp_insert_post( array(
        'post_type'   => 'ex_course',
        'post_title'  => 'Econ 101',
        'post_status'  => 'publish',
      ));
    }
    
    /* 
     * This $class_id will always be null.
     */
    $class_id = get_page_by_path( 'econ-101/spring-2014', OBJECT, 'ex_class' );

    if ( ! $class_id ) {
      /* 
       * So this will always be called and duplicates will be added.
       */
      $class_id = wp_insert_post( array(
        'post_type'   => 'ex_class',
        'post_title'  => 'Spring 2014',
        'post_status'  => 'publish',
        'post_parent' => $course_id,
      ));
    }

    $course = get_post( $course_id );
    $class = get_post( $class_id );

    /* 
     * Every time this is run you get same $course but a different $class.
     */
    echo "Slug is: " . $course->post_name . '/' . $class->post_name;

  }
}
$limits = new Limits_of_Get_Page_By_Slug();
$limits->expose();

So there's no current WordPress API function that allows for a lookup of a child post by slug when the parent post type differs from the child (nope, neither get_children() nor get_page_children() do either.) While it is easy to write a function to do this it's not part of the API so nobody else it using it, there are no standard hooks to allow others to extend it in a common way.

And there may be a better approach than to create get_post_by() but mimimally speaking get_page_by_post() is not sufficient as is.

Last edited 4 years ago by MikeSchinkel (previous) (diff)

#12 @wonderboymusic
5 years ago

  • Owner sorich87 deleted
  • Status changed from accepted to assigned

@MikeSchinkel
4 years ago

Added get_post_by() function, revised for 4.4.0

#13 @MikeSchinkel
4 years ago

  • Keywords dev-feedback added

Revised the patch from Utkarsh that was written 5 years ago.

Added a 'use_like' $arg to allow the use of MySQL WHERE...LIKE for post titles and post names.

Note: See TracTickets for help on using tickets.