Превратить DirectoryIterator в сопоставляемый массив? - PullRequest
0 голосов
/ 12 июня 2018

Я хочу превратить список содержимого каталога в массив JSON на PHP (я очень новичок в 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?Я думаю, что это сделает код чище.

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Если у вас есть вложенные папки, вы должны использовать 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.

0 голосов
/ 12 апреля 2019
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;
        }, []);
    }
}
0 голосов
/ 12 июня 2018

iterator_to_array () в функции array_filter () возвращает массив объектов 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);

После этого вы можете использовать функции массива.Я рекомендую использовать встроенные итераторы .Посмотрите документацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...