详解composer自动加载机制
下面由composer教程栏目给大家由浅入深的介绍composer自动加载机制,希望对需要的朋友有所帮助!
前言
由于对于composer自动加载机制的记忆只剩下了"spl_auto???"和"根据命名空间来推导出文件路径"这两个了。。。还是残缺的。。
本想网上收藏一篇详解,奈何,没发现符合我觉得的"由浅入深"文章。
所以有了这篇笔记。
以下知识点即将赶来:
1.了解一下spl_autoload_register
2.composer update发生的故事
3.追踪一下composer的自动加载
正文
1.了解一下spl_autoload_register
首先查一下php官方手册:
(偷懒可以只看红色部分即可)
是不是看着一知半解?
来用白话文来翻译一下:
我们new一个类的话,必须先require或者include类的文件,如果没有加载进来则会报错。这产生一个问题:那这样的话文件的头部到处都是requies和include,明显不符合程序员必须"偷懒"尿性。
为了不需要require或者include类文件也能正常的new一个类,出现了自动加载机制。spl_autoload_register这个函数就专门干这个事的。
从截图得知,此函数有三个参数:
参数 | 详解 |
---|---|
autoload_function | 这里填的是一个***"函数"的名称***,字符串或者数组,这个函数的功能就是把需要new的文件require或者include尽量,避免new的时候报错。简单的说就是要你封装一个***自动加载文件的函数*** |
throw | 当自动加载的函数无法注册的时候,是否抛异常 |
prepend | 是否添加函数到函数队列之首,如果是true则为首,否则尾部 |
来一波代码,印象深刻一些:
//文件 testClass.php ,即将new的类 class TestClass{ public function __construct() { echo '你已经成功new了我了'; } } //文件autoloadDemo.php文件 spl_autoload_register('autoLoad_function', true, true); function autoLoad_function($class_name){ echo "所有的require或者include文件工作都交给我吧!\r\n"; $class_filename = "./{$class_name}.php"; echo "我来加载{$class_filename}文件\r\n"; require_once("./{$class_name}.php"); } $obj_demo = new TestClass();
输出:
所有的require或者include文件工作都交给我吧! 我来加载testClass.php文件 你已经成功new了我了
明白了这个加载的原理,看下文就顺利多了。
2.composer update发生的故事
将自动加载之前,必须要先说一下composer update,这里头承载了自动加载的前提。
composer项目都包含一个composer.json的配置文件。
这里头有一个关键的字段"autoload",包含psr-4和files两个字段。
psr-4:说明是基于psr-4规范的类库,都支持自动加载,只要在后面的对象中以**“命名空间:路径”**的方式写入自己的类库信息即可。
files:这就就更直接了,写入路径就自动加载。
按照以上配置每回composer update之后呢,都会更新一个很重要的文件:./vender/composer/autoload_psr4.php。
这个文件只做了一件事情:把命名空间和文件路径对应起来,这样后续自动加载就有映射根据了。
3.追踪一下composer的自动加载
composer的故事从唯一的一个require说起:
require '../vendor/autoload.php'
这个脚本执行了一个函数:
ComposerAutoloaderInitd9b31141b114fcbee3cf55d0e97b7f87::getLoader()
继续跟getloader函数做了什么?
public static function getLoader() { if (null !== self::$loader) { return self::$loader; } spl_autoload_register(array('ComposerAutoloaderInitd9b31141b114fcbee3cf55d0e97b7f87', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInitd9b31141b114fcbee3cf55d0e97b7f87', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; call_user_func(\Composer\Autoload\ComposerStaticInitd9b31141b114fcbee3cf55d0e97b7f87::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\ComposerStaticInitd9b31141b114fcbee3cf55d0e97b7f87::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { composerRequired9b31141b114fcbee3cf55d0e97b7f87($fileIdentifier, $file); } return $loader; }
这个函数主要做了两件事情:
1.将各种存有命名空间和文件映射关系的文件autoload_xxx.php加载了进来,并作了一些处理(比如:setPsr4将相关映射加载了进去,这个留意下,下文会有呼应。)。
2.注册了函数register
继续跟踪register做了什么:
public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); }
原来调用了spl_autoload_register函数,当类没加载的时候使用loadClass来加载类。(这个前文讲的很清楚了,应该很熟了)
继续跟踪loadClass实现:
public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } }
大概可以看出,是做了文件的include。
继续跟踪下是怎么查找文件的,看findFile函数:
public function findFile($class) { // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { return false; } if (null !== $this->apcuPrefix) { $file = apcu_fetch($this->apcuPrefix.$class, $hit); if ($hit) { return $file; } } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if (false === $file && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if (null !== $this->apcuPrefix) { apcu_add($this->apcuPrefix.$class, $file); } if (false === $file) { // Remember that this class does not exist. $this->missingClasses[$class] = true; } return $file; }
这个函数做了一件事:就是寻找类从上文的autoload_xxx.php初始化的数据中来寻找映射的文件路径。
其中这个函数findFileWithExtension,适用于寻找psr-4规范的文件的映射信息的。
继续跟踪findFileWithExtension:
private function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); $search = $subPath.'\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { if (file_exists($file = $dir . $pathEnd)) { 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; } return false; }
这个函数做了件事:将命名空间\类这样的类名,转换成目录名/类名.php这样的路径,再从前文setPsr4设置的映射信息中寻找映射信息,然后完成返回路径。
至此composer的自动加载机制结束。
Atas ialah kandungan terperinci 详解composer自动加载机制. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Komposer menyediakan ciri lanjutan, termasuk: 1. Alias: tentukan nama yang sesuai untuk pakej untuk rujukan berulang; , kekangan kepuasan dan alias pakej menyelesaikan keperluan berbeza berbilang pakej untuk versi pergantungan yang sama untuk mengelakkan konflik pemasangan.

Jawapan: Perkhidmatan mikro PHP digunakan dengan HelmCharts untuk pembangunan tangkas dan kontena dengan DockerContainer untuk pengasingan dan kebolehskalaan. Penerangan terperinci: Gunakan HelmCharts untuk menggunakan perkhidmatan mikro PHP secara automatik untuk mencapai pembangunan tangkas. Imej Docker membenarkan lelaran pantas dan kawalan versi perkhidmatan mikro. Piawaian DockerContainer mengasingkan perkhidmatan mikro dan Kubernetes mengurus ketersediaan dan kebolehskalaan bekas. Gunakan Prometheus dan Grafana untuk memantau prestasi dan kesihatan perkhidmatan mikro, serta mencipta penggera dan mekanisme pembaikan automatik.

PHPCI/CD ialah amalan utama dalam projek DevOps yang mengautomasikan proses binaan, ujian dan penggunaan, dengan itu meningkatkan kecekapan pembangunan dan kualiti perisian. Saluran paip PHPCI/CD biasa terdiri daripada peringkat berikut: 1) Penyepaduan Berterusan: Setiap kali kod berubah, kod dibina dan diuji secara automatik. 2) Penggunaan berterusan: Mempercepatkan penghantaran dengan menggunakan kod yang diuji dan bersepadu secara automatik ke persekitaran pengeluaran. Dengan melaksanakan saluran paip PHPCI/CD, anda boleh meningkatkan kecekapan pembangunan, meningkatkan kualiti perisian, memendekkan masa untuk memasarkan dan meningkatkan kebolehpercayaan.

Kawalan versi kod PHP: Terdapat dua sistem kawalan versi (VCS) yang biasa digunakan dalam pembangunan PHP: Git: VCS yang diedarkan, tempat pembangun menyimpan salinan asas kod secara setempat untuk memudahkan kerjasama dan kerja luar talian. Subversion: VCS Berpusat, salinan unik pangkalan kod disimpan pada pelayan pusat, memberikan lebih kawalan. VCS membantu pasukan menjejaki perubahan, bekerjasama dan kembali ke versi terdahulu.

Terdapat tiga teknologi utama untuk menggambarkan struktur data dalam PHP: Graphviz: alat sumber terbuka yang boleh mencipta perwakilan grafik seperti carta, graf akiklik terarah dan pepohon keputusan. D3.js: Pustaka JavaScript untuk mencipta visualisasi dipacu data interaktif, menjana HTML dan data daripada PHP, dan kemudian menggambarkannya pada sisi klien menggunakan D3.js. ASCIIFlow: Perpustakaan untuk mencipta perwakilan teks rajah aliran data, sesuai untuk visualisasi proses dan algoritma.

Jawapan: Gunakan PHPCI/CD untuk mencapai lelaran pantas, termasuk menyediakan saluran paip CI/CD, ujian automatik dan proses penggunaan. Sediakan saluran paip CI/CD: Pilih alat CI/CD, konfigurasikan repositori kod dan tentukan saluran paip binaan. Ujian automatik: Tulis ujian unit dan penyepaduan dan gunakan rangka kerja ujian untuk memudahkan ujian. Kes praktikal: Menggunakan TravisCI: Pasang TravisCI, tentukan saluran paip, dayakan saluran paip dan lihat hasilnya. Laksanakan penyampaian berterusan: pilih alatan pengerahan, tentukan saluran paip pengerahan dan automatik penggunaan. Faedah: Meningkatkan kecekapan pembangunan, mengurangkan ralat dan memendekkan masa penghantaran.

Menggunakan cache Redis boleh mengoptimumkan prestasi halaman tatasusunan PHP. Ini boleh dicapai melalui langkah berikut: Pasang klien Redis. Sambung ke pelayan Redis. Cipta data cache dan simpan setiap halaman data ke dalam cincangan Redis dengan kunci "halaman:{page_number}". Dapatkan data daripada cache dan elakkan operasi mahal pada tatasusunan besar.

Komposer menguruskan kebergantungan dengan menggunakan fail composer.lock, yang merekodkan semua kebergantungan yang dipasang dan versi tepatnya, menjadikannya: Memastikan konsistensi dan mengelakkan konflik versi. Tingkatkan prestasi tanpa perlu mencari pakej berulang kali. Jejaki perubahan, merekodkan versi pergantungan yang dipasang selepas setiap arahan pemasangan.
