WordPress.org

Make WordPress Core

Opened 4 years ago

Last modified 6 months ago

#12726 accepted enhancement

Add get_post_by_*() functions

Reported by: mikeschinkel Owned by: sorich87
Milestone: Future Release Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch needs-testing
Focuses: Cc:

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 (2)

post.patch (4.6 KB) - added by sorich87 4 years ago.
12726.patch (4.6 KB) - added by Utkarsh 4 years ago.

Download all attachments as: .zip

Change History (13)

comment:1 mikeschinkel4 years ago

  • Keywords post function removed

comment:2 nacin4 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.

comment:3 kevinB4 years ago

  • Cc kevinB added

sorich874 years ago

comment:4 sorich874 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()?

comment:5 sorich874 years ago

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

Related #10865

comment:6 Utkarsh4 years ago

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

Utkarsh4 years ago

comment:7 Utkarsh4 years ago

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

comment:8 WraithKenny17 months ago

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

comment:9 jlambe6 months 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 months ago by jlambe (previous) (diff)

comment:10 ericlewis6 months 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 months ago by ericlewis (previous) (diff)

comment:11 MikeSchinkel6 months 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.

Expect 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.

Note: See TracTickets for help on using tickets.