函数文档

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.

Return

bool Whether the path was created. True if path already exists.

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.

User Contributed Notes