我正在尝试从各种路径生成维数组。 为此,我使用的是找到的here函数。
我的代码
function get_dir_content_to_array( string $dir_path, string $dir_filter = null, string $file_filter = null ) {
if( is_dir_empty( $dir_path ) )
return false;
$output = array();
$files = get_subdir_filtered( $dir_path, $dir_filter, $file_filter );
if ( isset( $files ) ) {
foreach ( $files as $name => $object ) {
if ( $object->getFilename() !== "." && $object->getFilename() !== ".." ) {
// Split by the delimiter.
$delimiter = "/";
$name = str_replace( "\\", $delimiter, $name );
$relative_path = str_replace( $dir_path, "", $name );
$a_relative_path = explode( $delimiter, $relative_path );
$path = [ array_pop( $a_relative_path ) ];
foreach ( array_reverse( $a_relative_path ) as $pathPart ) {
$path = [ $pathPart => $path ];
}
// Add it to a temp list.
$paths[] = $path;
}
$output = call_user_func_array( 'array_merge_recursive', $paths );
}
}
return $output;
}
function get_subdir_filtered( $dir_path, $dir_filter, $file_filter ) {
$path = realpath( $dir_path );
$directory = new \RecursiveDirectoryIterator( $path );
$files = null;
if ( ! empty( $dir_filter ) || ! empty( $file_filter ) ) {
if ( ! empty( $dir_filter ) ) {
$filter = new DirnameFilter( $directory, $dir_filter );
}
if ( ! empty( $file_filter ) ) {
$filter = new FilenameFilter( $filter, $file_filter );
}
$files = new \RecursiveIteratorIterator( $filter );
} else {
$files = new \RecursiveIteratorIterator( $directory );
}
return $files;
}
class DirnameFilter extends FilesystemRegexFilter {
// Filter directories against the regex
public function accept() {
return ( ! $this->isDir() || preg_match( $this->regex, $this->getFilename() ) );
}
}
除文件夹名为“ 0”时有效之外
我该如何解决? 为什么array_pop即使是字符串也跳过值“ 0”?
答案 0 :(得分:2)
当json_encode()
对键为以0
开头的连续整数或其等效字符串的数组进行编码时,它将生成JSON数组而不是对象。
您可以使用JSON_FORCE_OBJECT
标志,但是这会将文件夹内的文件名数组转换为不需要的对象。
您可以做的是使用PHP对象而不是数组来表示文件夹。 json_encode()
会将其编码为对象,即使它具有数字属性。
我认为这可以做到:
function get_dir_content_to_array( string $dir_path, string $dir_filter = null, string $file_filter = null ) {
if( is_dir_empty( $dir_path ) )
return false;
$output = array();
$files = get_subdir_filtered( $dir_path, $dir_filter, $file_filter );
if ( isset( $files ) ) {
foreach ( $files as $name => $object ) {
if ( $object->getFilename() !== "." && $object->getFilename() !== ".." ) {
// Split by the delimiter.
$delimiter = "/";
$name = str_replace( "\\", $delimiter, $name );
$relative_path = str_replace( $dir_path, "", $name );
$a_relative_path = explode( $delimiter, $relative_path );
$path = [ array_pop( $a_relative_path ) ];
foreach ( array_reverse( $a_relative_path ) as $pathPart ) {
$folder = new StdClass;
$folder->{$pathPart} = $path;
$path = $folder;
}
// Add it to a temp list.
$paths[] = $path;
}
$output = call_user_func_array( 'array_merge_recursive', $paths);
}
}
return $output;
}
我没有测试它,因为我没有get_subdir_filtered()
函数。 array_merge_recursive
可能无法正确合并。您可能还需要合并对象。 This tutorial包含一个mergeObjectsRecursively
的实现,我认为这应该是一个有用的替代方法。
答案 1 :(得分:0)
就我而言,我的路径是:update.json and 0/1/0/filename.zip
正如@Barmar所说,基本上,问题是当我尝试将数组转换为json对象时。
在PHP中,数组实际上一直是对象,因此... $ arr = [“ 0” => [“ 1” => ...]]对于php,等于:$ arr = [0 => [1 => ...]]。在PHP 7.2.x中,每次合并对象时,
"0"
作为字符串键将被转换为0
作为int。
后果
1。带有json_encode
echo json_encode( get_dir_content_to_array(...) );
//result = ["update.json",{"1":[["filename.zip"]]}]
2。与json_encode和JSON_FORCE_OBJECT
echo json_encode( get_dir_content_to_array(...), JSON_FORCE_OBJECT );
//result = {"0":"update.json","1":{"1":{"0":{"0":"filename.zip"}}}}
//I got 1,0,0,filename.zip instead of 0,1,0,filename.zip
3。添加(字符串)
$path = [array_pop( $a_relative_path)];
foreach ( array_reverse( $a_relative_path ) as $pathPart ) {
$path = [ (string) $pathPart => $path ];
}
//Same result of 2.
为了保持正确的路径顺序,我暂时发现了一个棘手的解决方案:
在每个键之前添加下划线
foreach ( array_reverse( $a_relative_path ) as $pathPart ) {
$path = [ "_" . $a_relative_path => $path ];
}
//result = {"0":"update.json", "_0":{"_1":{"_0":{"0":"filenamezip"}}}}
//With a new file path, I got this :
// {"0":"update.json","_toto":{"_foo":{"0":"test.txt"}},"_0":{"_1":{"_0":{"0":"filename.zip"}}}}
此解决方案是骇客,但我可以在kee(路径"_0":{"_1":{"_0"
和索引文件"0":"filename.zip"
的密钥)之间有所作为