关于php中的spl_autoload_register,splautoloadregister_PHP教程
关于php中的spl_autoload_register,splautoloadregister
一、自动加载定义
很多开发者写面向对象的应用程序时对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本开头写一个长长的包含文件列表(每个类一个文件)。
在 PHP 5 中,不再需要这样了。可以定义一个 __autoload() 函数,它会在试图使用尚未被定义的类时自动调用。通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类
__autoload 是一个魔术方法, 尝试加载未定义的类,spl_autoload_register - 注册给定的函数作为 __autoload 的实现
<p class="para"><span class="function"><span class="tip"><span class="tip">Tip</span></span></span></p> <p class="para"><span class="function">spl_autoload_register() 提供了一种更加灵活的方式来实现类的自动加载。因此,不再建议使用 <span class="function">__autoload()函数,在以后的版本中它可能被弃用。</span></span></p>
Note:
在 5.3.0 版之前,__autoload 函数抛出的异常不能被 catch 语句块捕获并会导致一个致命错误。从 5.3.0+ 之后,__autoload 函数抛出的异常可以被 catch 语句块捕获,但需要遵循一个条件。如果抛出的是一个自定义异常,那么必须存在相应的自定义异常类。__autoload 函数可以递归的自动加载自定义异常类。
Note:
自动加载不可用于 PHP 的 CLI 交互模式。
Note:
如果类名比如被用于 call_user_func(),则它可能包含一些危险的字符,比如 ../。 建议您在这样的函数中不要使用用户的输入,起码需要在 __autoload() 时验证下输入
二、spl_autoload_register
目录
classes --+ + mail.class.php + norman.class.php + db.class.php登入後複製1、Single Autoloads
<?php /*** nullify any existing autoloads ***/ spl_autoload_register(null, false); /*** specify extensions that may be loaded ***/ spl_autoload_extensions('.php, .class.php'); /*** class Loader ***/ function classLoader($class) { $filename = strtolower($class) . '.class.php'; $file ='classes/' . $filename; if (!file_exists($file)) { return false; } include $file; } /*** register the loader functions ***/ spl_autoload_register('classLoader'); /*** a new instance if norman ***/ $norman = new norman; /*** make norman do something ***/ $norman->do_something(); ?>登入後複製2、Mulitple Autoloads
<?php /*** nullify any existing autoloads ***/ spl_autoload_register(null, false); /*** specify extensions that may be loaded ***/ spl_autoload_extensions('.php, .class.php, .lib.php'); /*** class Loader ***/ function classLoader($class) { $filename = strtolower($class) . '.class.php'; $file ='classes/' . $filename; if (!file_exists($file)) { return false; } include $file; } function libLoader($class) { $filename = strtolower($class) . '.lib.php'; $file ='libs/' . $filename; if (!file_exists($file)) { return false; } include $file; } /*** register the loader functions ***/ spl_autoload_register('classLoader'); spl_autoload_register('libLoader'); /*** a new instance of norman ***/ $norman = new norman; /*** make norman do some thing ***/ $norman->do_something();登入後複製3、Interfaces
接口文件
<?php /* * icontroller.class.php * interface to ensure all classes have an index method * */ interface iController { public function index(); } ?>登入後複製autoload文件
<?php /*** nullify any existing autoloads ***/ spl_autoload_register(null, false); /*** specify extensions that may be loaded ***/ spl_autoload_extensions('.php, .class.php'); /*** class Loader ***/ function classLoader($class) { $filename = strtolower($class) . '.class.php'; $file ='classes/' . $filename; if (!file_exists($file)) { return false; } include $file; } /*** register the loader functions ***/ spl_autoload_register('classLoader'); class blog implements iController { public function index() { echo 'hello from the index'; } } /*** a new blog instance ***/ $blog = new blog; /*** run the index method ***/ $blog->index(); ?>登入後複製4、一个标准的示例
spl_autoload_register( 'autoload' ); /** * autoload * * @author testdd * @param string $class * @param string $dir * @return bool */ function autoload( $class, $dir = null ) { if ( is_null( $dir ) ) $dir = '/path/to/project'; foreach ( scandir( $dir ) as $file ) { // directory? if ( is_dir( $dir.$file ) && substr( $file, 0, 1 ) !== '.' ) autoload( $class, $dir.$file.'/' ); // php file? if ( substr( $file, 0, 2 ) !== '._' && preg_match( "/.php$/i" , $file ) ) { // filename matches class? if ( str_replace( '.php', '', $file ) == $class || str_replace( '.class.php', '', $file ) == $class ) { include $dir . $file; } } } }登入後複製5、框架中的写法
<?php /** * Autoloader * @author Jianxiang Qin <TalkativeDoggy@gmail.com> * @license http://opensource.org/licenses/BSD-3-Clause New BSD License * @version svn:$Id$ * @package Lotusphp\Autoloader */ /** * 自动加载类和函数 * * 按需加载类,每次只加载用到的类。 * * 函数库文件不是按需加载!若支持加载函数,则所有定义函数的文件都会加载。 * * 代码中用到一个类或者函数的时候,不需要使用include/require来包含类库文件或者函数库文件。 * * 基于Autoloader组件的代码中将不用使用include/require。 * * Autoloader缓存的是绝对路径,能让Opcode Cache有效缓存文件。 * * Autoloader要求类的名字唯一,不在意类文件的路径和文件名。目前不支持命名空间(PHP5.3) * * 传统的include/require通常存在以下问题。 * <ul> * <li>目录名和文件名变化引起程序代码变化。</li> * <li>Windows和Linux对文件路径的大小写和目录分隔符号的处理不同导致代码在不同平台迁移时出现问题。</li> * <li>include_path相对路径的性能低(显著地低)。</li> * <li>为了保证不重复包含,使用include_once和require_once导致效率低(不是显著的低)。</li> * </ul> * @author Jianxiang Qin <TalkativeDoggy@gmail.com> Yi Zhao <zhao5908@gmail.com> * @category runtime * @package Lotusphp\Autoloader * @todo 所有class-file mapping当成一个数据写入storeHandle */ class LtAutoloader { /** * @var bool true|false 是否自动加载定义了函数的文件。 * false 只自动加载定义了class或者interface的文件。 * true (默认) 自动加载定义了函数的文件。 */ public $isLoadFunction = true; /** * @var array 要扫描的文件类型 * 若该属性设置为array("php","inc","php3"), * 则扩展名为"php","inc","php3"的文件会被扫描, * 其它扩展名的文件会被忽略 */ public $allowFileExtension = array('php', 'inc'); /** * @var array 不扫描的目录 * 若该属性设置为array(".svn", ".setting"), * 则所有名为".setting"的目录也会被忽略 */ public $skipDirNames = array('.svn', '.git'); /** @var LtStoreFile 存储句柄默认使用 @link LtStoreFile */ public $storeHandle; /** @var array 指定需要自动加载的目录列表 */ public $autoloadPath; /** @var bool * true 开发模式下 每次都会扫描目录列表 * false 生产环境下 只扫描一次 */ public $devMode = true; /** @var array 函数名 -> 文件路径 映射 */ private $functionFileMapping = array(); /** @var array 类名 -> 文件路径 映射 */ private $classFileMapping = array(); /** @var array 定义了函数的文件列表 */ private $functionFiles = array(); /** @var LtStoreFile 持久存储句柄,存储文件的get_token_all分析结果/filesize/filehash @link LtStoreFile */ private $persistentStoreHandle; /** @var int store name space id */ private $storeNameSpaceId; /** @var int number of parse error */ private $parseErrorAmount = 0; /** @var int number of library files successfully parsed */ private $libFileAmount = 0; /** * 递归扫描指定的目录列表,根据@see LtAutoloader::$isLoadFunction是否加载全部的函数定义文件。 * 注册自动加载函数,按需加载类文件。 * @return void */ public function init() { $this->storeNameSpaceId = sprintf("%u", crc32(serialize($this->autoloadPath))); if (true != $this->devMode) { if ($this->storeHandle instanceof LtStore) { $this->storeHandle->prefix = 'Lt-Autoloader-' . $this->storeNameSpaceId; } else { if (null == $this->storeHandle) { $this->storeHandle = new LtStoreFile; $this->storeHandle->prefix = 'Lt-Autoloader-' . $this->storeNameSpaceId; $this->storeHandle->useSerialize = true; $this->storeHandle->init(); } else { trigger_error("You passed a value to autoloader::storeHandle, but it is NOT an instance of LtStore"); } } } else { $this->storeHandle = new LtStoreMemory; } // Whether scanning directory if ($storedMap = $this->storeHandle->get("map")) { $this->classFileMapping = $storedMap["classes"]; $this->functionFiles = $storedMap["functions"]; } else { $this->setPersistentStoreHandle(); $autoloadPath = $this->preparePath($this->autoloadPath); foreach($autoloadPath as $path) { if (is_file($path)) { $this->addFileMap($path); } } $this->scanDirs($autoloadPath); unset($autoloadPath); } // Whether loading function files $this->loadFunctionFiles(); spl_autoload_register(array($this, "loadClass")); } protected function setPersistentStoreHandle() { $this->persistentStoreHandle = new LtStoreFile; $this->persistentStoreHandle->prefix = 'Lt-parsed-token-' . $this->storeNameSpaceId; $this->persistentStoreHandle->useSerialize = true; } /** * Autoloader扫描项目,若某个php文件中定义了函数,则此文件的绝对路径被缓存, * 每次执行LtAutoloader->init()方法时,自动include所有定义了函数的php文件。 * 因为PHP的Autoload机制是针对Class的.function文件没有办法按需加载 * @return void */ protected function loadFunctionFiles() { if ($this->isLoadFunction && count($this->functionFiles)) { foreach ($this->functionFiles as $functionFile) { include_once($functionFile); } } } /** * 被注册的自动加载函数 * @param string $className * @return void */ protected function loadClass($className) { if ($filePath = $this->getFilePathByClassName($className)) { include($filePath); } } /** * 将目录分隔符号统一成linux目录分隔符号/ * @param string $path * @return boolean */ protected function convertPath($path) { $path = str_replace("\\", "/", $path); if (!is_readable($path)) { trigger_error("Directory is not exists/readable: {$path}"); return false; } $path = rtrim(realpath($path), '\\/'); if (preg_match("/\s/i", $path)) { trigger_error("Directory contains space/tab/newline is not supported: {$path}"); return false; } return $path; } /** * The string or an Multidimensional array into a one-dimensional array * 将字符串和多维数组转换成一维数组 * @param mixed $paths * @return array one-dimensional array */ protected function preparePath($paths) { $oneDPathArray = array(); if (!is_array($paths)) { $paths = array($paths); } $i = 0; while (isset($paths[$i])) { if (!is_array($paths[$i]) && $path = $this->convertPath($paths[$i])) { $oneDPathArray[] = $path; } else { foreach($paths[$i] as $v) { $paths[] = $v; } } $i ++; } unset($paths); return $oneDPathArray; } /** * Using iterative algorithm scanning subdirectories * save autoloader filemap * 递归扫描目录包含子目录,保存自动加载的文件地图。 * @param array $dirs one-dimensional * @return void * @todo in_array换成array_key_exists以提升性能 */ protected function scanDirs($dirs) { $i = 0; while (isset($dirs[$i])) { $dir = $dirs[$i]; $files = scandir($dir); foreach ($files as $file) { $currentFile = $dir . DIRECTORY_SEPARATOR . $file; if (is_file($currentFile)) { $this->addFileMap($currentFile); } else if (is_dir($currentFile)) { if (in_array($file, array(".", "..")) || in_array($file, $this->skipDirNames)) { continue; } else { // if $currentFile is a directory, pass through the next loop. $dirs[] = $currentFile; } } else { trigger_error("$currentFile is not a file or a directory."); } } //end foreach $i ++; } //end while if(0 == $this->parseErrorAmount) { $this->functionFiles = array_unique(array_values($this->functionFileMapping)); $map = array("classes" => $this->classFileMapping, "functions" => $this->functionFiles); if ($this->storeHandle->get("map")) { $this->storeHandle->update("map", $map); } else { $this->storeHandle->add("map", $map); } } else { trigger_error($this->parseErrorAmount . " error(s) occoured when scanning and parsing your lib files"); } } /** * 分析出字符串中的类,接口,函数。 * @param string $src * @return array * @todo 若当前文件包含了直接执行的php语句,或者html,输出警告 * @todo 若当前文件有语法错误,抛出异常 */ protected function parseLibNames($src) { $libNames = array(); $tokens = token_get_all($src); $level = 0; $found = false; $name = ''; foreach ($tokens as $token) { if (is_string($token)) { if ('{' == $token) { $level ++; } else if ('}' == $token) { $level --; } } else { list($id, $text) = $token; if (T_CURLY_OPEN == $id || T_DOLLAR_OPEN_CURLY_BRACES == $id) { $level ++; } if (0 < $level) { continue; } switch ($id) { case T_STRING: if ($found) { $libNames[strtolower($name)][] = $text; $found = false; } break; case T_CLASS: case T_INTERFACE: case T_FUNCTION: $found = true; $name = $text; break; } } } return $libNames; } /** * 保存类名、接口名和对应的文件绝对路径。 * @param string $className * @param string $file * @return boolean */ protected function addClass($className, $file) { $key = strtolower($className); if (isset($this->classFileMapping[$key])) { $existedClassFile = $this->classFileMapping[$key]; trigger_error("duplicate class [$className] found in:\n$existedClassFile\n$file\n, or please clear the cache"); return false; } else { $this->classFileMapping[$key] = $file; return true; } } /** * 保存函数名和对应的文件绝对路径 * @param string $functionName * @param string $file * @return boolean */ protected function addFunction($functionName, $file) { $functionName = strtolower($functionName); if (isset($this->functionFileMapping[$functionName])) { $existedFunctionFile = $this->functionFileMapping[$functionName]; trigger_error("duplicate function [$functionName] found in:\n$existedFunctionFile\n$file\n"); return false; } else { $this->functionFileMapping[$functionName] = $file; return true; } } /** * 将文件添加到自动加载的FileMap, * 添加之前会判断自从上次扫描后有没有修改,若没有修改则无需重复添加, * 若修改过,则分析文件内容,根据内容中包含的类、接口,函数添加到FileMap * @param string $filePath * @return boolean */ protected function addFileMap($filePath) { if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), $this->allowFileExtension)) {//init()会调用这个方法, 不要将这个判断移动到scanDir()中 return false; } $fileSize = filesize($filePath); $fileHash = md5_file($filePath); $savedFileInfo = $this->persistentStoreHandle->get($filePath); if (!isset($savedFileInfo['file_size']) || $savedFileInfo['file_size'] != $fileSize || $savedFileInfo['file_hash'] != $fileHash) { if($libNames = $this->parseLibNames(trim(file_get_contents($filePath)))) { $newFileInfo = array('file_size' => $fileSize, 'file_hash' => $fileHash, 'lib_names' => $libNames); if (isset($savedFileInfo['file_size'])) { $this->persistentStoreHandle->update($filePath, $newFileInfo); } else { $this->persistentStoreHandle->add($filePath, $newFileInfo); } } else { $this->parseErrorAmount ++; } } else { $libNames = $savedFileInfo['lib_names']; } foreach ($libNames as $libType => $libArray) { $method = "function" == $libType ? "addFunction" : "addClass"; foreach ($libArray as $libName) { if (!$this->$method($libName, $filePath)) { $this->parseErrorAmount ++; } } } return true; } protected function getFilePathByClassName($className) { $key = strtolower($className); if (isset($this->classFileMapping[$key])) { return $this->classFileMapping[$key]; } else { return false; } } }登入後複製6、set_include_path 方式
set_include_path(implode(PATH_SEPARATOR, array(get_include_path(), './services', './printers'))); spl_autoload_register();登入後複製7、PSR-4: Autoloader
http://www.php-fig.org/psr/psr-4/
参考文章
http://www.phpro.org/tutorials/SPL-Autoload.html
https://github.com/qinjx/adv_php_book/blob/master/class_autoload.md
http://php.net/manual/zh/language.oop5.autoload.php

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHPSPL資料結構庫概述PHPSPL(標準php庫)資料結構庫包含一組類別和接口,用於儲存和操作各種資料結構。這些資料結構包括數組、鍊錶、堆疊、佇列和集合,每個資料結構都提供了一組特定的方法和屬性,用於操縱資料。數組在PHP中,數組是儲存一系列元素的有序集合。 SPL數組類別提供了對原生的PHP數組進行加強的功能,包括排序、過濾和映射。以下是使用SPL陣列類別的範例:useSplArrayObject;$array=newArrayObject(["foo","bar","baz"]);$array

PHPSPL資料結構:概述phpSPL資料結構是PHP標準函式庫(SPL)中的一個元件,它提供了一組通用資料結構,包括堆疊、佇列、陣列和雜湊表。這些資料結構經過最佳化,可高效處理各種資料類型,並提供了一致的接口,簡化了應用程式開發。主要資料結構堆疊堆疊是一種遵循後進先出(LIFO)原則的有序集合。在堆疊中,最後一個新增的元素將是第一個被刪除的元素。 SPL提供了一個SplStack類別來表示堆疊。以下範例展示如何使用SplStack:$stack=newSplStack();$stack->push(1

PHPSPL資料結構庫簡介PHP標準函式庫(SPL)包含了一組豐富的內建資料類型,稱為資料結構。這些結構提供了對複雜資料集合的高效和靈活的管理。使用SPL資料結構可以為您的應用程式帶來以下好處:效能最佳化:SPL資料結構經過專門設計,可在各種情況下提供最佳效能。可維護性提高:這些結構簡化了複雜資料類型的處理,從而提高程式碼的可讀性和可維護性。標準化:SPL資料結構符合php程式設計規範,確保跨應用程式的一致性和互通性。 SPL資料結構類型SPL提供了幾種資料結構類型,每種類型都有其獨特的特性和用途:堆疊(St

可以在Java應用中嵌入的資料引擎看起來比較豐富,但其實並不容易選擇。 Redis運算能力很差,只適合簡單查詢的場景。 Spark架構複雜沉重,部署維護很麻煩。 H2\HSQLDB\Derby等內嵌資料庫倒是架構簡單,但運算能力又不足,連基本的視窗函數都不支援。相較之下,SQLite在架構性和運算能力上取得了較好的平衡,是應用較廣的Java嵌入資料引擎。 SQLite適應常規基本應用場景SQLite架構簡單,其核心雖然是C語言開發的,但封裝得比較好,對外呈現為一個小巧的Jar包,能方便地集成在Java

1.選擇合適的抽象資料類型(ADT)ADT定義了一組操作和屬性,用於抽像地描述資料類型。 SPL提供了大量的ADT實現,包括陣列、集合、佇列和堆疊。選擇合適的ADT至關重要,因為它會影響程式碼的行為和開銷。數組(ArrayObject):有序集合,用於儲存鍵值對。集合(SetObject):無序集合,用來儲存唯一元素。佇列(QueueObject):先進先出(FIFO)資料結構,用來處理訊息和事件。堆疊(StackObject):後進先出(LIFO)資料結構,用於遞歸處理和函數呼叫。 2.使用迭代器進

PHPStandardLibrary(SPL)為php提供了一套強大的資料結構,用於高效處理和管理複雜資料。這些資料結構包括數組、集合、有序映射等,它們專門設計為在各種場景下提供優異的效能和靈活性。數組(Array)PHP數組是一個有序集合,它以鍵值對的形式儲存資料。數組廣泛用於儲存列表、哈希表和關聯數組。透過使用內建的array_*函數,可以輕鬆地建立、操作和遍歷數組。 $array=["apple","banana","cherry"];array_push($array,"durian");

PHP是一種開源的、物件導向的、伺服器端的腳本語言,可以用於快速開發動態Web應用程式。 PHP的標準函式庫提供了許多常用的函數和類別,但有些時候需要處理的資料結構比較複雜,標準函式庫中的功能就不夠用了。此時,可以使用PHP的SPL擴充來解決問題。 SPL是StandardPHPLibrary的縮寫,它是PHP5引入的一個標準庫,提供了一系列的介面和類,用於處理各種

探索PHPSPL資料結構的優勢phpSPL(標準PHP庫)資料結構庫是一個寶庫,它提供了各種預先定義的資料結構,例如陣列、佇列、堆疊和集合,有助於簡化和有效率地管理資料。利用這些結構,開發人員可以:提高資料管理效率:SPL資料結構提供了一致的介面和最佳化演算法,簡化了資料的儲存、檢索和操縱。增強程式碼可讀性:使用標準化的結構,程式碼變得更易於理解和維護,從而提高開發效率。提升效能:SPL資料結構經過最佳化,可有效處理大量數據,從而提高應用程式的整體效能。 SPL資料結構類型SPL資料結構庫涵蓋了廣泛的資料結構
