WordPress oddity with broken images (part 2)

Can you tell me your opinion of this, and possibly see if you can recreate it? There are TWO scenarios:

SCENARIO 1 (works as intended)…

Read More

The $post->post_content variable contains this (with a VALID image src):

(string) "before [hw] <img src="/path/to/valid_image.gif" /> after"

This code placed at the top of the theme header.php…

1: echo test_out();
2: 
3: function test_out() {
4:     global $post;
5:     error_log( 'stage_1' );
6:     $str = $post->post_content;
7:     error_log( 'stage_2' );
8:     var_dump( isset( $str ) );
9:     error_log( 'stage_3' );
10:    $str = test_core_wp( 'test_shortcode', $str );
11:    error_log( 'stage_4' );
12:
13:    return $str;
14: }
15:
16: function test_shortcode( $content ) {
17:    return str_replace( '[hw]', 'Hello World!', $content );
18: }
19:
20: function test_core_wp( $function, $a = NULL ) {
21:    $wrap = array ( 'test_shortcode' => 'test_shortcode' );
22:
23:    if ( isset( $a ) ) $args[] = $a;
24:
25:    return call_user_func_array( $wrap[ $function ], $args );
26: }

Outputs this (correctly)…

bool(true)
before Hello World! <img src="/path/to/valid_image.gif" /> after

With this in the PHP log (correctly)…

[22-Jul-2009 11:49:36] stage_1
[22-Jul-2009 11:49:36] stage_2
[22-Jul-2009 11:49:36] stage_3
[22-Jul-2009 11:49:36] stage_4

SCENARIO 2 (where the problem occurs)…

The $post->post_content variable now contains: (with an INVALID image src):

(string) "before [hw] <img src="/path/to/broken_image.gif" /> after"

Outputs this (STILL correctly)…

bool(true)
before Hello World! <img src="/path/to/broken_image.gif" /> after

With this in the PHP log (THIS IS THE PROBLEM)…

[22-Jul-2009 11:56:11] stage_1
[22-Jul-2009 11:56:11] stage_2
[22-Jul-2009 11:56:11] stage_3
[22-Jul-2009 11:56:11] stage_4
[22-Jul-2009 11:56:11] stage_1
[22-Jul-2009 11:56:11] stage_2
[22-Jul-2009 11:56:11] stage_3
[22-Jul-2009 11:56:11] PHP Warning:  Missing argument 1 for test_shortcode() in
/path/to/header.php on line 16
[22-Jul-2009 11:56:11] stage_4

The test-out() function seems to be running itself TWICE, but only when $post->post_content contains a broken image.

FYI, with Firefox you can reload the web page source by hitting CTRL-R. When reloading the source, no problems. However, when reloading the web page in the browser tab (or ANY browser), I get the warning shown above.

I have confirmed the oddity only occurs when there is a broken img src in the variable $post->post_content (or any of the $post variables, for you WordPress gurus).

Any chance you can reproduce this and tell me what you think? I’m new to PHP, but I’m pretty sure something is going on that is way beyond my knowledge. 🙂

EDIT:

I was about to start checking my local dev environment, but a friend wrote me:

After looking at your post, I think I
may have an idea what’s going on.

I had assumed that the warning message
you were talking about was being
displayed in the browser when you
loaded the page in question, but your
post indicates that you’re seeing the
warning message in the PHP log
instead. Is it only appearing in
the PHP log? YES

If that’s so, then consider this
explanation….

In the case where you the post body
contains an tag to a valid
image, then your code is being run
once to generate the page as expected.
The browser sees the rendered page and
then attempts to load the image. The
server finds the image and dishes it
up directly – no surprises here.

In the case where the post body
contains an tag to an invalid
image, then your code is being run
once to generate the page, just as
before. Then the browser makes a
separate HTTP connection to attempt to
load the image. Normally, it would
just trigger a 404 error and the
browser would display a broken image,
end of story. However, if the broken
image URL is to something under your
WordPress installation, then WordPress
overrides the default web server 404
behavior and dishes up a fancy “404
Not Found” page instead of the web
server’s default 404 page. Here’s the
kicker — WordPress’s fancy 404 page
includes the same header and footer as
all the other pages it displays. So
if you have this code at the top of
your header, it’ll get called again by
the 404 page that the web server sends
in response to the missing image your
browser requested from it.

You never actually see the 404 page in
this case, because it’s being
generated in response to an
request, not a page request, so the
browser just treats the response as a
bad image and shows the broken image
icon, but it is actually being
generated and sent.

Compare this (a valid image URL under
a WordPress installation):

http://www.example.com/foo.jpg

to this (an invalid image URL under a
WordPress installation):

http://www.example.com/foo.jpg

Note the custom 404 page including
header that gets returned…?

And… in the context of the 404
page, the $post object doesn’t exist,
so $post->post_content obviously isn’t
a string.

I had assumed that the warning message
was being displayed in the browser on
the original page load, which is why I
didn’t really consider this situation,
but if it’s just being output to your
PHP log, then it makes perfect sense.

And if that is the case, then you can
either ignore the warning as it really
makes no difference, or you can test
for that situation in your code (like
the isset workaround you mentioned
before).

Any other thoughts, let me know, but
that seems to fit with what I know
about it so far.

Related posts

Leave a Reply

2 comments

  1. Is it only appearing in the PHP log?

    Yes.

    OK. Then the custom 404 handler being run on the request for the missing image is almost certainly what is causing the warning. Since the warning’s not being displayed anywhere, it’s safe to ignore, or you can use your isset test if you don’t want it cluttering your log. In any event, it’s really a non-issue, but at least now you know where it was coming from and that it’s not a sign of some real problem.

    I don’t think that (DEV) environment should have anything to do with it at all. It’d behave the same way on a live server with a real DNS entry set up.

  2. I can’t believe I didn’t think of that — DUH!!!! Your friend is 100% correct. It’s firefox loading the broken image, which wordpress is serving, thus running your code twice.