php命名空间 autoload,PHP命名空间namespace使用之spl_autoload

本文详细介绍了PHP的自动加载机制,从传统方式引入类文件的不便,到使用__autoload函数的改进,再到优化后的命名空间和Autoloader类的运用。通过实例演示了如何为项目创建和注册Autoloader,使得类文件的引入更加简洁高效。此外,还展示了如何为Gaufrette项目添加自定义的Autoloader,以便于管理和使用项目库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在github上很多项目都不会告诉你如何include或require他们的项目,有的项目会提供一个autoload.php文件直接引用即可(如Predis),有的项目什么也不会给,甚至在README中都不会给出require的代码(如Gaufrette)。毕竟国外的程序员都已经习以为常,使用autoload来包含项目非常容易。

下面,以自己写的一个小项目为例循序渐进讲解一下如果autoload项目文件。

主要项目文件介绍:

IpWatch.class.php:类文件,IpWatch是主要用到的类。

FileCache.class.php:类文件,FileCache在IpWatch内部实例化。

RedisCache.class.php:类文件,RedisCache在IpWatch内部实例化。

其余的后面再说,传统方式使用只需要引用这三个文件即可使用本项目的所有功能,代码如下。

传统:<?php

include 'IpWatch.class.php';

include 'FileCache.class.php';

include 'RedisCache.class.php';

use Shuiguang\IpWatch;

use Shuiguang\FileCache;

use Shuiguang\RedisCache;

$file_config = array(

'interval' => 60,                       //最后一次请求到现在的间隔时间(s),如果大于此值则清除统计缓存

'mode' => 'file',                       //可选file(文件记录),redis(需安装redis扩展)

'type' => 'time',                       //可选number(数值记录),time(访问时间记录)

'file_dir' => 'ip',                     //缓存文件路径,建议放在/tmp目录下或定时清除

'prefix' => '',                         //缓存文件名前缀

'suffix' => '.ip',                      //缓存文件名后缀

);

$ipWatcher = Shuiguang\IpWatch::getInstance($file_config);

//允许单个IP单位时间内最大访问次数

$max_request = 10;

//获取当前IP访问次数

$current = $ipWatcher->get();

//超过这个次数则退出脚本

if($current >= $max_request)

{

die($current);

}else{

$add = $ipWatcher->incr();

}

echo 'ok, go on';

使用传统的include或require方式:当项目文件数较小的时候,多处逻辑代码引用了这3个文件,如果后来该项目增加了其他很多的类文件,需要修改所有的逻辑代码,非常不便。

如果使用__autoload来定义include规则自动include类文件将会非常轻松。

进阶:<?php

//自定义自动加载函数

function autoload($classname)

{

$dir = './';

if(is_file($dir.'/'.$classname.'.class.php'))

{

include $dir.'/'.$classname.'.class.php';

}else{

throw new Exception($dir.'/'.$classname.'.class.php not exists');

}

}

//注册自动加载函数

spl_autoload_register('autoload');

use Shuiguang\IpWatch;

use Shuiguang\FileCache;

use Shuiguang\RedisCache;

$file_config = array(

'interval' => 60,                       //最后一次请求到现在的间隔时间(s),如果大于此值则清除统计缓存

'mode' => 'file',                       //可选file(文件记录),redis(需安装redis扩展)

'type' => 'time',                       //可选number(数值记录),time(访问时间记录)

'file_dir' => 'ip',                     //缓存文件路径,建议放在/tmp目录下或定时清除

'prefix' => '',                         //缓存文件名前缀

'suffix' => '.ip',                      //缓存文件名后缀

);

$ipWatcher = Shuiguang\IpWatch::getInstance($file_config);

//允许单个IP单位时间内最大访问次数

$max_request = 10;

//获取当前IP访问次数

$current = $ipWatcher->get();

//超过这个次数则退出脚本

if($current >= $max_request)

{

die($current);

}else{

$add = $ipWatcher->incr();

}

echo 'ok, go on';

然而这样的方式并不是非常合适,一方面autoload函数将会作用于全局这样并不好,另一方面autoload函数中的.class.php文件路径是固定的,而且无法使用命名空间、子空间的优势。

从Predis项目中可以找到一个这样的类:Autoloader.php。(本项目中已经将类文件重命名为Autoloader.class.php)。

优化:<?php

/*

* This file is part of IpWatch.

*

* Licensed under The MIT License

* For full copyright and license information, please see the MIT-LICENSE.txt

* Redistributions of files must retain the above copyright notice.

* IpWatch for php

* @author shuiguang

* @link https://github.com/shuiguang/IpWatch

* @license http://www.opensource.org/licenses/mit-license.php MIT License

*/

namespace Shuiguang;

class Autoloader

{

private $directory;

private $prefix;

private $prefixLength;

/**

* @param string $baseDirectory Base directory where the source files are located.

*/

public function __construct($baseDirectory = __DIR__)

{

$this->directory = $baseDirectory;

$this->prefix = __NAMESPACE__ . '\\';

$this->prefixLength = strlen($this->prefix);

}

/**

* Registers the autoloader class with the PHP SPL autoloader.

*

* @param bool $prepend Prepend the autoloader on the stack instead of appending it.

*/

public static function register($prepend = false)

{

spl_autoload_register(array(new self, 'autoload'), true, $prepend);

}

/**

* Loads a class from a file using its fully qualified name.

*

* @param string $className Fully qualified name of a class.

*/

public function autoload($className)

{

if (0 === strpos($className, $this->prefix)) {

$parts = explode('\\', substr($className, $this->prefixLength));

$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.class.php';

if (is_file($filepath)) {

require($filepath);

}

}

}

}

该类中主要使用了上一篇文章《PHP命名空间namespace使用》中介绍的__NAMESPACE__自动获取命名空间(文件夹名)和子命名空间(子文件夹名),然后通过autoload.php文件中的Shuiguang\Autoloader::register();进行注册。原理大致相同,但是实现方式非常优雅,所有的逻辑程序文件可引入autoload.php后直接使用即可,代码如下。<?php

/*

* This file is part of IpWatch.

*

* Licensed under The MIT License

* For full copyright and license information, please see the MIT-LICENSE.txt

* Redistributions of files must retain the above copyright notice.

* IpWatch for php

* @author shuiguang

* @link https://github.com/shuiguang/IpWatch

* @license http://www.opensource.org/licenses/mit-license.php MIT License

*/

require __DIR__ . '/src/Shuiguang/Autoloader.class.php';

Shuiguang\Autoloader::register();

逻辑代码如下:include 'autoload.php';

use代码

调用代码

如果以后需要添加类文件,放在src/Shuiguang下然后use即可,无需手动导入。

案例:

从github上下载最新版的Gaufrette,官方未给出任何自动加载的教程,需要我们自己实现。

解压之后,项目文件存在于Gaufrette-master\src\Gaufrette目录下,将predis中的Autoloader.php文件复制到Gaufrette-master\src\Gaufrette目录下,并且修改为namespace Gaufrette;<?php

namespace Gaufrette;

/**

* Implements a lightweight PSR-0 compliant autoloader for Predis.

*

* @author Eric Naeseth 

* @author Daniele Alessandri 

*/

class Autoloader

{

private $directory;

private $prefix;

private $prefixLength;

/**

* @param string $baseDirectory Base directory where the source files are located.

*/

public function __construct($baseDirectory = __DIR__)

{

$this->directory = $baseDirectory;

$this->prefix = __NAMESPACE__.'\\';

$this->prefixLength = strlen($this->prefix);

}

/**

* Registers the autoloader class with the PHP SPL autoloader.

*

* @param bool $prepend Prepend the autoloader on the stack instead of appending it.

*/

public static function register($prepend = false)

{

spl_autoload_register(array(new self(), 'autoload'), true, $prepend);

}

/**

* Loads a class from a file using its fully qualified name.

*

* @param string $className Fully qualified name of a class.

*/

public function autoload($className)

{

if (0 === strpos($className, $this->prefix)) {

$parts = explode('\\', substr($className, $this->prefixLength));

$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';

if (is_file($filepath)) {

require $filepath;

}

}

}

}

然后到Gaufrette-master目录建立一个autoload.php文件,该文件位置可任意放置,只需要保证require的路径正确即可。<?php

require __DIR__ . '/src/Gaufrette/Autoloader.php';

Gaufrette\Autoloader::register();

最后,到逻辑代码处引用这个autoload.php文件即可,例如。<?php

include 'autoload.php';

use Gaufrette\Filesystem;

use Gaufrette\Adapter\Local as LocalAdapter;

$adapter = new LocalAdapter(__DIR__);

$filesystem = new Filesystem($adapter);

$content = 'Hello I am the new content';

$filesystem->write('myFile.txt', $content);

完成引入该项目。

PS:外国人不喜欢使用.class.php作为类文件的后缀,通常直接使用.php文件名,其关键代码在Autoloader.php文件的这一行,怎么选取决于自己的习惯:$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';

案例下载:

随意转载~但请保留教程地址★

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值