Skip to content

Instantly share code, notes, and snippets.

@requinix
Last active August 29, 2015 14:10
Show Gist options
  • Save requinix/c3a576a5a8953d26da02 to your computer and use it in GitHub Desktop.
Save requinix/c3a576a5a8953d26da02 to your computer and use it in GitHub Desktop.
Treatise on PHP bug #68485

As written before this is a breach.

And as I've said, it is not and you are misunderstanding.

in my example at runtime the instance is in \Beta namespace and this namespace and it's class should be used.

The code that is looking for $Value is in the Alpha namespace. It's that simple.

So currently you're fixated on the term "current namespace". Let me demonstrate what that value is:

<?php

namespace Alpha;

// for everything in here the current namespace is Alpha

namespace Beta;

// for everything in here the current namespace is Beta

?>

When you execute \Beta\Base::Write() the current namespace is Beta (because you're still under the effect of the "namespace Beta;"). That means you could write that same line as "Base::Write()" if you wanted and get the same effect - as a demonstration of how the unqualified name ("Base") gets resolved according to the current namespace ("Beta").

\Beta\Base::Write gets its code inherited from \Alpha\Base. That does NOT mean the code is as if it had been copied and pasted,

class Base extends \Alpha\Base {

	public static function Write() {
		echo Helper::$Value;
	}

}

but that \Beta\Base will automatically invoke \Alpha\Base's Write() method. Due to LSB some things will still "refer" to \Beta\Base (get_called_class() and static::) but pretty much everything else executes the way it normally would.

Now \Alpha\Base::Write() is being executed. It is under the effect of the "namespace Alpha;" because that is where the code is written, so the current namespace is Alpha. The fact that \Beta\Base invoked the code means nothing regarding the namespace. The namespace is not "reverse inherited" or whatever you might want to call that behavior. Short of get_called_class() or a backtrace, \Alpha\Base knows nothing of the Beta namespace nor that it even exists. The Beta namespace has absolutely no effect on any code in Alpha, nor vice versa.

The current namespace works like __FILE__ and __CLASS__ and the other magic constants: it doesn't matter what you did before or what code is calling what or when, their values depend literally on where the code is written.

Here's me trying another tactic: imagine if this namespace inheritance or whatever actually was the case. It is not. But I'm going to pretend for a second that it is.

https://gist.github.com/requinix/57f5fe27945ee5ae8324

That code is correct and runs correctly in every version of PHP since namespaces were introduced.

http://3v4l.org/QmbLJ

With your scheme the code would break in many ways:

  • Can't use the div/lshift/rshift operator because the global namespace (where the call to ::calculate() is made) does not have a MoreOperators class defined.
  • Can't use the basic operators because neither the global namespace nor the MoreMath namespace has the AddOperator or MultiplyOperator classes.

How could I, as the developer, fix that? Maybe I could import every single class that code uses,

use Math\AddOperator;
use Math\MultiplyOperator;
use MoreMath\MoreOperators;

echo MoreMath\BetterCalculator::calculate("+", 1, 2); // 3

If that worked (I'm not sure if your logic would allow it) it's ridiculous because I would have to be aware of every single class that code uses. If the code adds another basic operator, like ** pow, then every. single. place. that uses it would break until it imported the (eg) Math\PowOperator class.

More likely I would rewrite my code to always use fully-qualified names.

https://gist.github.com/requinix/1375e605838e67dde10f

That sucks. Imagine having to type out the namespace name every single time you wanted to reference a class - even in the same namespace as your code. Why even bother with namespaces at all? They would cause more headaches than they're worth.

So it's a good thing it doesn't work that way. Which, to reiterate, it does not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment