咳咳,各位同学,欢迎来到今天的“Wordpress 媒体上传目录探秘”讲座。我是你们今天的讲师,咱们废话不多说,直接进入正题!
今天我们要解剖的,是 WordPress 中一个非常重要且常用的函数:wp_upload_dir()
。它就像 WordPress 的“文件管理员”,负责告诉你,你的媒体文件都应该放在哪里,以及如何通过 URL 访问它们。
一、wp_upload_dir()
的身世背景
首先,我们要知道 wp_upload_dir()
函数位于 wp-includes/functions.php
文件中。它返回一个数组,包含了媒体上传目录的各种信息,比如路径、URL 等等。
二、wp_upload_dir()
的庐山真面目(源码解析)
让我们直接来看源码(简化版,方便理解):
function wp_upload_dir( $time = null, $create_dir = true, $deprecated = false ) {
global $switched;
static $cache = array();
if ( $deprecated ) {
_deprecated_argument( __FUNCTION__, '2.0' );
}
$key = md5( serialize( array( $time, $create_dir, $switched ) ) );
if ( isset( $cache[ $key ] ) ) {
return $cache[ $key ];
}
$siteurl = get_option( 'siteurl' );
$upload_path = trim( get_option( 'upload_path' ) );
if ( empty( $upload_path ) ) {
$dir = WP_CONTENT_DIR . '/uploads';
} else {
$dir = $upload_path;
if ( 0 !== strpos( $dir, ABSPATH ) ) {
$dir = trailingslashit( ABSPATH ) . $dir;
}
}
$url = get_option( 'upload_url_path' );
if ( empty( $url ) ) {
$url = trailingslashit( $siteurl ) . 'wp-content/uploads';
}
// If multisite (and not switched), confirm that the upload base exists.
if ( is_multisite() && ! is_switched() ) {
$ms_dir = '/sites/' . get_current_blog_id();
$dir .= $ms_dir;
$url .= $ms_dir;
}
if ( false !== strpos( $time, '/' ) ) {
$time_bits = explode( '/', $time );
$time = array(
'year' => $time_bits[0],
'month' => $time_bits[1],
);
unset( $time_bits );
}
if ( empty( $time ) ) {
$time = gmdate( 'Y/m' );
}
if ( is_array( $time ) ) {
$year = ( ! empty( $time['year'] ) ) ? absint( $time['year'] ) : gmdate( 'Y' );
$month = ( ! empty( $time['month'] ) ) ? zeroise( absint( $time['month'] ), 2 ) : gmdate( 'm' );
} else {
$year = substr( $time, 0, 4 );
$month = substr( $time, 5, 2 );
}
$subdir = "/{$year}/{$month}";
$dir .= $subdir;
$url .= $subdir;
$basedir = $dir;
$baseurl = $url;
$error = false;
if ( $create_dir ) {
$stat = wp_mkdir_p( untrailingslashit( $dir ) );
if ( ! $stat ) {
$error = true;
}
}
$ret = array(
'path' => $dir,
'url' => $url,
'subdir' => $subdir,
'basedir' => $basedir,
'baseurl' => $baseurl,
'error' => $error,
);
$cache[ $key ] = $ret;
return $ret;
}
是不是感觉有点长?别怕,我们一步一步来拆解它。
2.1 缓存机制
static $cache = array();
$key = md5( serialize( array( $time, $create_dir, $switched ) ) );
if ( isset( $cache[ $key ] ) ) {
return $cache[ $key ];
}
首先,函数使用了静态变量 $cache
来缓存结果。这意味着,如果相同的参数被多次调用,函数会直接从缓存中返回结果,而不会重新计算。这提高了性能。md5(serialize())
主要用来生成一个基于传入参数的唯一键值。
2.2 获取配置信息
$siteurl = get_option( 'siteurl' );
$upload_path = trim( get_option( 'upload_path' ) );
$url = get_option( 'upload_url_path' );
这里,函数从 WordPress 选项中获取了三个关键配置:
siteurl
: WordPress 站点的 URL。upload_path
: 上传目录的路径。这是一个可选配置,允许你自定义上传目录的位置。如果没有设置,默认为wp-content/uploads
。upload_url_path
: 上传目录的 URL。同样是可选配置,用于自定义上传目录的 URL。如果没有设置,默认为siteurl . '/wp-content/uploads'
。
2.3 确定上传目录的基本路径
if ( empty( $upload_path ) ) {
$dir = WP_CONTENT_DIR . '/uploads';
} else {
$dir = $upload_path;
if ( 0 !== strpos( $dir, ABSPATH ) ) {
$dir = trailingslashit( ABSPATH ) . $dir;
}
}
这段代码确定了上传目录的基本路径。如果 upload_path
没有设置,就使用默认的 WP_CONTENT_DIR . '/uploads'
。WP_CONTENT_DIR
是 wp-content
目录的绝对路径。
如果 upload_path
设置了,函数会检查它是否是绝对路径。如果不是,就把它拼接到 ABSPATH
(WordPress 根目录的绝对路径) 后面。
2.4 确定上传目录的基本 URL
$url = get_option( 'upload_url_path' );
if ( empty( $url ) ) {
$url = trailingslashit( $siteurl ) . 'wp-content/uploads';
}
这段代码确定了上传目录的基本 URL。如果 upload_url_path
没有设置,就使用默认的 siteurl . '/wp-content/uploads'
。
2.5 多站点支持
if ( is_multisite() && ! is_switched() ) {
$ms_dir = '/sites/' . get_current_blog_id();
$dir .= $ms_dir;
$url .= $ms_dir;
}
如果 WordPress 是多站点模式,并且当前不是“切换”到其他站点(is_switched()
函数用于判断是否已经切换到其他站点),那么这段代码会在路径和 URL 中添加 /sites/{blog_id}
子目录,用于区分不同站点的上传文件。
2.6 时间参数处理 (年/月)
if ( false !== strpos( $time, '/' ) ) {
$time_bits = explode( '/', $time );
$time = array(
'year' => $time_bits[0],
'month' => $time_bits[1],
);
unset( $time_bits );
}
if ( empty( $time ) ) {
$time = gmdate( 'Y/m' );
}
if ( is_array( $time ) ) {
$year = ( ! empty( $time['year'] ) ) ? absint( $time['year'] ) : gmdate( 'Y' );
$month = ( ! empty( $time['month'] ) ) ? zeroise( absint( $time['month'] ), 2 ) : gmdate( 'm' );
} else {
$year = substr( $time, 0, 4 );
$month = substr( $time, 5, 2 );
}
这段代码处理了时间参数 $time
。$time
可以是 null、字符串 (YYYY/MM) 或数组 (array(‘year’ => YYYY, ‘month’ => MM))。
- 如果
$time
是 null,就使用当前的年份和月份。 - 如果
$time
是字符串,就把它分割成年份和月份。 - 如果
$time
是数组,就从中提取年份和月份。
zeroise()
函数用于在月份前面补 0,例如把 1 变成 01。
2.7 生成子目录
$subdir = "/{$year}/{$month}";
$dir .= $subdir;
$url .= $subdir;
根据年份和月份,生成子目录 $subdir
,并把它拼接到路径和 URL 后面。
2.8 创建目录
if ( $create_dir ) {
$stat = wp_mkdir_p( untrailingslashit( $dir ) );
if ( ! $stat ) {
$error = true;
}
}
如果 $create_dir
参数为 true (默认值),就使用 wp_mkdir_p()
函数创建目录。wp_mkdir_p()
函数会递归创建目录,类似于 Linux 的 mkdir -p
命令。
如果目录创建失败,就把 $error
设置为 true。
2.9 返回结果
$ret = array(
'path' => $dir,
'url' => $url,
'subdir' => $subdir,
'basedir' => $basedir,
'baseurl' => $baseurl,
'error' => $error,
);
$cache[ $key ] = $ret;
return $ret;
最后,函数返回一个数组,包含了以下信息:
path
: 完整的上传目录路径。url
: 完整的上传目录 URL。subdir
: 年/月 子目录。basedir
: 上传目录的基本路径 (不包含年/月)。baseurl
: 上传目录的基本 URL (不包含年/月)。error
: 是否发生错误。
并将结果存入缓存。
三、wp_upload_dir()
的参数
wp_upload_dir()
函数接受三个参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
$time |
string/array/null | null | 指定上传目录的年份和月份。可以是以下几种形式:
|
$create_dir |
bool | true | 是否创建目录。如果为 true,函数会尝试创建上传目录。如果为 false,函数不会创建目录。 |
$deprecated |
bool | false | 这是一个废弃的参数,不要使用。 |
四、wp_upload_dir()
的使用示例
<?php
$upload_dir = wp_upload_dir();
echo '<pre>';
print_r( $upload_dir );
echo '</pre>';
// 获取当前月份的上传目录路径
$upload_path = $upload_dir['path'];
echo "当前月份的上传目录路径: " . $upload_path . "<br>";
// 获取当前月份的上传目录 URL
$upload_url = $upload_dir['url'];
echo "当前月份的上传目录 URL: " . $upload_url . "<br>";
// 获取基本目录
$basedir = $upload_dir['basedir'];
echo "基本目录: " . $basedir . "<br>";
// 获取基本URL
$baseurl = $upload_dir['baseurl'];
echo "基本URL: " . $baseurl . "<br>";
// 指定年份和月份
$upload_dir_2023_10 = wp_upload_dir( '2023/10' );
echo "2023年10月的上传目录路径: " . $upload_dir_2023_10['path'] . "<br>";
// 指定年份和月份, 不创建目录
$upload_dir_2024_01_no_create = wp_upload_dir( '2024/01', false );
echo "2024年1月的上传目录路径 (不创建目录): " . $upload_dir_2024_01_no_create['path'] . "<br>";
?>
这段代码演示了如何使用 wp_upload_dir()
函数来获取上传目录的信息。
五、自定义上传目录
WordPress 允许你自定义上传目录的位置和 URL。你可以在 wp-config.php
文件中定义 WP_CONTENT_DIR
和 WP_CONTENT_URL
常量来修改 wp-content
目录的位置。
或者,你可以在 WordPress 后台的“设置 -> 媒体”页面中设置“上传文件”选项,来修改上传目录的路径和 URL。 但是强烈建议使用常量定义,以保证路径的绝对性和可靠性。
六、注意事项
- 确保上传目录具有正确的权限,以便 WordPress 可以写入文件。
- 避免在
wp-content/uploads
目录中存放除了媒体文件以外的其他文件。 - 如果你的网站使用了 CDN,你需要配置 CDN 来加速上传目录的访问。
七、总结
wp_upload_dir()
函数是 WordPress 中一个非常重要的函数,它负责告诉你媒体文件应该放在哪里,以及如何通过 URL 访问它们。理解它的工作原理,可以帮助你更好地管理你的媒体文件,并自定义上传目录的位置和 URL。
八、思考题
wp_upload_dir()
函数中的缓存机制有什么作用?- 如果
upload_path
选项没有设置,wp_upload_dir()
函数会使用哪个默认路径? wp_mkdir_p()
函数的作用是什么?它和mkdir()
函数有什么区别?- 如何自定义 WordPress 的上传目录?有哪些方法?
- 在多站点模式下,
wp_upload_dir()
函数如何区分不同站点的上传文件?
好了,今天的讲座就到这里。希望大家有所收获!下课!