Auto load of the dependency management tool Composer in PHP)

Source: Internet
Author: User
Tags autoload autoloader hhvm
Composer is a PHP package dependency management tool, similar to RubyGems in Ruby or NPM in Node. it is not official, but is now very popular. This article does not describe how to use Composer, but focuses on its autoload content. For example, if our project wants to use the monolog log tool, we need to tell composer in composer. json that we need it:

{ "require": {  "monolog/monolog": "1.*" }}

Then run:

php composer.phar install

Okay. now the installation is complete. how can I use it? Composer automatically generates an autoload file, you just need to reference it

require '/path/to/vendor/autoload.php';

Then we can easily use third-party class libraries. does it feel great! For the monolog we need, we can use it like this:

use Monolog\Logger;use Monolog\Handler\StreamHandler;// create a log channel$log = new Logger('name');$log->pushHandler(new StreamHandler('/path/to/log/log_name.log', Logger::WARNING));// add records to the log$log->addWarning('Foo');$log->addError('Bar');

In this process, what does Composer do? It generates an autoloader and then automatically loads the package based on its own autoload configuration. (If you do not know much about the content of autoload, read one of my previous articles.
) Let's see how Composer works.

For the automatic loading of third-party packages, Composer provides support in four ways: automatic loading of PSR-0 and PSR-4 (one of my articles has also introduced them ), generate class-map and directly include files.

PSR-4 is a recommended method for composer because it is easier to use and can bring a more concise directory structure. In composer. json, the configuration is as follows:

{  "autoload": {    "psr-4": {      "Foo\\": "src/",    }  }}

The key and value define the namespace and the ing to the corresponding path. According to the PSR-4 rules, when trying to automatically load the class "Foo \ Bar \ Baz", it will look for "src/Bar/Baz. php "file. if it exists, it will be loaded. Note: "Foo \\"
It does not appear in the file path, which is a different point from the PSR-0, if the PSR-0 has this configuration, it will look

"Src/Foo/Bar/Baz. php"

This file.

Also note that in the configuration of the PSR-4 and PSR-0, the namespace separator ending with "Foo \" must be added and escaped to prevent exceptions like "Foo" matching "FooBar.

After the composer is installed or updated, the configuration of the psr-4 is converted to the form of Map with the namespace as the key and the dir path as the value, and written into the generated vendor/composer/autoload_psr4.php file.

{  "autoload": {    "psr-0": {      "Foo\\": "src/",    }  }}

Finally, this configuration is written into the generated

Vendor/composer/autoload_namespaces.php

File.

The Class-map method is to configure the specified directory or file, and then scan the specified directory when Composer is installed or updated. php or. the class in the file ending with inc generates the ing from the class to the specified file path, and adds it to the newly generated file vendor/composer/autoload_classmap.php ,.

{  "autoload": {    "classmap": ["src/", "lib/", "Something.php"]  }}

For example, if src/has a BaseController class, this configuration will be generated in the autoload_classmap.php file:

'Basecontroller' => $ baseDir. '/src/BaseController. php'

Files is manually specified for direct loading. For example, we have a series of global helper functions, which can be put into a helper file and loaded directly.

{  "autoload": {    "files": ["src/MyLibrary/functions.php"]  }}

It will generate an array containing the files specified in these configurations, and then write the newly generated

Vendor/composer/autoload_files.php

File for autoloader to load directly.

Let's take a look at the composer autoload code.

<? Php // autoload_real.php @ generated by Composerclass extends {private static $ loader; public static function loadClassLoader ($ class) {if ('composer \ Autoload \ ClassLoader '===$ class) {require _ DIR __. '/ClassLoader. php ';}} public static function getLoader () {if (null! = Self ::$ loader) {return self: $ loader;} spl_autoload_register (array ('upload', 'loadclassloader '), true, true); self :: $ loader = new \ Composer \ Autoload \ ClassLoader (); spl_autoload_unregister (array ('upload', 'loadclassloader ')); $ vendorDir = dirname (_ DIR _); // The third-party class library provider directory $ baseDir = dirname ($ vendorDir ); // the entire application directory $ includePaths = require _ DIR __. '/include_paths.php'; array_push ($ includePaths, get_include_path (); set_include_path (join (PATH_SEPARATOR, $ includePaths); $ map = require _ DIR __. '/autoload_namespaces.php'; foreach ($ map as $ namespace =>$ path) {$ loader-> set ($ namespace, $ path );} $ map = require _ DIR __. '/autoload_psr4.php'; foreach ($ map as $ namespace => $ path) {$ loader-> setPsr4 ($ namespace, $ path );} $ classMap = require _ DIR __. '/autoload_classmap.php'; if ($ classMap) {$ loader-> addClassMap ($ classMap);} $ loader-> register (true ); $ includeFiles = require _ DIR __. '/autoload_files.php'; foreach ($ your defiles as $ file) {response ($ file);} return $ loader ;}} function compute ($ file) {require $ file ;}

First initialize the ClassLoader class, and then register/directly load the class using the four loading methods mentioned above. some core code of ClassLoader is as follows:

/*** @ Param array $ classMap Class to filename map */public function addClassMap (array $ classMap) {if ($ this-> classMap) {$ this-> classMap = array_merge ($ this-> classMap, $ classMap);} else {$ this-> classMap = $ classMap ;}} /*** Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. ** @ param string $ prefix The prefix * @ param array | string $ Paths The PSR-0 base directories */public function set ($ prefix, $ paths) {if (! $ Prefix) {$ this-> fallbackDirsPsr0 = (array) $ paths;} else {$ this-> prefixesPsr0 [$ prefix [0] [$ prefix] = (array) $ paths;}/*** Registers a set of PSR-4 directories for a given namespace, * replacing any others previusly set for this namespace. ** @ param string $ prefix The prefix/namespace, with trailing '\' * @ param array | string $ paths The PSR-4 base directories ** @ throws \ InvalidArgumentE Xception */public function setPsr4 ($ prefix, $ paths) {if (! $ Prefix) {$ this-> fallbackDirsPsr4 = (array) $ paths;} else {$ length = strlen ($ prefix); if ('\\'! = $ Prefix [$ length-1]) {throw new \ InvalidArgumentException ("A non-empty PSR-4 prefix must end with a namespace separator. ") ;}$ this-> prefixLengthsPsr4 [$ prefix [0] [$ prefix] = $ length; $ this-> prefixDirsPsr4 [$ prefix] = (array) $ paths ;}}/*** Registers this instance as an autoloader. ** @ param bool $ prepend Whether to prepend the autoloader or not */public function register ($ prepend = false) {spl_autoload_register (array ($ this, 'loadclass'), true, $ prepend);}/*** Loads the given class or interface. ** @ param string $ class The name of the class * @ return bool | null True if loaded, null otherwise */public function loadClass ($ class) {if ($ file = $ this-> findFile ($ class) {includeFile ($ file); return true ;}} /*** Finds the path to the file where the class is defined. ** @ param string $ class The name of the class ** @ return string | false The path if found, false otherwise */public function findFile ($ class) {// This is a bug in PHP5.3.0-5.3.2. for details, see https://bugs.php.net/50731 If ('\' = $ class [0]) {$ class = substr ($ class, 1 );} // if (isset ($ this-> classMap [$ class]) in class map mode) {return $ this-> classMap [$ class];} // psr-0/4 ways to find $ file = $ this-> findFileWithExtension ($ class ,'. php '); // Search for Hack files if we are running on HHVM if ($ file === null & defined ('hhvm _ version ')) {$ file = $ this-> findFileWithExtension ($ class ,'. hh ');} if ($ file = null) {// Rememb Er that this class does not exist. return $ this-> classMap [$ class] = false;} return $ file;} private function findFileWithExtension ($ class, $ ext) {// PSR-4 lookup $ logicalPathPsr4 = strtr ($ class, '\', DIRECTORY_SEPARATOR ). $ ext; $ first = $ class [0]; if (isset ($ this-> prefixLengthsPsr4 [$ first]) {foreach ($ this-> prefixLengthsPsr4 [$ first] as $ prefix => $ length) {if (0 = strpos ($ class, $ prefix )) {Foreach ($ this-> prefixDirsPsr4 [$ prefix] as $ dir) {if (file_exists ($ file = $ dir. DIRECTORY_SEPARATOR. substr ($ logicalPathPsr4, $ length) {return $ file ;}}}// PSR-4 fallback dirs foreach ($ this-> fallbackDirsPsr4 as $ dir) {if (file_exists ($ file = $ dir. DIRECTORY_SEPARATOR. $ logicalPathPsr4) {return $ file ;}// PSR-0 lookup if (false! ==$ Pos = strrpos ($ class, '\') {// namespaced class name $ logicalPathPsr0 = substr ($ logicalPathPsr4, 0, $ pos + 1 ). strtr (substr ($ logicalPathPsr4, $ pos + 1), '_', DIRECTORY_SEPARATOR);} else {// PEAR-like class name $ logicalPathPsr0 = strtr ($ class, '_', DIRECTORY_SEPARATOR ). $ ext;} if (isset ($ this-> prefixesPsr0 [$ first]) {foreach ($ this-> prefixesPsr0 [$ first] as $ prefix => $ dirs) {if (0 === strpos ($ class, $ prefix) {foreach ($ dirs as $ dir) {if (file_exists ($ file = $ dir. DIRECTORY_SEPARATOR. $ logicalPathPsr0) {return $ file ;}}}// PSR-0 fallback dirs foreach ($ this-> fallbackDirsPsr0 as $ dir) {if (file_exists ($ file = $ dir. DIRECTORY_SEPARATOR. $ logicalPathPsr0) {return $ file ;}// PSR-0 include paths. if ($ this-> useIncludePath & $ file = stream_resolve_include_path ($ logicalPathPsr0) {return $ file ;}/ *** Scope isolated include. ** Prevents access to $ this/self from specified Ded files. */function includeFile ($ file) {include $ file ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.