Last active
December 18, 2015 16:19
-
-
Save AmyStephen/5810668 to your computer and use it in GitHub Desktop.
There are two basic issues with PSR-X. https://github.com/php-fig/fig-standards/blob/master/proposed/autoloader.md Neither one turn out to be a real problem. The first issue is only a perception problem. The second, developers can work around outside of an autoloader, if required.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Problem 1: Problem only of perception or a Programmer Error. | |
// | |
// PSR-X allows the appearance of multiple FQNS to be assigned to a single class file. | |
// People might be confused and incorrectly assume the following is true. | |
// | |
// /path/to/packages/foo-bar/ | |
// src/ | |
// Baz.php # Foo\Bar\Baz | |
// Qux/ | |
// Quux.php # Foo\Bar\Quax\Quux <== this is fantasy | |
// # Corge\Grault\Quux <== this is real | |
// | |
// Quux.php appears to have two *possible* FQNS: but really only has Corge\Grault\Quux | |
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); | |
$loader->addNamespace('Corge\Grault', '/path/to/packages/foo-bar/src/Qux'); | |
// The situation would cause no errors by itself -- only if a developer | |
// used the incorrect namespace in code would it present: | |
$class = '\Foo\Bar\Quax\Qux'; | |
if (class_exists($class)) { | |
// should return false | |
} else { | |
// could return true; | |
} | |
// Will fatal error if the developer uses an incorrect FQNS - just like any other such erroneous use | |
$instance = new $class(); | |
// Why do I call this a programmer error? | |
// | |
// Which of the following is the BEST way to determine what the FQNS really is for a class file? | |
// 1. Look at the Composer.json file? | |
// 2. Apply the namespace of a neighbor file which just so happens to share a containing folder? | |
// 3. Look at the first line at the top of the class file? <== Correct answer. (And correct for PSR-X) | |
// | |
// First, the rules do not create a problem. PSR-X does *not* create multiple FQNS per class file. | |
// The only way a problem would even show up would be if developers used the wrong FQNS in code. | |
// | |
// Nothing in PSR-X says the namespace of the folder defines the class file namespace. | |
// It CAN but it is NOT a rule. People assuming otherwise does not mean the standard is at fault. | |
// | |
// Further, in order for this problem to actually manifest, a developer would have to select the | |
// wrong value to use in their code as the FQNS. That means the developer did not check the | |
// namespace definition within the file. | |
// | |
// For whatever reason, this problem in perception seeems to have people most concerned. | |
// | |
// OPTION 1: DO IT LIKE WE ALWAYS DO IT. LOCK IT DOWN. | |
// | |
// Bear in mind, we know this isn't a real problem but are pursuing the approach of separating namespaces | |
// into different physical folders, for no reason other than the risk that someone might confused. | |
// | |
// That means, PSR-X would include rules like these: | |
// i. Each folder MUST have no more than one namespace prefix assigned to it. | |
// ii. The folder namespace prefix MUST propagate down into the subfolders and ultimately to the class file. | |
// iii. A namespace prefix can only be assigned to a folder, never directly to a file. | |
// | |
// As a result, the folder system in the example has to be redesigned to separate classes into folders by namespace. | |
// As a result the FQNS might have to change (as in this example). | |
// | |
// /path/to/packages/foo-bar/ | |
// src/ | |
// Baz/ | |
// Baz.php # Foo\Bar\Bar\Baz | |
// Qux/ | |
// Quux.php # Corge\Grault\Quux | |
// | |
// Quux.php now not only has one FQNS, but it also appears that way when looking at composer.json and folder contents | |
// | |
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); | |
$loader->addNamespace('Corge\Grault', '/path/to/packages/foo-bar/src/Qux'); | |
// | |
// OPTION 2: BUSINESS AS USUAL WITH ROOM FOR INNOVATION | |
// | |
// Enable autoloaders to continue as they have but stop short of activating hard rules defined above that | |
// would implement unnecessary restrictions and make it more difficult to use PSR-X for resource loading. | |
// | |
// Add a rule like this: | |
// i. Each class file must have a canonical namespace associated with an absolute path that can be used by | |
// the autoloader to identify and include the file. | |
// | |
// This rule would ALLOW autolaoders to use the Solution 1, points i, ii, and iii, without requiring it. | |
// This rule would not couple the logical namespace to a physical folder structure, thus retaining the flexibility. | |
// Features like resource loading and tagging could still be added without BC issues for class loading. | |
// The code examples for both are exactly the same. The only difference is Solution 2 deals with the *perceived problem* | |
// in a way that does not restrict PSR-X flexibility. | |
// | |
// Solution 3: EDUCATION | |
// | |
// As PSR-X rolls out, educate people on how it will be different than PSR-0. | |
// Don't change PSR-X because it is not broken. | |
// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Problem 2: | |
// | |
// Ironically, the second is actually a problem in that currently, it is not possible to use | |
// a PSR-X autoloader in a predicatable way to override files | |
// | |
// For whatever reason, this problem doesn't seem to bother people as much. Most are willing to | |
// pass it off to the autoloader as an implementation issue and not add a rule to prevent failure. | |
// | |
// /path/to/packages/foo-bar/ | |
// override/ | |
// Baz.php # Foo\Bar\Baz | |
// src/ | |
// Baz.php # Foo\Bar\Baz | |
// | |
// PSR-X allows a developer to define the location of an override file | |
// PSR-X does NOT define a rule that requires the autoloader use it. | |
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src'); | |
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/override'); | |
// The error COULD manifest if the autoloader elected to use the first file defined, not the second. | |
// However, the problem MIGHT NOT manifest, if the autoloader selected the override file. | |
// | |
// How to fix it? | |
// | |
// Option 1: Add a rule like this: | |
// i. Autoloaders with addNamespaces methods MUST provide an append option which allows a developer to | |
// position the namespace before namespaces already defined. | |
// | |
// Option 2: Do nothing. | |
// Developers can still work around this by adding an spl_autoload of their own for overrides and | |
// registering with the prepend feature. ANYTHING they define will then be first. | |
// | |
public function registerMyOwnAutoloader() | |
{ | |
spl_autoload_register(array($this, 'loadClass'), true); | |
} | |
// And then use THEIR loader to override the core namespace | |
$loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/override'); | |
// Regardless - this problem can be solved without a rule change. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment