For example, assuming that 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.*"
}
}
After execution:
PHP Composer.phar Install
OK, now the installation is finished, how to use it? Composer automatically generates a AutoLoad file, you just have to reference it
Require '/path/to/vendor/autoload.php ';
Then it is very convenient to use the third party's class library, it is not very good ah! For the monolog we need, we can use 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 ');
What did composer do in the process? It generates a autoloader, and then builds on each package's own autoload configuration, which helps us automate the loading process. (If you don't know this part of the autoload, you can look at one of my previous articles.)
Next, let's see how composer does it.
For automatic loading of third-party packages, composer provides support in four ways, the automatic loading of PSR-0 and PSR-4 (which I have described in an article), the generation of Class-map, and the way in which files are directly contained.
PSR-4 is a recommended way for composer, because it is easier to use and leads to a more concise directory structure. This is configured in the Composer.json:
{"
AutoLoad": {"psr-4": {"
foo\\": "src/",
}
}}
Key and value define the namespace and the mapping to the corresponding path. In accordance with PSR-4 's rules, when attempting to automatically load the class "Foo\\bar\\baz", the file is searched for "src/bar/baz.php", which is loaded if it exists. Note that "foo\\"
Does not appear in the file path, which is different from the PSR-0, if the PSR-0 has this configuration, then will go to find
"Src/foo/bar/baz.php"
This file.
Also note in the configuration of PSR-4 and PSR-0, the namespace delimiter at the end of "foo\\" must be added and escaped to prevent an unexpected occurrence of "Foo" matching to "FooBar".
After the composer is installed or updated, the psr-4 configuration is converted to the form of a map namespace Key,dir path and written to the generated vendor/composer/autoload_psr4.php file.
{"
AutoLoad": {"psr-0": {"
foo\\": "src/",
}
}}
Finally, this configuration is also written as a map to the generated
vendor/composer/autoload_namespaces.php
Documents.
Class-map by configuring the specified directory or file, and then when installing or updating composer, it scans the class in the specified directory for files in. php or. Inc, generating the mapping of class to the specified file path, and adding the newly generated vendor/composer/autoload_classmap.php file,.
{
"AutoLoad": {"
classmap": ["src/", "lib/", "something.php"]
}
}
For example, there is a Basecontroller class under src/, in which case the configuration is generated in the autoload_classmap.php file:
' Basecontroller ' => $baseDir. '/src/basecontroller.php '
The files method is to manually specify a file for direct loading. For example, we have a series of global helper functions that can be put into a helper file and loaded directly.
{
' autoload ': {'
files ': [' src/mylibrary/functions.php ']
}
}
It generates an array containing the files specified in these configurations, and then writes the newly generated
vendor/composer/autoload_files.php
File for Autoloader to load directly.
Let's look at the code for composer AutoLoad.
<?php//autoload_real.php @generated by Composer class Composerautoloaderinit73612b48e6c3d0de8d56e03dece61d11 {pri
vate static $loader; public static function Loadclassloader ($class) {if (' composer\autoload\classloader ' = = = $class) {require __dir__.
'/classloader.php ';
The public static function Getloader () {if (Null!== self:: $loader) {return self:: $loader; } spl_autoload_register (Array (' Composerautoloaderinit73612b48e6c3d0de8d56e03dece61d11 ', ' LoadClassLoader '), True,
true);
Self:: $loader = $loader = new \composer\autoload\classloader ();
Spl_autoload_unregister (Array (' Composerautoloaderinit73612b48e6c3d0de8d56e03dece61d11 ', ' LoadClassLoader ')); $vendorDir = DirName (__dir__); Verdor 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 ($includeFiles as $file) {composerrequire73612b48e6c3d0de8d56e03dece61d11 ($file);
return $loader;
} function Composerrequire73612b48e6c3d0de8d56e03dece61d11 ($file) {require $file;}
The
Initializes the ClassLoader class first and then registers/loads directly with the 4 loading methods mentioned above, ClassLoader some of the core code for the following:
/** * @param array $classMap Class to filename map */Public Function Addclassmap (array $classMap) {if ($this-&G
T;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 PR
Efix. * * @param string $prefix the prefix * @param array|string $paths the PSR-0 base directories/Public function SE
T ($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 no others previously set for this
Namespace. * * @param string $prefix The Prefix/namespace, with trailing ' \ ' * @param array|string $paths the PSR-4 base Direct Ories * * @throws \invalidargumentexception/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 Nam
Espace separator. ");}
$this->prefixlengthspsr4[$prefix [0]][$prefix] = $length;
$this->prefixdirspsr4[$prefix] = (array) $paths;
}/** * Registers this instance as a autoloader.
* @param bool $prepend Whether to prepend the autoloader or not/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 functio
n 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 */PU
Blic 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);
}//class map method lookup if (isset ($this->classmap[$class)) {return $this->classmap[$class];
//PSR-0/4 way 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) {//Remember that this class does not exist.
return $this->classmap[$class] = false;
return $file; Private Function Findfilewithextension ($class, $ext) {//PSR-4 lookup $LOGICALPATHPSR 4 = STRTR ($class, ' \ \ ', DIRE Ctory_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 ($LOGICALPATHPSR 4, $length))) {return $file; }}///PSR-4 fallback dirs foreach ($this->fallbackdirspsr4 as $dir) {if file_exists ($file = $dir. Directory_separator.
$LOGICALPATHPSR 4)) {return $file; }//PSR-0 lookup if (false!== $pos = Strrpos ($class, ' \ \)) {//namespaced class name $LOGICALPATHPSR 0 = SUBSTR ($LOGICALPATHPSR 4, 0, $pos + 1).
STRTR (substr ($LOGICALPATHPSR 4, $pos + 1), ' _ ', directory_separator);
else {//Pear-like class name $LOGICALPATHPSR 0 = 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.
$LOGICALPATHPSR 0)) {return $file; }}///PSR-0 fallback dirs foreach ($this->fallbackdirspsr0 as $dir) {if file_exists ($file = $dir. Directory_separator.
$LOGICALPATHPSR 0)) {return $file;
}//PSR-0 include paths.
if ($this->useincludepath && $file = Stream_resolve_include_path ($LOGICALPATHPSR 0)) {return $file;
}/** * Scope isolated include.
* Prevents access to $this/self from included files.
*/function Includefile ($file) {include $file;}