我想将目录内容列表转换为PHP中的JSON数组(我是PHP的新手)。我知道这有效:
// this code works
$base_dir = './posts/';
$directory_iterator = new Directoryiterator($base_dir);
$file_array = [];
foreach($directory_iterator as $file) {
if(!$file->isDot()) {
$file_array[] = $file->getFilename();
}
}
echo json_encode($file_array);
但是,我认为使用聚合函数(过滤器然后映射)而不是迭代它可能更简洁。我想在JavaScript中会看起来像这样:
// this is what I'd imagine it looks like in JS
Array.from(directory_iterator)
.filter(file => !file.isDot())
.map(file => file.getFilename())
我尝试使用iterator_to_array
将迭代器转换为数组以执行聚合函数,然后使用array_filter
和array_map
,如下所示:
// this doesn't work
$file_array = array_map(
function($file) { return $file->getFilename(); },
array_filter(
iterator_to_array($directory_iterator),
function($file) { return !$file->isDot(); })
);
但结果是:
Array
(
[0] =>
[1] =>
[2] =>
)
当我在var_dump($file->getFilename())
回调中运行array_filter()
时,它会给我string(0) ""
。所以我猜测原始迭代器到数组的转换是错误的。
我在这里做错了什么? iterator_to_array()
不是将DirectoryIterator
对象转换为文件对象数组的正确函数吗?
其次,是否存在作为数组方法的map和filter函数,而不是将数组作为参数,类似于JavaScript?我认为这会使代码更清晰。
答案 0 :(得分:2)
array_filter()函数中的iterator_to_array()返回一个DirectoryIterator对象数组。然后你运行的是array_map,它试图在该数组中的每个DirectoryIterator对象上应用一个函数。这就是为什么你得到一个空列表。
使用' RecursiveDirectoryIterator'查看以下内容。
// flattens the directory
$it = new RecursiveDirectoryIterator(new DirectoryIterator($dir));
// creates a map - file path as the key and SPLFileInfo as the value
$map = iterator_to_array($it);
// some array functions to use for example;
$filePaths = array_keys($map);
// returns an array of SPLFileInfo objects
$files = array_values($map)
// applies a function on each element in $map - modifies it
array_walk($map, function(&$value, $key) {
$value = $key . ' => ' . $value->getFilename();
});
// modified
var_dump($map);
之后您可以使用数组函数。我建议使用内置iterators。查看文档。
答案 1 :(得分:1)
如果您有嵌套文件夹,则应使用RecursiveDirectoryIterator
和RecursiveIteratorIterator
。要跳过点,请使用FilesystemIterator::SKIP_DOTS
标记。然后你可以获得如下路径:
$iterator = new RecursiveDirectoryIterator(__DIR__ . '/test/', FilesystemIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator($iterator);
$paths = array_keys(iterator_to_array($iterator));
迭代器通常是递归的,因此PHP中没有本地map
和filter
函数。要过滤迭代器,您可以使用FilterIterator
或RecursiveFilterIterator
。
答案 2 :(得分:0)
use RecursiveDirectoryIterator;
use SplFileInfo;
class DirectoryContentProvider implements DirectoryContentProviderInterface
{
/**
* @param string $path
*
* @return SplFileInfo[]
*/
public function getContent(string $path): array
{
$iterator = new RecursiveDirectoryIterator($path);
$list = iterator_to_array($iterator);
return array_reduce($list, function (array $carrier, SplFileInfo $file) {
if ($file->isFile()) {
$carrier[] = $file;
}
return $carrier;
}, []);
}
}