Make WordPress Core

Opened 7 months ago

Closed 7 months ago

Last modified 7 months ago

#53474 closed defect (bug) (fixed)

Improve Walker compatibility with PHP8

Reported by: sunxiyuan Owned by: SergeyBiryukov
Milestone: 5.8 Priority: normal
Severity: major Version: 5.8
Component: General Keywords: has-patch php8
Focuses: Cc:


PHP 8 introduced a new numeric and string comparison mechanism
For the following code:

0 == '';

True under PHP 7 and False under PHP 8.

There is the following statement in line 345 of the Walker class (wp-includes/class-wp-walker.php):

if ( 0 == $e->$parent_field ) {

If $e->$parent_field is an empty string, the judgment result of the statement in PHP 7 and PHP 8 will be inconsistent.

The question broke the reply order of my bbPress forum.

The offending code should be changed to:

if ( 0 == (int) $e->$parent_field ) {

Change History (7)

This ticket was mentioned in PR #1407 on WordPress/wordpress-develop by sunxiyuan.

7 months ago

  • Keywords has-patch added

#2 @SergeyBiryukov
7 months ago

  • Keywords php8 added

#3 @SergeyBiryukov
7 months ago

  • Milestone changed from Awaiting Review to 5.8
  • Owner set to SergeyBiryukov
  • Status changed from new to reviewing

#4 @SergeyBiryukov
7 months ago

Hi there, welcome to WordPress Trac! Thanks for the ticket and the patch.

I think we can use an empty() check here, for consistency with the change to the ::walk() method in [35876].

There are three similar instances of these checks in a few methods:

  • WP_Walker::walk()
  • WP_Walker::paged_walk()
  • WP_Walker::get_number_of_root_elements()

It looks like [35876] only fixed the first instance because the Menus screen only used the ::walk() method, and the other two methods can currently still throw a PHP notice if a non-existing property is checked. So using empty() in all the three places would fix that in the other two methods too, as well as the issue reported here.

I'll commit the change shortly, which also includes a unit test @aristath and I worked on.

#5 @SergeyBiryukov
7 months ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 51204:

Code Modernization: Use a consistent check for parent items in WP_Walker.

This affects the ::walk(), ::paged_walk(), and ::get_number_of_root_elements() methods.

PHP 8 changes the way string to number comparisons are performed: https://wiki.php.net/rfc/string_to_number_comparison

In particular, checking if an empty string is equal to zero in PHP 8 evaluates to false, not true.

For the WP_Walker class, this resulted in an incorrect handling of parent items in a few methods.

By explicitly checking for an empty() value instead, we make sure the check works as expected in PHP 8 and earlier versions.

Follow-up to [35876], [48960], [49043], [49076].

Props sunxiyuan, aristath, SergeyBiryukov.
Fixes #53474.

#6 @sunxiyuan
7 months ago

empty() is indeed a better choice

Note: See TracTickets for help on using tickets.