Make WordPress Core

Opened 7 weeks ago

Last modified 5 days ago

#61352 new defect (bug)

PHP deprecation warning in /wp-includes/general-template.php

Reported by: nexbridge's profile nexbridge Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.5.5
Component: General Keywords:
Focuses: Cc:

Description

I'm getting the following warning on what is currently the latest version of WordPress:

PHP Deprecated:  explode(): Passing null to parameter #2 ($string) of type string is deprecated in /wp-includes/general-template.php on line 1425

This is the line in question:

$title_array = apply_filters( 'wp_title_parts', explode( $t_sep, $title ) );

The PHP version is 8.2.

Change History (4)

#1 @Tussendoor
7 weeks ago

We are experiencing the same problem. It occurs on a dynamic post which we are creating on runtime.

Ways to reproduce:

  1. Add a rewrite tag to be able to catch a custom query
    <?php
    add_rewrite_tag('%rewrite_tag_example%', '([^&]+)');
    
  1. Add a rewrite rule for the rewrite tag
    <?php
    add_rewrite_rule('basepage/([^/]*)/?', 'index.php?rewrite_tag_example=$matches[1]', 'top');
    
  1. Register a template with template_include
    <?php
    add_filter('template_include', 'registerFrontendTemplate', 9999);
    
  1. Add the registerFrontendTemplate function with a custom query to dynamically populate a template
    <?php
    /**
     * Register the template file
     *
     * @param string $template
     * @return string
     */
    function registerFrontendTemplate(string $template)
    {
        if (empty(get_query_var('rewrite_tag_example'))) {
            return $template;
        }
    
        // Add custom query here. To get data from a custom database table for 
        // example. Use the custom query variable to get postdata dynamically 
        // based on the request
    
        return locate_template('template/single.php');
    }
    
  1. Refresh the permalinks by navigating to the permalinks settings in the WordPress admin.
  1. Go to the generated frontend page: https:/example.com/basepage/test. With that URL the "rewrite_tag_example" query variable is filled with "test".
  1. On this page the <title> HTML-element will show the deprecation warning. This is because in wp-includes/general-template.php the wp_title function call the single_post_title function via:
    <?php
    // If there is a post.
    if ( is_single() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ) {
        $title = single_post_title( '', false );
    }
    


And the single_post_title function returns null because of:

<?php
if ( ! isset( $_post->post_title ) ) {
   return;
}

Possible solution
We could make the single_post_title function return a string value. But this does not solve the problem for other possible occurances of this error that are possibly triggered by the wp_title function. So that requires changing the functions below to always return a string instead of string|void:

  • single_post_title
  • post_type_archive_title
  • single_term_title
  • single_term_title
  • post_type_archive_title

As the default value of $title is already an empty string (and not null) in the wp_title function we could try this for each occurance of those functions in wp_title:

<?php
// If there is a post.
if ( is_single() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ) {
    $title ??= single_post_title( '', false );
}

The Null Coalescing Assignment operator (??=) does require PHP 7.4 tho.

Hope this helps! :)

#2 follow-up: @michaelreetz
6 weeks ago

Perhaps it would be better to just do the Null coalescing operator inside the explode.

<?php
/**
 * Filters the parts of the page title.
 *
 * @since 4.0.0
 *
 * @param string[] $title_array Array of parts of the page title.
 */
$title_array = apply_filters( 'wp_title_parts', explode( $t_sep, $title ?? '') ); 

This feels to me like what the code would have done in previous versions. And it would be compatible to php7.0.

#3 in reply to: ↑ 2 @Tussendoor
6 weeks ago

Replying to michaelreetz:

Yes that seems like a good approach!

#4 @nexbridge
5 days ago

  • Version changed from 6.5.3 to 6.5.5

Just to say that this is still happening in the latest version (6.5.5). I notice that the ticket status is currently "awaiting review" - how long does it normally take for a ticket to be reviewed?

Note: See TracTickets for help on using tickets.