PHP Conference Japan 2024

dl

(PHP 4、PHP 5、PHP 7、PHP 8)

dl在运行时加载 PHP 扩展

描述

dl(字符串 $extension_filename): 布尔值

加载由参数 extension_filename 指定的 PHP 扩展。

使用 extension_loaded() 测试给定的扩展是否已可用。这适用于内置扩展和动态加载的扩展(通过 php.inidl())。

警告

此函数仅适用于 CLI 和嵌入式 SAPI,以及从命令行运行的 CGI SAPI

参数

extension_filename

此参数是要加载的扩展的文件名,也取决于您的平台。例如,sockets 扩展(如果编译为共享模块,而不是默认值!)在 Unix 平台上称为 sockets.so,而在 Windows 平台上称为 php_sockets.dll

加载扩展的目录取决于您的平台

Windows - 如果在 php.ini 中未显式设置,则默认情况下从 C:\php5\ 加载扩展。

Unix - 如果在 php.ini 中未显式设置,则默认扩展目录取决于

  • PHP 是否已使用 --enable-debug 构建
  • PHP 是否已使用 ZTS(Zend 线程安全)支持构建
  • 当前的内部 ZEND_MODULE_API_NO(Zend 内部模块 API 编号,基本上是主要模块 API 更改的日期,例如 20010901
考虑到以上因素,目录默认为 <install-dir>/lib/php/extensions/ <debug-or-not>-<zts-or-not>-ZEND_MODULE_API_NO,例如 /usr/local/php/lib/php/extensions/debug-non-zts-20010901/usr/local/php/lib/php/extensions/no-debug-zts-20010901

返回值

成功时返回 true,失败时返回 false。如果加载模块的功能不可用或已被禁用(通过在 php.ini 中将 enable_dl 设置为关闭),则会发出 E_ERROR 并停止执行。如果 dl() 由于无法加载指定的库而失败,除了 false 之外,还会发出 E_WARNING 消息。

示例

示例 #1 dl() 示例

<?php
// 示例根据操作系统加载扩展
if (!extension_loaded('sqlite')) {
if (
strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
dl('php_sqlite.dll');
} else {
dl('sqlite.so');
}
}

// 或使用 PHP_SHLIB_SUFFIX 常量
if (!extension_loaded('sqlite')) {
$prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
dl($prefix . 'sqlite.' . PHP_SHLIB_SUFFIX);
}
?>

注释

注意:

dl() 在 Unix 平台上区分大小写。

参见

添加注释

用户贡献的注释 4 条注释

shaunspiller at spammenot-gmail dot com
15 年前
dl 比较麻烦,因为文件名格式依赖于操作系统,并且如果扩展已加载,它可能会报错。此包装函数解决了这个问题

<?php

function load_lib($n, $f = null) {
return
extension_loaded($n) or dl(((PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '') . ($f ? $f : $n) . '.' . PHP_SHLIB_SUFFIX);
}

?>

示例

<?php

// 确保我们有 SSL 和 MySQL 支持
load_lib('openssl');
load_lib('mysql');

// 一些扩展的文件名与其扩展名不同,例如图像 (gd) 库,因此我们像这样指定它们:
load_lib('gd', 'gd2');

?>
mag_2000 at front dot ru
18 年前
<?php

function dl_local( $extensionFile ) {
//确保能够加载库
if( !(bool)ini_get( "enable_dl" ) || (bool)ini_get( "safe_mode" ) ) {
die(
"dh_local(): 加载扩展不允许。\n" );
}

//检查文件是否存在
if( !file_exists( $extensionFile ) ) {
die(
"dl_local(): 文件 '$extensionFile' 不存在。\n" );
}

//检查文件权限
if( !is_executable( $extensionFile ) ) {
die(
"dl_local(): 文件 '$extensionFile' 不可执行。\n" );
}

//确定路径
$currentDir = getcwd() . "/";
$currentExtPath = ini_get( "extension_dir" );
$subDirs = preg_match_all( "/\//" , $currentExtPath , $matches );
unset(
$matches );

//确保提取了有效的扩展路径
if( !(bool)$subDirs ) {
die(
"dl_local(): 无法确定有效的扩展路径 [extension_dir]。\n" );
}

$extPathLastChar = strlen( $currentExtPath ) - 1;

if(
$extPathLastChar == strrpos( $currentExtPath , "/" ) ) {
$subDirs--;
}

$backDirStr = "";
for(
$i = 1; $i <= $subDirs; $i++ ) {
$backDirStr .= "..";
if(
$i != $subDirs ) {
$backDirStr .= "/";
}
}

//构建最终加载路径
$finalExtPath = $backDirStr . $currentDir . $extensionFile;

//执行 dl() 加载模块
if( !dl( $finalExtPath ) ) {
die();
}

//如果模块加载成功,获取模块名称
$loadedExtensions = get_loaded_extensions();
$thisExtName = $loadedExtensions[ sizeof( $loadedExtensions ) - 1 ];

//返回扩展名称
return $thisExtName;

}
//end dl_local()

?>
anrdaemon at freemail dot ru
8 年前
就像使用 eval() 一样,使用 dl() 的唯一正确方法是不使用它。
测试您打算使用的函数(s) 是否可用。
如果不可用,则向用户抱怨或实现解决方法。
更不用说 dl() 在多线程环境中的问题了。
endofyourself at yahoo dot com
21 年前
如果您需要从当前本地目录加载扩展,因为您没有权限将扩展放置在服务器的 PHP 扩展目录中,那么我编写的此函数可能对您有用

<?php
/*
函数:dl_local()
参考:http://us2.php.net/manual/en/function.dl.php
作者:Brendon Crawford <endofyourself |AT| yahoo>
用法:dl_local( "mylib.so" );
返回值:扩展名(但不是扩展文件名)
注意:
此函数可用于您需要加载 PHP 扩展(模块、共享对象等)时,
但您没有足够的权限将扩展放置在可以加载它的正确目录中。此函数
将仅从当前工作目录加载扩展。
如果您需要查看特定扩展中有哪些函数可用,
使用“get_extension_funcs()”。此函数的文档可在以下位置找到:
"http://us2.php.net/manual/en/function.get-extension-funcs.php"。
*/

function dl_local( $extensionFile ) {
//确保能够加载库
if( !(bool)ini_get( "enable_dl" ) || (bool)ini_get( "safe_mode" ) ) {
die(
"dh_local(): 加载扩展不允许。\n" );
}

//检查文件是否存在
if( !file_exists( $extensionFile ) ) {
die(
"dl_local(): 文件 '$extensionFile' 不存在。\n" );
}

//检查文件权限
if( !is_executable( $extensionFile ) ) {
die(
"dl_local(): 文件 '$extensionFile' 不可执行。\n" );
}

//确定路径
$currentDir = getcwd() . "/";
$currentExtPath = ini_get( "extension_dir" );
$subDirs = preg_match_all( "/\//" , $currentExtPath , $matches );
unset(
$matches );

//确保提取了有效的扩展路径
if( !(bool)$subDirs ) {
die(
"dl_local(): 无法确定有效的扩展路径 [extension_dir]。\n" );
}

$extPathLastChar = strlen( $currentExtPath ) - 1;

if(
$extPathLastChar == strrpos( $currentExtPath , "/" ) ) {
$subDirs--;
}

$backDirStr = "";
for(
$i = 1; $i <= $subDirs; $i++ ) {
$backDirStr .= "..";
if(
$i != $subDirs ) {
$backDirStr .= "/";
}
}

//构建最终加载路径
$finalExtPath = $backDirStr . $currentDir . $extensionFile;

//执行 dl() 加载模块
if( !dl( $finalExtPath ) ) {
die();
}

//如果模块加载成功,获取模块名称
$loadedExtensions = get_loaded_extensions();
$thisExtName = $loadedExtensions[ sizeof( $loadedExtensions ) - 1 ];

//返回扩展名称
return $thisExtName;

}
//end dl_local()

?>
To Top