名词解释
- 语言结构&函数
- 语言结构:就是php语言的关键词,语言语法的一部分;它不可以被用户定义或者添加到语言扩展或者库中;它可以有也可以没有变量和返回值。
- 函数:由代码块组成的,可以复用。从源码的角度来说,也就是基于Zend引擎的基础来实现的,ext拓展库中的函数都是这样实现的
- 区别
- 语言结构比对应功能的函数快
- 语言结构在错误处理上比较鲁棒,由于是语言关键词,所以不具备再处理的环节
- 语言结构不能在配置项(php.ini)中禁用,函数则可以。
- 语言结构不能被用做回调函数
- 语言结构为什么比函数快?
原因是在PHP中,函数都要先被PHP解析器(Zend引擎)分解成语言结构,所以有此可见,函数比语言结构多了一层解析器解析。这样就能比较好的理解,什么语言结构比函数快了。
- 如何判断是不是语言结构呢?
通过function_exists判断,如果是函数会返回true
$a = [ 'echo', 'print', 'die', 'isset', 'unset', 'include', 'require', 'array', 'list', 'empty', 'include_once', 'require_once', 'array_merge', 'is_null', 'empty', 'function_exists', 'defined', 'define', 'if', 'for', 'foreach',];foreach ($a as $b) { echo "$b: " . intval(function_exists($b)) . PHP_EOL;}
- 如何在php.ini中禁用函数?
在php.ini有一个配置为disable_functions,只要填写想要禁用的函数(逗号分隔),就能够禁用了
disable_functions = array_merge,echo
var_dump(json_encode(new stdClass()));var_dump(array_merge([2], [1]));echo 123 . PHP_EOL;
例子
例子可以参考我的git:https://github.com/JACKCHEN213/php_class_load/tree/master
手动引入
require
引入一个外部文件
引入顺序
- 使用
require "xxx.php";require("yyy.php");
- 引入说明
require是一个语言结构,并且支持这两种调用方式
测试
引入不存在的文件
注意如果文件无法访问, include 和 require 在分别发出最后的 E_WARNING 或 E_ERROR 之前,都会发出额外一条 E_WARNING。
<?phprequire "9——9.txt";echo 1;
- 忽略错误执行
@require "9——9.txt";echo 1;
重复引入
function test(){ echo 1;}
require '1.php';require '1.php';test();
- 要怎么才能够实现重复引入呢?
- 修改1.php就行了
if (!function_exists('test')) { function test() { echo 1; }}
require支持重复引入,但函数不支持重复定义
引入存在相同函数
require '2.php';require '3.php';echo 111 . PHP_EOL;
function test(){ echo 2;}
function test(){ echo 3;}
require_once
require_once 表达式和 require 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。
测试
引入不存在的文件
require_once 'xxxxx.yyyy';echo 111 . PHP_EOL;
报错,忽略错误直接结束
重复引入
function test(){ echo 1;}
require_once '1.php';require_once '1.php';test();
include
require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误。换句话说将导致脚本中止而 include 只产生警告(E_WARNING),脚本会继续运行。
测试
引入错误
@include 'xxxxx.yyyy';echo 111 . PHP_EOL;
引入错误,并调用目标文件的函数
<?php@include 'xxxxx.yyyy';test();echo 111 . PHP_EOL;
include_once
同include与require_once
自动引入
多个同名类、函数怎么区分调用?
问题
ehigh@ubuntu:autoload$ tree.├── 1.php├── 2.php├── 3.php└── 4.php
- 1.php
include_once "2.php";include_once "3.php";include_once "4.php";test();
- 2,3,4.php
function test(){ echo __FUNCTION__ . PHP_EOL;}
名字空间——namespace
- 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
用法
namespace top_name\second_name\...\last_name;
示例1
namespace t1 { function test() { echo __FUNCTION__ . PHP_EOL; }}namespace test { function test() { echo __FUNCTION__ . PHP_EOL; }}namespace test\test { function test() { echo __FUNCTION__ . PHP_EOL; }}// 多个namespace,顶级namespace这么用namespace { \t1\test(); // t1\test \test\test(); // test\test \test\test\test(); // test\test\test}
示例2
ehigh@ubuntu:autoload$ tree.├── 1.php├── 2.php├── 3.php└── 4.php
namespace test;function test(){ echo __FUNCTION__ . PHP_EOL;}
namespace t1;function test(){ echo __FUNCTION__ . PHP_EOL;}
namespace test\t1;function test(){ echo __FUNCTION__ . PHP_EOL;}
include_once "2.php";include_once "3.php";include_once "4.php";\test\test();\t1\test();\test\t1\test();test();
use
引入命名空间下的文件,use与require和include是不相同的,使用use的前提是文件已经包含进当前文件。
用法
类: use namespace\class;函数: use function namespache\function;常量: use const namespace\function;
示例1
namespace t1 { function test() { echo __FUNCTION__ . PHP_EOL; }}namespace test { function test() { echo __FUNCTION__ . PHP_EOL; }}namespace test\test { function test() { echo __FUNCTION__ . PHP_EOL; }}// 多个namespace,顶级namespace这么用namespace { use function t1\test as t1; use function test\test as t2; use function test\test\test as t3; t1(); // t1\test t2(); // test\test t3(); // test\test\test}
示例2
include_once "2.php";include_once "3.php";include_once "4.php";use function t1\test as t2;use function test\t1\test as t3;use function test\test as t1;t1(); // test\testt2(); // t1\testt3(); // test\t1\test
类的自动加载
现在我们可以使用namespace和use来区分类、函数、常量了,但是我们要将目标文件引入才能使用。单靠use不能将目标类导入,那么有什么办法可以不用引入(require)使用的文件呢?
php提供__autoload魔术函数和spl_autoload_register函数来实现类自动加载。
__autoload
用法
__autoload(string $class): void
示例1
ehigh@ubuntu:autoload$ tree.├── handle│ └── entry.php├── redis│ └── redis.php└── index.php
- redis.php
namespace redis\redis;class RedisConn{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- entry.php
namespace handle\entry;use redis\redis\RedisConn;class Entry{ public function __construct() { echo __METHOD__ . PHP_EOL; new RedisConn(); }}
- index.php
use handle\entry\Entry;function __autoload($class){ $classmap = [ "redis\\redis\\RedisConn" => __DIR__ . "/redis/redis.php", "handle\\entry\\Entry" => __DIR__ . "/handle/entry.php", ]; if (isset($classmap[$class]) && is_file($classmap[$class])) { require_once $classmap[$class]; } else { throw new Exception("Class not found: " . $class); }}$r = new Entry();
spl_autoload_register
spl_autoload_register — 注册给定的函数作为 __autoload 的实现
用法
spl_autoload_register(callable $autoload_function = ?, bool $throw = true, bool $prepend = false): bool
示例1
use handle\entry\Entry;spl_autoload_register(function ($class) { $classmap = [ "redis\\redis\\RedisConn" => __DIR__ . "/redis/redis.php", "handle\\entry\\Entry" => __DIR__ . "/handle/entry.php", ]; if (isset($classmap[$class]) && is_file($classmap[$class])) { require_once $classmap[$class]; } else { throw new Exception("Class not found: " . $class); }});new Entry();
示例2
use handle\entry\Entry;function load_entry(){ require_once "handle/entry.php";}function load_redis(){ require_once "redis/redis.php";}spl_autoload_register('load_redis');spl_autoload_register('load_entry');new Entry()
常量和函数的自动加载?
在上面,我们通过__autoload和spl_autoload_register来加载类,其中使用了namespace和use。
在第二节中,我们知道namespace可以用来修饰常量和函数,那么我们能不能使用__autoload和spl_autoload_register来加载呢?
示例1
namespace test;echo __FILE__ . PHP_EOL;function test(){ echo __FUNCTION__ . PHP_EOL;}const NAME = 'JackC';class Student{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
use test\Student;use function test\test;use const test\NAME;function load($class){ require_once "2.php";}spl_autoload_register('load');test();new Student();var_dump(NAME);
常量和函数写为类的静态属性和静态方法!
使用了类自动加载,use了相应类,类对应文件是否被引入了?
示例1
use handle\entry\Entry;use redis\redis\RedisConn;function load_entry(){ require_once "handle/entry.php";}function load_redis(){ require_once "redis/redis.php";}spl_autoload_register('load_redis');spl_autoload_register('load_entry');new RedisConn();var_dump(get_included_files());
类的自动加载是动态的!
composer引入
Composer 是 PHP 的一个依赖管理工具。它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们。
使用composer创建一个项目
mkdir test && cd testcomposer init
ehigh@ubuntu:test$ composer init Welcome to the Composer config generator This command will guide you through creating your composer.json config.Package name (<vendor>/<name>) [ehigh/test]: jackc/testDescription []: 测试项目Author [chenchao <1366294101@qq.com>, n to skip]: Minimum Stability []: 1Invalid minimum stability "1". Must be empty or one of: stable, RC, beta, alpha, devMinimum Stability []: devPackage Type (e.g. library, project, metapackage, composer-plugin) []: projectLicense []: xxx-xxx-xxxDefine your dependencies.Would you like to define your dependencies (require) interactively [yes]? Search for a package: thans/tp-jwt-authEnter the version constraint to require (or leave blank to use the latest version): 1.2.1Search for a package: Would you like to define your dev dependencies (require-dev) interactively [yes]? Search for a package: topthink/think-swooleEnter the version constraint to require (or leave blank to use the latest version): 4.0.7Search for a package: Add PSR-4 autoload mapping? Maps namespace "Jackc\Test" to the entered relative path. [src/, n to skip]: { "name": "jackc/test", "description": "测试项目", "type": "project", "require": { "thans/tp-jwt-auth": "1.2.1" }, "require-dev": { "topthink/think-swoole": "4.0.7" }, "license": "xxx-xxx-xxx", "autoload": { "psr-4": { "Jackc\\Test\\": "src/" } }, "authors": [ { "name": "chenchao", "email": "1366294101@qq.com" } ], "minimum-stability": "dev"}Do you confirm generation [yes]? Would you like to install dependencies now [yes]? Loading composer repositories with package informationInfo from https://repo.packagist.org: #StandWithUkraineUpdating dependenciesLock file operations: 22 installs, 0 updates, 0 removals - Locking league/flysystem (1.x-dev 094defd) - Locking league/flysystem-cached-adapter (1.1.0) - Locking league/mime-type-detection (1.11.0) - Locking nette/php-generator (v3.6.x-dev 9073c8a) - Locking nette/utils (v3.2.x-dev 02a54c4) - Locking open-smf/connection-pool (v1.0.16) - Locking psr/cache (1.0.1) - Locking psr/container (1.x-dev 513e066) - Locking psr/http-message (dev-master efd67d1) - Locking psr/log (1.1.4) - Locking psr/simple-cache (1.0.1) - Locking qeq66/jwt (3.3.x-dev bd2fa6c) - Locking stechstudio/backoff (1.2) - Locking swoole/ide-helper (4.8.x-dev afe3a09) - Locking symfony/deprecation-contracts (2.5.x-dev e8b495e) - Locking symfony/finder (5.4.x-dev 7872a66) - Locking symfony/polyfill-php80 (dev-main cfa0ae9) - Locking thans/tp-jwt-auth (v1.2.1) - Locking topthink/framework (6.0.x-dev 4c328dc) - Locking topthink/think-helper (v3.1.6) - Locking topthink/think-orm (2.0.x-dev d86a204) - Locking topthink/think-swoole (v4.0.7)Writing lock fileInstalling dependencies from lock file (including require-dev)Package operations: 22 installs, 0 updates, 0 removals - Downloading psr/cache (1.0.1) - Downloading league/mime-type-detection (1.11.0) - Downloading league/flysystem (1.x-dev 094defd) - Downloading league/flysystem-cached-adapter (1.1.0) - Downloading nette/utils (v3.2.x-dev 02a54c4) - Downloading psr/container (1.x-dev 513e066) - Downloading psr/http-message (dev-master efd67d1) - Downloading symfony/deprecation-contracts (2.5.x-dev e8b495e) - Downloading symfony/polyfill-php80 (dev-main cfa0ae9) - Downloading topthink/think-helper (v3.1.6) - Downloading psr/simple-cache (1.0.1) - Downloading topthink/think-orm (2.0.x-dev d86a204) - Downloading topthink/framework (6.0.x-dev 4c328dc) - Downloading qeq66/jwt (3.3.x-dev bd2fa6c) - Downloading thans/tp-jwt-auth (v1.2.1) - Downloading symfony/finder (5.4.x-dev 7872a66) - Downloading swoole/ide-helper (4.8.x-dev afe3a09) - Downloading stechstudio/backoff (1.2) - Downloading open-smf/connection-pool (v1.0.16) - Downloading nette/php-generator (v3.6.x-dev 9073c8a) - Downloading topthink/think-swoole (v4.0.7) - Installing psr/cache (1.0.1): Extracting archive - Installing league/mime-type-detection (1.11.0): Extracting archive - Installing league/flysystem (1.x-dev 094defd): Extracting archive - Installing league/flysystem-cached-adapter (1.1.0): Extracting archive - Installing nette/utils (v3.2.x-dev 02a54c4): Extracting archive - Installing psr/container (1.x-dev 513e066): Extracting archive - Installing psr/http-message (dev-master efd67d1): Extracting archive - Installing symfony/deprecation-contracts (2.5.x-dev e8b495e): Extracting archive - Installing symfony/polyfill-php80 (dev-main cfa0ae9): Extracting archive - Installing topthink/think-helper (v3.1.6): Extracting archive - Installing psr/simple-cache (1.0.1): Extracting archive - Installing psr/log (1.1.4): Extracting archive - Installing topthink/think-orm (2.0.x-dev d86a204): Extracting archive - Installing topthink/framework (6.0.x-dev 4c328dc): Extracting archive - Installing qeq66/jwt (3.3.x-dev bd2fa6c): Extracting archive - Installing thans/tp-jwt-auth (v1.2.1): Extracting archive - Installing symfony/finder (5.4.x-dev 7872a66): Extracting archive - Installing swoole/ide-helper (4.8.x-dev afe3a09): Extracting archive - Installing stechstudio/backoff (1.2): Extracting archive - Installing open-smf/connection-pool (v1.0.16): Extracting archive - Installing nette/php-generator (v3.6.x-dev 9073c8a): Extracting archive - Installing topthink/think-swoole (v4.0.7): Extracting archive12 package suggestions were added by new dependencies, use `composer suggest` to see details.Generating autoload files6 packages you are using are looking for funding.Use the `composer fund` command to find out more!PSR-4 autoloading configured. Use "namespace Jackc\Test;" in src/Include the Composer autoloader with: require 'vendor/autoload.php';
require & require-dev
require中的依赖是开发环境和生产环境都会使用的;require-dev中的依赖只会在开发环境中使用。
composer require --dev 表示将所要安装的依赖名放在"require-dev"下。composer install no-dev 表示只安装"require"中的依赖。
自动加载方式
PSR-0
已弃用- 自 2014 年 10 月 21 日起,PSR-0 已被标记为已弃用。现在推荐PSR-4作为替代方案。
[1] 命名空间必须与绝对路径一致
[2] 类名首字母必须大写
[3 ]除去入口文件外,其他“.php”必须只有一个类
[4] php类文件必须自动载入,不采用include等
[5] 单一入口
composer使用psr-0加载类
与psr-4不用的是,使用psr-0加载类的命名空间不用指定最外层目录的名字空间,见下例子
- 文件目录
.├── composer.json├── composer.lock├── index.php├── sdk│ └── DB│ ├── MySQL.php│ ├── Redis.php│ └── test│ └── Test.php└── src
- composer.json
{ "name": "jackc/test", "description": "测试项目", "type": "project", "require": { "thans/tp-jwt-auth": "1.2.1" }, "require-dev": { "topthink/think-swoole": "4.0.7" }, "license": "xxx-xxx-xxx", "autoload": { "psr-0": { "DB\\": "sdk/" } }, "authors": [ { "name": "chenchao", "email": "1366294101@qq.com" } ], "minimum-stability": "dev"}
- MySQL.php
namespace DB;class MySQL{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- Redis.php
namespace DB;class Redis{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- Test.php
namespace DB\test;class Test{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- index.php
require_once "vendor/autoload.php";use DB\Redis;use DB\MySQL;use DB\test\Test;new Redis();new MySQL();new Test();
- composer
# 只修改了自动加载规则composer update# 其他依赖没安装(vendor目录不存在)composer install
- vendor/composer/autoload_namespaces.php
// autoload_namespaces.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array( 'DB\\' => array($baseDir . '/sdk'),);
问题:在sdk根目录下的类要怎么加载?
//
PSR-4
PSR-4和PSR-0最大的区别是对下划线(underscore)的定义不同。PSR-4中,在类名中使用下划线没有任何特殊含义。而PSR-0则规定类名中的下划线_会被转化成目录分隔符。
composer使用psr-4引入类
使用上面的项目,在src下面天机哎测试用例
src├── driver│ ├── Rar.php│ ├── SevenZ.php│ └── Zip.php└── Extractor.php
- composer.json
{ "name": "jackc/test", "description": "测试项目", "type": "project", "require": { "thans/tp-jwt-auth": "1.2.1" }, "require-dev": { "topthink/think-swoole": "4.0.7" }, "license": "xxx-xxx-xxx", "autoload": { "psr-0": { "DB\\": "sdk/" }, "psr-4": { "src\\": "src/" } }, "authors": [ { "name": "chenchao", "email": "1366294101@qq.com" } ], "minimum-stability": "dev"}
- Rar.php,SevenZ.php,Zip.php
namespace src\driver;class SevenZ{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- index.php
require_once "vendor/autoload.php";use src\Extractor;new Extractor();
- composer
composer update
- vendor/composer/autoload_psr4.php
// autoload_psr4.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array( 'think\\swoole\\' => array($vendorDir . '/topthink/think-swoole/src'), 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src'), 'thans\\jwt\\' => array($vendorDir . '/thans/tp-jwt-auth/src'), 'src\\' => array($baseDir . '/src'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Smf\\ConnectionPool\\' => array($vendorDir . '/open-smf/connection-pool/src'), 'STS\\Backoff\\' => array($vendorDir . '/stechstudio/backoff/src'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'), 'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'), 'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'), 'Lcobucci\\JWT\\' => array($vendorDir . '/qeq66/jwt/src'),);
classmap
将指定目录下的类加载到顶级命名空间下
使用
还是复用上面的项目,添加了一个lib目录,目录下有一个车俩的类
ehigh@ubuntu:test$ tree liblib└── Car.php
- composer.json
{ "name": "jackc/test", "description": "测试项目", "type": "project", "require": { "thans/tp-jwt-auth": "1.2.1" }, "require-dev": { "topthink/think-swoole": "4.0.7" }, "license": "xxx-xxx-xxx", "autoload": { "psr-0": { "DB\\": "sdk/" }, "psr-4": { "src\\": "src/" }, "classmap": ["lib"] }, "authors": [ { "name": "chenchao", "email": "1366294101@qq.com" } ], "minimum-stability": "dev"}
- Car.php
<?phpclass Car{ public function __construct() { echo __METHOD__ . PHP_EOL; }}
- index.php
require_once "vendor/autoload.php";new \Car();
- composer
composer update
- vendot/composer/autoload_classmap.php
// autoload_classmap.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array( 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Car' => $baseDir . '/lib/Car.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\HtmlStringable' => $vendorDir . '/nette/utils/src/HtmlStringable.php', 'Nette\\IOException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\InvalidArgumentException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\InvalidStateException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\Iterators\\CachingIterator' => $vendorDir . '/nette/utils/src/Iterators/CachingIterator.php', 'Nette\\Iterators\\Mapper' => $vendorDir . '/nette/utils/src/Iterators/Mapper.php', 'Nette\\Localization\\ITranslator' => $vendorDir . '/nette/utils/src/compatibility.php', 'Nette\\Localization\\Translator' => $vendorDir . '/nette/utils/src/Translator.php', 'Nette\\MemberAccessException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\NotImplementedException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\NotSupportedException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\OutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\PhpGenerator\\Attribute' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Attribute.php', 'Nette\\PhpGenerator\\ClassType' => $vendorDir . '/nette/php-generator/src/PhpGenerator/ClassType.php', 'Nette\\PhpGenerator\\Closure' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Closure.php', 'Nette\\PhpGenerator\\Constant' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Constant.php', 'Nette\\PhpGenerator\\Dumper' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Dumper.php', 'Nette\\PhpGenerator\\EnumCase' => $vendorDir . '/nette/php-generator/src/PhpGenerator/EnumCase.php', 'Nette\\PhpGenerator\\Extractor' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Extractor.php', 'Nette\\PhpGenerator\\Factory' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Factory.php', 'Nette\\PhpGenerator\\GlobalFunction' => $vendorDir . '/nette/php-generator/src/PhpGenerator/GlobalFunction.php', 'Nette\\PhpGenerator\\Helpers' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Helpers.php', 'Nette\\PhpGenerator\\Literal' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Literal.php', 'Nette\\PhpGenerator\\Method' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Method.php', 'Nette\\PhpGenerator\\Parameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Parameter.php', 'Nette\\PhpGenerator\\PhpFile' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpFile.php', 'Nette\\PhpGenerator\\PhpLiteral' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpLiteral.php', 'Nette\\PhpGenerator\\PhpNamespace' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PhpNamespace.php', 'Nette\\PhpGenerator\\Printer' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Printer.php', 'Nette\\PhpGenerator\\PromotedParameter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PromotedParameter.php', 'Nette\\PhpGenerator\\Property' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Property.php', 'Nette\\PhpGenerator\\PsrPrinter' => $vendorDir . '/nette/php-generator/src/PhpGenerator/PsrPrinter.php', 'Nette\\PhpGenerator\\TraitUse' => $vendorDir . '/nette/php-generator/src/PhpGenerator/TraitUse.php', 'Nette\\PhpGenerator\\Traits\\AttributeAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php', 'Nette\\PhpGenerator\\Traits\\CommentAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php', 'Nette\\PhpGenerator\\Traits\\FunctionLike' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php', 'Nette\\PhpGenerator\\Traits\\NameAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/NameAware.php', 'Nette\\PhpGenerator\\Traits\\VisibilityAware' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php', 'Nette\\PhpGenerator\\Type' => $vendorDir . '/nette/php-generator/src/PhpGenerator/Type.php', 'Nette\\SmartObject' => $vendorDir . '/nette/utils/src/SmartObject.php', 'Nette\\StaticClass' => $vendorDir . '/nette/utils/src/StaticClass.php', 'Nette\\UnexpectedValueException' => $vendorDir . '/nette/utils/src/exceptions.php', 'Nette\\Utils\\ArrayHash' => $vendorDir . '/nette/utils/src/Utils/ArrayHash.php', 'Nette\\Utils\\ArrayList' => $vendorDir . '/nette/utils/src/Utils/ArrayList.php', 'Nette\\Utils\\Arrays' => $vendorDir . '/nette/utils/src/Utils/Arrays.php', 'Nette\\Utils\\AssertionException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php', 'Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php', 'Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php', 'Nette\\Utils\\Floats' => $vendorDir . '/nette/utils/src/Utils/Floats.php', 'Nette\\Utils\\Helpers' => $vendorDir . '/nette/utils/src/Utils/Helpers.php', 'Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php', 'Nette\\Utils\\IHtmlString' => $vendorDir . '/nette/utils/src/compatibility.php', 'Nette\\Utils\\Image' => $vendorDir . '/nette/utils/src/Utils/Image.php', 'Nette\\Utils\\ImageException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Json' => $vendorDir . '/nette/utils/src/Utils/Json.php', 'Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\ObjectHelpers' => $vendorDir . '/nette/utils/src/Utils/ObjectHelpers.php', 'Nette\\Utils\\ObjectMixin' => $vendorDir . '/nette/utils/src/Utils/ObjectMixin.php', 'Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php', 'Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php', 'Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php', 'Nette\\Utils\\RegexpException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Strings' => $vendorDir . '/nette/utils/src/Utils/Strings.php', 'Nette\\Utils\\Type' => $vendorDir . '/nette/utils/src/Utils/Type.php', 'Nette\\Utils\\UnknownImageFileException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php', 'Nette\\Utils\\Validators' => $vendorDir . '/nette/utils/src/Utils/Validators.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',);
目录存在同名类,怎么处理?
- 不在同一个目录下
- 同一个目录下存在同名类
3. 结论
存在多个同名类,只会导入一个类,加载规则是: 1. 不存在目录,加载第一个文件的类 2. 存在目录,加载第一个目录最深的级的类
files
指定文件导入
使用
复用上面的项目,添加了common目录,添加了person类
- composer.json
{ "name": "jackc/test", "description": "测试项目", "type": "project", "require": { }, "require-dev": { }, "license": "xxx-xxx-xxx", "autoload": { "psr-0": { "DB\\": "sdk/" }, "psr-4": { "src\\": "src/" }, "classmap": ["lib"], "files": ["common/Person.php"] }, "authors": [ { "name": "chenchao", "email": "1366294101@qq.com" } ], "minimum-stability": "dev"}
- Person.php
class Person{ public function __construct() { echo __FILE__ . ' --- ' . __METHOD__ . PHP_EOL; }}
- index.php
require_once "vendor/autoload.php";new Person();
- composer
composer update
- vendor/composer/autoload_files.php
// autoload_files.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array( '34e6717e4080f708d812ed7cb7d8586c' => $baseDir . '/common/Person.php',);
引入的文件存在同名类怎么处理?
- vendor/composer/autoload_files.php
// autoload_files.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array( '34e6717e4080f708d812ed7cb7d8586c' => $baseDir . '/common/Person.php', '7677e46b6e54f2c15468e2eafd3c16ac' => $baseDir . '/common/test/Person.php',);
- 结论
composer会引入,但运行会报错
测试项目
composer文件说明
- autoload_classmap.php
classmap映射加载的类
- autoload_files.php
files定义的文件
- autoload_namespaces.php
psr-0定义的命名空间
- autoload_psr4.php
psr-4定义的名字空间
- autoload_real.php
框架加载类的入口文件
// autoload_real.php @generated by Composerclass ComposerAutoloaderInitaffaa1fd2638648a4ae4ee9274a5741d{ 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('ComposerAutoloaderInitaffaa1fd2638648a4ae4ee9274a5741d', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); spl_autoload_unregister(array('ComposerAutoloaderInitaffaa1fd2638648a4ae4ee9274a5741d', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::getInitializer($loader)); } else { $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); if ($useStaticLoader) { $includeFiles = Composer\Autoload\ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { composerRequireaffaa1fd2638648a4ae4ee9274a5741d($fileIdentifier, $file); } return $loader; }}function composerRequireaffaa1fd2638648a4ae4ee9274a5741d($fileIdentifier, $file){ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; require $file; }}
- vendor/autoload.php
// autoload.php @generated by Composerrequire_once __DIR__ . '/composer/autoload_real.php';return ComposerAutoloaderInitaffaa1fd2638648a4ae4ee9274a5741d::getLoader();
- autoload_static.php
autoload_classmap.php、autoload_namespace.php、autoload_psr4.php、autoload_file.php的总和
// autoload_static.php @generated by Composernamespace Composer\Autoload;class ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d{ public static $files = array ( '34e6717e4080f708d812ed7cb7d8586c' => __DIR__ . '/../..' . '/common/Person.php', '7677e46b6e54f2c15468e2eafd3c16ac' => __DIR__ . '/../..' . '/common/test/Person.php', ); public static $prefixLengthsPsr4 = array ( 's' => array ( 'src\\' => 4, ), ); public static $prefixDirsPsr4 = array ( 'src\\' => array ( 0 => __DIR__ . '/../..' . '/src', ), ); public static $prefixesPsr0 = array ( 'D' => array ( 'DB\\' => array ( 0 => __DIR__ . '/../..' . '/sdk', ), ), ); public static $classMap = array ( 'Car' => __DIR__ . '/../..' . '/lib/test/test1/Apple.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::$prefixDirsPsr4; $loader->prefixesPsr0 = ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::$prefixesPsr0; $loader->classMap = ComposerStaticInitaffaa1fd2638648a4ae4ee9274a5741d::$classMap; }, null, ClassLoader::class); }}
建议
- PHP工程项目使用composer进行管理
- 不要去修改依赖库的代码
- 类的引入方式采用PSR-4规范
- …
来源地址:https://blog.csdn.net/qq_41105107/article/details/127065985