Spooky Action at not so much Distance

Avatar von Martin Brotzeller

Over the weekend i encountered a twist in PHP that really left me wondering. I made a mistake and i thought i should have gotten an error, or at least a warning. I got a completely unexpected behavior instead.

According to our PHP Oracle this is just a legacy from PHP 4 though and there was much Discussion wether changing this behavior would break old apps. I think it’s a possible source of hard-to-track errors though.Consider the following snippet:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
error_reporting(E_ALL);
class a {
public function bar() {
$b = new b();
b::foo("foobar"); // error, this method is not static
}
public function mprint($what) {
echo "not ".$what."\n";
}
}
class b {
public function foo($what) {
$this->mprint($what);
}
public function mprint($what) {
echo $what."\n";
}
}
$a = new a();
$a->bar();
?>
<?php error_reporting(E_ALL); class a { public function bar() { $b = new b(); b::foo("foobar"); // error, this method is not static } public function mprint($what) { echo "not ".$what."\n"; } } class b { public function foo($what) { $this->mprint($what); } public function mprint($what) { echo $what."\n"; } } $a = new a(); $a->bar(); ?>
<?php
error_reporting(E_ALL);
class a {
        public function bar() {
                $b = new b();
                b::foo("foobar"); // error, this method is not static
        }
        public function mprint($what) {
                echo "not ".$what."\n";
        }
}

class b {
        public function foo($what) {
                $this->mprint($what);
        }
        public function mprint($what) {
                echo $what."\n";
        }
}

$a = new a();
$a->bar();
?>

What would one expect? Probably an error, or at least a warning.
What does it do?

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
~> /usr/local/bin/php mytest.php
not foobar
~> /usr/local/bin/php mytest.php not foobar
~> /usr/local/bin/php  mytest.php 
not foobar

What happened? The instance of class a has a reference to $this. Since we do not use $b, $this in method foo() still points to the instance of class a. If class a had no method mprint(), PHP would complain about the missing method. Too bad there is not a not-static keyword.
The aforementioned Oracle told me that this will not work in PHP 6 though, since all methods not declared static are non-static there.

Unsere Data-Webinar-Reihe

Avatar von Martin Brotzeller

Kommentare

3 Antworten zu „Spooky Action at not so much Distance“

  1. According to http://www.php.net/manual/en/language.oop5.static.php

    „Calling non-static methods statically generates an E_STRICT level warning.“

    so if you change the error_reporting line to:

    error_reporting(E_ALL | E_STRICT);

    You get this:

    PHP Strict Standards: Non-static method b::foo() should not be called statically, assuming $this from incompatible context

    Strict Standards: Non-static method b::foo() should not be called statically, assuming $this from incompatible context

    1. Apparently 5.2 does this – i tried that on a 5.1.2 and this does not warn even with E_STRICT. Can’t find it in the changelog though.

  2. Wow, this is ugly. This should not happen, since you make a static call to a method. It’s funny to see that PHP does only trigger a STRICT and not a FATAL, since $this is being used in a static context – which breaks all rules of OOP ;)…
    Anyway – as you said, this belongs to the remains of good old PHP4… *crosses fingers for PHP6 and knocks on wood*

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.