Opened 18 months ago
Closed 7 days ago
#61352 closed defect (bug) (fixed)
PHP deprecation notice in wp_title()
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 6.9 | Priority: | normal |
| Severity: | normal | Version: | 6.5.5 |
| Component: | Themes | Keywords: | has-patch 2nd-opinion |
| 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.
Attachments (1)
Change History (41)
#2
follow-up:
↓ 3
@
18 months 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
@
18 months ago
Replying to michaelreetz:
Yes that seems like a good approach!
#4
@
16 months 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?
#5
@
16 months ago
Just to say that this is still happening in 6.6.1, however the line number has now changed to 1440.
#6
@
16 months ago
- Keywords has-patch added
I've now added a patch as per the suggestion by @michaelreetz.
#7
@
13 months ago
Same here.
The problem occurs at least in my case when on custom route where there is no "title" parameter as it is on default WP views.
WP Version 6.6.2
#8
@
12 months ago
Still happening in 6.7.
When will this fix be applied ? This error is kind of annoying.
This ticket was mentioned in Slack in #core by sirlouen. View the logs.
7 months ago
#12
follow-up:
↓ 13
@
7 months ago
@sabernhardt
Setting a static blog page leaving the homepage set to --select-- instantly creates the issue and is easier to reproduce the issue than by recoding or adding code as mentioned above as "steps to recreate it".
I wonder why resolving this issue in the core code takes that long (more than 11 months) as the fix is easy and simple to apply and would have saved me a lot of time today.
Any theme using the wptitle function with a static blog page trigger the deprecated message.
Thank you
#13
in reply to:
↑ 12
@
7 months ago
Replying to neo2k23:
I wonder why resolving this issue in the core code takes that long (more than 11 months) as the fix is easy and simple to apply and would have saved me a lot of time today.
Long story short
This ticket was mentioned in PR #8729 on WordPress/wordpress-develop by @dhruvang21.
7 months ago
#15
- Keywords needs-refresh removed
#16
@
7 months ago
- Milestone changed from Awaiting Review to 6.9
PR 8729 removes the deprecation notice and passes the GitHub tests.
I'll also suggest an alternative in case it might be better:
// If there is a post.
if ( is_single() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ) {
$title = single_post_title( '', false );
if ( empty( $title ) ) {
$title = '';
}
}
#17
@
7 months ago
@sabernhardt This is all about wordpress being php compatible. Why checking for a empty($title) in above code as the cause of the problem is the filter with the explode call in general-template.php on line 1439.
The only logical fix would be checking $title before the filter is called or in that explode call on line 1439 and if $title is empty make sure its a empty string.
There are many cases why one can land on that line with $title == null.
The given solution in https://core.trac.wordpress.org/attachment/ticket/61352/general-template.diff
requires at least php 7.4 and i am not sure if the latest minimum requirement for php in wordpress already has been set to 7.4 or still is on 7.2
https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/
#18
@
7 months ago
- Summary changed from PHP deprecation warning in /wp-includes/general-template.php to PHP deprecation notice in wp_title()
My alternative suggestion, whether it includes empty() or null === $title, would only be a good idea if some situation should give an error (that is, if it ever indicates doing something wrong). I did not create a patch because I am not convinced my direction is better than PR 8729.
If this function's deprecation notice should be silenced in all cases,
wp_resolve_block_style_variation_ref_values() already established a precedent with
explode( '.', $value['ref'] ?? '' ) and comment:2 says that syntax is compatible with PHP 7.0.
#19
@
7 months ago
@sabernhardt you are right it was introduced in php 7.0 https://www.php.net/manual/en/migration70.new-features.php
I doubt if one is interested in false doing it wrongs which also could be the case and as we have now when f.e. one sets a static blog page.
I rather see it silenced for all than getting these false incorrect deprecated messages. Moreover even if the title is empty the correct one is still presented after the filter has ran. Which was the case with the static blog page.
#20
@
3 months ago
Bug Report
Description
✅ This report validates whether the issue can be reproduced, and whether the indicated patch works as expected.
[26-Aug-2025 17:50:04 UTC] PHP Deprecated: explode(): Passing null to parameter #2 ($string) of type string is deprecated in /var/www/src/wp-includes/general-template.php on line 1439
Patch Tested : https://github.com/WordPress/wordpress-develop/pull/8729
Environment
- WordPress: 6.9-alpha-60093-src
- PHP: 8.2.29
- Server: nginx/1.29.1
- Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
- Browser: Firefox 142.0
- OS: Linux
- Theme: Twenty Twenty 2.9
- MU Plugins: None activated
- Plugins:
- Test Reports 1.2.0
- WP 61352 Repro 1.0
Actual Results
- ✅ Error condition occurs (reproduced).
- ✅ Issue resolved with patch.
Additional Notes
- I tried it with twentytwenty theme, by explictly adding
<title><?php wp_title(); ?></title>in theheader.phpfile. The bug was successfully reproduced.
This ticket was mentioned in Slack in #core-test by nimeshatxecurify. View the logs.
3 months ago
#23
@
3 weeks ago
@sabernhardt I notice you've changed the milestone from 6.9 to Future Release - does that mean it's not going to be fixed in 6.9?
#24
@
3 weeks ago
@sabernhardt Why is this put on a waiting list for a future fix? The fix is pretty easy to apply and not very difficult? I am confused about the why! It is already been open for 17 months? What is keeping you from fixing this? Please advice. Thank you
This ticket was mentioned in Slack in #core by sabernhardt. View the logs.
2 weeks ago
#26
@
2 weeks ago
- Owner set to joedolson
- Status changed from new to accepted
@nexbridge and @neo2k23 Please don't blame @sabernhardt! Stephen does not have commit access to WordPress core, and cannot fix the issue directly. As @SirLouen mentioned, the volume of reports is vastly higher than the capacity to actually resolve them.
I'm looking at this, and will see whether it's viable to get it in at this point.
#27
@
2 weeks ago
@joedolson i am not blaming anybody. I was just wondering why it was put on the long run. Btw may i ask why if one can not change the core code why he can change the milestone?
I thank you for your reply and efford to check if it can be resolved sooner.
#28
@
2 weeks ago
There are many different roles here; one very important role is what we call a "bug gardener", which is somebody who helps make decisions about what milestone a ticket is going to target. They can place tickets in a milestone, and that helps inform committers what is seen as more important or higher priority so that we can assess what's going to happen.
And the deadline for getting this into WordPress 6.9 is getting very close, so Stephen made a practical call that given that nobody had taken ownership of this ticket, it was not likely to go in. And, honestly, if he hadn't done that, it's very possible that nobody would have noticed the ticket. I only noticed it because he mentioned having closed it in the dev Slack.
This is still potentially true. I've taken ownership, but I have several other tickets to shepherd through in the remaining time for this release, and I cannot guarantee getting this done.
#31
follow-up:
↓ 33
@
2 weeks ago
- Resolution fixed deleted
- Status changed from closed to reopened
Using empty() in [61108] is not ideal.
$title is a string, so this can instead be simplified to a string comparison '' !== $title, saving internal variable type checks.
(For the case where it's not a string explode() would otherwise also throw a warning or error.)
In addition, this could lead to the valid title "0" (a string with a zero) to be treated in the wrong way.
See [60726] for a similar change.
#32
@
2 weeks ago
- Keywords commit removed
The $title variable is not always a string because single_post_title() can return void. That is why the deprecation notice can show.
Another possibility is to check if is_string( $title ) before running explode() in wp_title(). After determining that the type is a string, it could also check '' !== $title to skip the explode() function for untitled posts.
Note: The wp_get_document_title() function, which is used by most themes created in the last ten years instead of wp_title(), does not support a post title of '0'. The 0 simply would not appear in the <title> tag. If the slug is also 0, then example.org/0/ matches the is_home() conditional and displays the blogroll instead of the desired post.
#33
in reply to:
↑ 31
@
2 weeks ago
Replying to TobiasBg:
Using
empty()in [61108] is not ideal.
$titleis a string, so this can instead be simplified to a string comparison'' !== $title, saving internal variable type checks.
Afaik, null is not ''. If $title is empty, it doesn't trigger the deprecated notice, only if $title is null. With a empty check, you solve both cases.
On the other hand, is_string as @sabernhardt suggests does the trick, but from my perspective, is less readable than empty for what we are trying to signal here (not null ideally, and preferably not empty string).
I would suggest to leave this fixed.
#34
@
2 weeks ago
Ah, I had overlooked the null part of the ticket, and thought that this is only about the '' being passed to explode(). Thanks for pointing this out!
Nevertheless, empty() is still not ideal, and there are a few nice articles about this:
https://localheinz.com/articles/2023/05/10/avoiding-empty-in-php/
https://dev.to/klnjmm/never-use-empty-function-in-php-4pb0
https://www.beberlei.de/post/when_to_use_empty_in_php_i_say_never
Of course, empty() does work here and there are many many places in Core where it's used like that, but I think for new code, stricter checks are beneficial.
In this case, instead of my suggestion from above, a check like
if ( ! is_string( $title ) ) {
$title = '';
}
(above the apply_filters from [61108]) would be worthwhile, I think.
Then, the explode() would always work on a string, and it would return the expected output of an array with an empty string.
#35
@
2 weeks ago
Checking ! is_string() has advantages in that it will also guard against other non-string types, should the value be passed as an array or object. That seems improbable, but it's hypothetically possible.
The current case would cause problems in the relatively obscure case that the title of a page is 0. It's unlikely, but it is possible and I can think of legitimate use cases for it. I don't think it's urgent to make this decision for the next beta, but should be resolved before RC.
#36
@
11 days ago
- Keywords needs-patch added; has-patch removed
Since the RC1 release is imminent, I would like to check the status of this ticket.
- Is [61108] still okay as it was shipped in 6.9?
- A new patch is needed.
This ticket was mentioned in PR #10494 on WordPress/wordpress-develop by @sabernhardt.
9 days ago
#37
- Keywords has-patch added; needs-patch removed
Checks whether $title is a string and then checks whether it equals an empty string before adding the separator.
#38
@
9 days ago
- Keywords 2nd-opinion added
wp_title() already used ! empty() in line 1428 to determine whether it should add a separator. In the case of the 0 post title, unless you use a filter, WordPress 6.8 would create a <title> like this:
<title>0Site Title</title>
If it is worth changing in one part of the function, it should be changed in both places.
#39
@
8 days ago
I think that this makes sense. This value really shouldn't ever be anything other than a string; even if it is numeric, the variable type should be string. This change just makes sure of this.
I wonder a little whether we should cast numerics to strings, in case somebody somewhere is passing a float or int to this. But if they're returning a non-string on a filter that expects a string return, then that's really just _doing_it_wrong(). Technically, the case we're handling is already doing it wrong, by not returning or returning null, though, so it seems reasonale to also handle other related cases.
The problem with explode is really that it errors if the value passed is null or not stringy. If we're protected against passing any non-string values, then it can just be exploded.

We are experiencing the same problem. It occurs on a dynamic post which we are creating on runtime.
Ways to reproduce:
And the single_post_title function returns null because of:
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:
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:
The Null Coalescing Assignment operator (??=) does require PHP 7.4 tho.
Hope this helps! :)