Я пытаюсь из разных путей для создания размерного массива.
Для этого я использую найденную функцию Вот.
Мой код
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», даже если это строка?
когда 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
не будет делать правильное слияние этого. Возможно, вам также понадобится объединить объекты. Этот урок содержит реализацию mergeObjectsRecursively
что я думаю должен быть полезной заменой.
В моем случае я получил этот путь: update.json and 0/1/0/filename.zip
Как сказал @Barmar, проблема в том, что я пытаюсь преобразовать массив в объект json.
В PHP массив на самом деле все время является объектом, поэтому … $ arr = [«0» => [«1» => …]] для php равно: $ arr = [0 => [1 => …]]. В PHP 7.2.x каждый раз, когда вы будете объединять объекты,
"0"
как строковый ключ будет приведен к0
как инт.
последствия
1 с кодом json
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"}}}}
Это решение взломать, но я могу сделать разницу между ключом, который является путем "_0":{"_1":{"_0"
и ключ для индексации файла "0":"filename.zip"