【问题标题】:PHP : How to fix array_pop and the value 0PHP:如何修复 array_pop 和值 0
【发布时间】:2018-12-14 23:07:31
【问题描述】:

我正在尝试从各种路径生成维度数组。 为此,我正在使用 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”,这似乎也能正常工作。
  • @cmbuckley,非常感谢!我真的累了。问题是因为json_encode 传递的结果删除了零键。
  • 请将其添加到问题中。

标签: php arrays array-population


【解决方案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 可能不会对此进行正确的合并。您可能还需要合并对象。 This tutorial 包含 mergeObjectsRecursively 的实现,我认为它应该是一个有用的替代品。

【讨论】:

  • 我用过JSON_FORCE_OBJECT,但我的问题是下面这个:/0/1/0/filename.zip返回这个:a:1:{i:0;a:1:{i:1;a:1:{i:0;a:1:{i:0;s:23:"filename.zip";}}}},所以在根目录中多了一个文件,我得到了这个:{"0":"update.json","1":{"1":{"0":{"0":"filename.zip"}}}}而不是@987654334 @
  • 您正在混合真正的数组和应该以“0”为键的关联数组?这更难。
  • 是的,有点乱。我不知道我是否应该修改get_dir_content_to_array 并制作不同的结构或数组,或者为json_encode 选择正确的选项。
  • 如果我做一个 hack :$path = [ "_" . $pathPart => $path ];,当然可以,但会有点痛。
  • 暂时不行。我添加了完整的代码来帮助测试它。我得到了这个结果:O:8:"stdClass":1:{s:1:"0";O:8:"stdClass":1:{s:1:"1";O:8:"stdClass":1:{s:1:"0";O:8:"stdClass":1:{s:23:"filename.zip";a:1:{i:0;N;}}}}}json_encode 给出了null 结果。
【解决方案2】:

就我而言,我得到了这条路径:update.json and 0/1/0/filename.zip

正如@Barmar 所说,基本上,问题出在我尝试将数组转换为 json 对象时。

在PHP中,数组其实一直都是一个对象,所以... $arr = [ "0" => [ "1" => ... ] ] 对于php,等于:$arr = [ 0 => [ 1 => ... ] ]。在 PHP 7.2.x 中,每次合并对象时,"0" as string 键将被强制转换为 0 as 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.

为了保持路径的正确顺序,我暂时找到了一个 hacky 解决方案:

在每个键前添加下划线

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"}}}}

这个解决方案是一个 hack,但我可以区分路径 "_0":{"_1":{"_0" 的 kee 和索引文件的键 "0":"filename.zip"

【讨论】:

  • 您的结果有键 "0""_0",这似乎有问题。我认为问题可能是您试图在同一个对象中混合索引和键控数据。
  • 是的,你没事。有一个混合索引。这就是为什么我添加一个下划线来区分作为目录名“_0”、“_1”的键和 0,1,2... 这是一个常见的索引。另一种方法可能是做一个更大的对象,其中 dirname 是一个值,键可以是“dir”或“file”或类似的东西。
猜你喜欢
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 2013-07-30
  • 2021-11-30
  • 2022-11-17
  • 2015-02-03
  • 1970-01-01
  • 2019-12-05
相关资源
最近更新 更多