Make WordPress Core

Opened 2 years ago

Closed 22 months ago

Last modified 22 months ago

#57041 closed enhancement (fixed)

Deprecate `get_page_by_title()` in favour of `WP_Query`

Reported by: peterwilsoncc's profile peterwilsoncc Owned by: peterwilsoncc's profile peterwilsoncc
Milestone: 6.2 Priority: normal
Severity: normal Version: 2.1
Component: Posts, Post Types Keywords: has-patch needs-dev-note
Focuses: Cc:

Description

As an API get_page_by_title() is somewhat problematic in that it can return a post with a post status that may not be visible to the current user, potentially leading to 404.

It is also somewhat flakey in that a change in post title within the admin will potentially break a site using it to return a particular post.

Additionally, the lack of orderby clause results in undefined behavior at a database level: different database engines and versions optimize the query differently and return results using different indexes. (This changed in 6.1 but is likely to be returned in 6.1.1 due to #57039).

I propose the function be deprecated in 6.2 as an API and developers recommended to use WP_Query directly in the event they need to get a post object by title.

Change History (21)

#1 @TimothyBlynJacobs
2 years ago

I agree this would be good to deprecate in 6.2. The WP_Query API is simple enough to use and has all of the configuration flags necessary. This way we can avoid duplicating numerous WP_Query args in the function call in order to accommodate all the different use cases.

If a developer still wants to use a standalone function for this purpose, they can always write their own wrapper that calls WP_Query under the hood.

Additionally, this function is not used in WordPress Core, and has been discouraged by many linting tools as it has been an uncached query previously.

#2 @peterwilsoncc
2 years ago

In 54782:

Posts, Post Types: Revert get_page_by_title()'s use of WP_Query.

Revert to legacy database query in get_pages_by_title(). Due to the lack of orderby clause in the previous database query, it is not possible to gain consistent results by converting the function to a WP_Query wrapper.

Reverts [54271, 54242, 54234].

Props Bjorn2404, 10upsimon, dilipbheda, mukesh27, spacedmonkey, TimothyBlynJacobs, rjasdfiii, stentibbing, pbiron, pento.
Fixes #57039, #56991.
See #57041.

#3 @peterwilsoncc
2 years ago

In 54783:

Posts, Post Types: Revert get_page_by_title()'s use of WP_Query.

Revert to legacy database query in get_pages_by_title(). Due to the lack of orderby clause in the previous database query, it is not possible to gain consistent results by converting the function to a WP_Query wrapper.

Reverts [54271, 54242, 54234].

Props Bjorn2404, 10upsimon, dilipbheda, mukesh27, spacedmonkey, TimothyBlynJacobs, rjasdfiii, stentibbing, pbiron, pento.
Merges [54782] to the 6.1 branch.
Fixes #57039, #56991.
See #57041.

#4 @costdev
23 months ago

  • Version set to 2.1

This ticket was mentioned in Slack in #core by mukeshpanchal27. View the logs.


23 months ago

#6 @mukesh27
23 months ago

  • Keywords reporter-feedback added

This ticket was discussed in the recent bug scrub.

@peterwilsoncc Is there any work remaining for this ticket?

Props to @costdev

#8 @peterwilsoncc
23 months ago

  • Keywords reporter-feedback removed

Yes, this still requires a patch to deprecate the function. I've just linked a pull request.

The function doesn't appear to be tested but I'll wait for the CI to complete to ensure I don't need to add @expectedDeprecated get_page_by_title anywhere.

#9 @peterwilsoncc
22 months ago

  • Owner set to peterwilsoncc
  • Resolution set to fixed
  • Status changed from new to closed

In 55207:

Posts, Post Types: Deprecate get_page_by_title() in favour of WP_Query.

Formally deprecate get_page_by_title(). In its current form the function is unpredictable in that it may return a result that leads to a 404 error and will return different results depending on the database version/engine combination used.

It is recommended developers use WP_Query instead:

$query = new WP_Query(
 array(
  'post_type' => 'page',
  'title'     => 'Sample Page',
 )
);

Props TimothyBlynJacobs, costdev, mukesh27, spacedmonkey, peterwilsoncc.
Fixes #57041.

#11 @afragen
22 months ago

Just an FYI. I use get_page_by_title() in a plugin's constructor. I have changed to the recommended WP_Query call and I get an error that is_user_logged_in() hasn't been defined.

This doesn't seem optimal.

#12 @peterwilsoncc
22 months ago

  • Keywords needs-dev-note added

#13 @peterwilsoncc
22 months ago

@afragen For your plugin, you'll need to hold off until the plugins_loaded hook runs as pluggable functions aren't available until then. This is a part of the issue in which the function could lead to a 404 for some users.

This fact will need to be included in the dev note.

#14 @afragen
22 months ago

Thanks @peterwilsoncc I’ll give that a try.

#15 @afragen
22 months ago

@peterwilsoncc using the plugins_loaded hook works if the user is logged in but doesn’t seem to work if user is not logged in. I’ll need to investigate further.

#16 follow-up: @afragen
22 months ago

@peterwilsoncc here's what I found out. My simple query,

$query             = new WP_Query(
	[
		'post_type' => 'page',
		'title'     => $the_headers_title,
	]
);

returns nothing when there is not logged in user. This is problematic as the plugin works on the frontend. This previously worked with get_page_by_title().

The post in question is a private post.

Last edited 22 months ago by afragen (previous) (diff)

#17 in reply to: ↑ 16 @afragen
22 months ago

Replying to afragen:

@peterwilsoncc here's what I found out. My simple query,

$query             = new WP_Query(
	[
		'post_type' => 'page',
		'title'     => $the_headers_title,
	]
);

returns nothing when there is not logged in user. This is problematic as the plugin works on the frontend. This previously worked with get_page_by_title().

The post in question is a private post.

I think I see a solution.

#18 @afragen
22 months ago

After discussing this with Peter the solution seems to be adding another element to the query. As such the example given to developers should probably be something like the following to account for differences that might occur between get_post_by_title() and using WP_Query.

$query = new WP_Query(
 array(
  'post_type'   => 'page',
  'title'       => 'Sample Page',
  'post_status' => 'all',
 )
);

#19 @milana_cap
22 months ago

@peterwilsoncc, do we have a volunteer to write the Dev note?

#20 follow-up: @peterwilsoncc
22 months ago

@milana_cap I can help with that. I've jotted down some notes but will run it past a couple of people first. Once I have the document closer to it's final form, I'll let you know if it will need a dedicated dev note or can go in the miscellaneous changes note.

#21 in reply to: ↑ 20 @milana_cap
22 months ago

Replying to peterwilsoncc:

@milana_cap I can help with that. I've jotted down some notes but will run it past a couple of people first. Once I have the document closer to it's final form, I'll let you know if it will need a dedicated dev note or can go in the miscellaneous changes note.

Thank you

Note: See TracTickets for help on using tickets.