wp_mkdir_p()
云策文档标注
概述
wp_mkdir_p() 是 WordPress 中用于递归创建目录的函数,基于完整路径操作,并尝试设置文件夹权限。它返回布尔值表示路径是否创建成功,如果路径已存在则返回 true。
关键要点
- 函数 wp_mkdir_p( $target ) 接受一个必需参数 $target,表示要创建的完整路径。
- 返回值为布尔类型:成功创建或路径已存在时返回 true,否则返回 false。
- 函数会处理流包装器(如 wp_is_stream()),并防止路径遍历攻击(如 '../')。
- 权限继承自父目录,使用 stat() 获取权限位,默认权限为 0777。
- 如果 umask 影响权限,函数会通过 chmod() 重新设置正确权限。
- 相关函数包括 wp_is_stream()、wp_upload_bits() 等,用于文件操作和流处理。
代码示例
if ( wp_mkdir_p( '/a/really/deep/sub/directory' ) ) {
echo __( 'It worked! Now look for a directory named "a".', 'textdomain' );
}注意事项
- 使用前应检查目录是否已存在,以避免不必要的操作,例如使用 is_dir()。
- 对于需要特定权限(如 777)的目录,创建后可能需要手动调用 chmod() 调整。
- 函数从 WordPress 2.0.1 版本引入,适用于各种文件系统操作场景。
原文内容
Recursive directory creation based on full path.
Description
Will attempt to set permissions on folders.
Parameters
$targetstringrequired-
Full path to attempt to create.
Source
function wp_mkdir_p( $target ) {
$wrapper = null;
// Strip the protocol.
if ( wp_is_stream( $target ) ) {
list( $wrapper, $target ) = explode( '://', $target, 2 );
}
// From php.net/mkdir user contributed notes.
$target = str_replace( '//', '/', $target );
// Put the wrapper back on the target.
if ( null !== $wrapper ) {
$target = $wrapper . '://' . $target;
}
/*
* Safe mode fails with a trailing slash under certain PHP versions.
* Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
*/
$target = rtrim( $target, '/' );
if ( empty( $target ) ) {
$target = '/';
}
if ( file_exists( $target ) ) {
return @is_dir( $target );
}
// Do not allow path traversals.
if ( str_contains( $target, '../' ) || str_contains( $target, '..' . DIRECTORY_SEPARATOR ) ) {
return false;
}
// We need to find the permissions of the parent folder that exists and inherit that.
$target_parent = dirname( $target );
while ( '.' !== $target_parent && ! is_dir( $target_parent ) && dirname( $target_parent ) !== $target_parent ) {
$target_parent = dirname( $target_parent );
}
// Get the permission bits.
$stat = @stat( $target_parent );
if ( $stat ) {
$dir_perms = $stat['mode'] & 0007777;
} else {
$dir_perms = 0777;
}
if ( @mkdir( $target, $dir_perms, true ) ) {
/*
* If a umask is set that modifies $dir_perms, we'll have to re-set
* the $dir_perms correctly with chmod()
*/
if ( ( $dir_perms & ~umask() ) !== $dir_perms ) {
$folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
for ( $i = 1, $c = count( $folder_parts ); $i <= $c; $i++ ) {
chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
}
}
return true;
}
return false;
}
Changelog
| Version | Description |
|---|---|
| 2.0.1 | Introduced. |
Skip to note 4 content
Codex
Basic Example
if ( wp_mkdir_p( '/a/really/deep/sub/directory' ) ) { echo __( 'It worked! Now look for a directory named "a".', 'textdomain' ); }Skip to note 5 content
JCV
Should you need to create a folder with 777 permission (i.e. usefull for a cache folder), just do:
$cache_folder = ABSPATH . 'cache'; if ( ! is_dir( $cache_folder ) ) { wp_mkdir_p( $cache_folder ); chmod( $cache_folder, 0777 ); }Skip to note 6 content
Usman Ahmed
Creating a directory if doesn’t already exist.
if ( ! is_dir( ABSPATH . 'my-folder' ) ) { wp_mkdir_p( ABSPATH . 'my-folder' ); }