массивы — PHP: как исправить array_pop и значение 0

Я пытаюсь из разных путей для создания размерного массива.
Для этого я использую найденную функцию Вот.

Мой код

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», даже если это строка?

-1

Решение

когда 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 что я думаю должен быть полезной заменой.

2

Другие решения

В моем случае я получил этот путь: 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"

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector