Map-based autoloader across php and phar resources

⌈⌋ branch:  Canonic Autoloader


File List

Files of check-in [18e74838b1] in the top-level directory



Canonic Autoloader
------------------

shared.phar is a PHP autoloader for classes and functions. It's map-based
and self-contained in a compressed phar.


 → It scans both .php scripts and .phar collections for class declarations.

 → Honors PHP semantics and avoids plattform ambiguity by interpreting all
   identifiers case-insensitively.

 → Can be updated manually or implicitly (AUTOLOADER_UPDATE env variable).


Usage
-----

Using it is as simple as:

    include("./vendor/shared.phar");

Updating the internal map can be done from the command line:

    php -dphar.readonly=0 ./shared.phar

It's currently best to do so in the main project directory. All scripts
are scanned for class/function/const declarations below its basedir.

There'll be warnings for duplicate declarations.
 → When using the internal tokenizer method, there'll all also be
   warnings for invalidly structured code blocks.
 → The default regex method will merely ignore code nesting errors.

On deployment `shared.phar` can just be copied along with the include
structure (AKA classpath).


Automatic scanning
------------------

For development setups the implicit update is advisable, which kicks in
whenever an unknown class name gets requested. Set it per virtual domain
with:

    SetEnv AUTOLOADER_UPDATE 1

Then adapting phar.readonly=0 in the php.ini is necessary in any case.
(Which was intended as security feature obviously, to eschew manual file
permission management on a per-phar basis.)


Internal structure
------------------

`shared.phar` is a ZIP-based Phar. Its stub contains the autoloader logic,
while the classmap is located in `autoload.map.php` and the update code in
`autoload.update.php`.

Current versions (0.3.x) might be split up, while future versions will drop
that option.


Composer .phars
---------------

You might use https://fossil.include-once.org/xpm/ to convert e.g. composer
bundles into system and .phar packages:

   xpm -s composer --phar -t deb,rpm,phar vnd/pkg

Which then contain a `map` array in the Phar containers meta data. It's
compatible to the shared.phar-internal identifier map, and can easily be
registered (at runtime) using:

   Canonic_Autoloader::addPhar("vnd-pkg.phar");

The same map[] can be crafted into any Phar using the `pharmap.php` tool.


Application advise
------------------

 → Preferrably encode class names *and* filenames in UTF-8.

   PHP 5.x isn't strict about this and literally accepts any character in
   the 0x7F-0xFF range as valid for identifiers. Thus `shared.phar` does not
   enforce anything either.

   It's common sense to use Unicode-valid filenames however WHEN there's a
   need for non-ASCII class names or file names.
   (Prefer plain English though generally for distributable code!)

 → Remove duplicate class declarations. Use a source code versioning system
   instead of leaving edited stubs or old backups in your classpath.

 → Optimize your class dependencies. When using a map-based autoloader,
   there's no need to scatter class declarations across hundreds of separate
   scripts.

 → It runs on PHP 5.3+, albeit PHP 5.2 (which even in 2014 is still used on
   over 20% of webservers) might work too with present PECL Phar extension.


Alternatives
------------

 → [Automap](https://github.com/flaupretre/automap) implements a similar
   map-based approach, also highly compliant to PHP semantics, including
   function and constant declaration lookups.
   The token traversor looks better designed than the one in Canonic_Automap;
   even takes meta definitions into account.
   Implements PHK format support (preceds PHAR packages), which already
   provide meta-bundling and some autoloading support by themselves.

 → [phpab](https://github.com/theseer/Autoload) is another well-designed
   autoload builder. It also doubles as Phar packaging tool for merging
   dependencies into distributable bundles. It's highly configurable (unlike
   shared.phar), therefore allows for more targetted results, and adds more
   robust PHP 5.2 compatibility.
   It's also PHP language compliant per default. (Doesn't yet scan within
   phar packages itself however.)

 → [OPL3/PHARLoader](https://github.com/OPL/opl3-autoloader) provides some
   Phar loading support, but being PSR-0 articled forgos proper identifier
   mapping.