Лучшие практики файловой системы

11

Я работаю над расширением Magento 2, которое требует чтения файлов из файловой системы.
При запуске сниффера php с использованием стандартов ECGM2 он жалуется на то, что я использую такие функции, как basenameили dirname.

Использование функции dirname () запрещено

или

Использование функции basename () запрещено

Какую обертку я должен использовать вместо тех, чтобы получить тот же эффект?

[РЕДАКТИРОВАТЬ]
Вот код, но это не имеет отношения к вопросу.
У меня есть класс коллекции, который расширяет \Magento\Framework\Data\Collection\Filesystemкласс, и я хочу перечислить эту коллекцию в сетке (ui-компоненты), и одно из действий в сетке - действие загрузки.
Для этого мне нужно получить фактическое имя файла, чтобы я мог отправить его в действие загрузки.

    // here $file is dynamic and it can be
    // folder/filename.xml or folder/subfolder/file.tar.gz
    //so there is no strict number of folders and subfolders.
    $file = $downloader->getRelativePath($packageName);
    $relativeFile = UmcFilesystem::VAR_DIR_NAME . '/' .$file;
    $absoluteFile = $rootDir->getAbsolutePath($relativeFile);
    if ($rootDir->isFile($relativeFile) && $rootDir->isReadable($relativeFile)){
        //I don't want to use `explode` just for the sake of avoiding basename
        $fileName = basename($absoluteFile);
        $this->fileFactory->create(
            $fileName,
            null,
            DirectoryList::VAR_DIR,
            'application/octet-stream',
            $rootDir->stat($relativeFile)['size']
        );

        $resultRaw = $this->resultRawFactory->create();
        $resultRaw->setContents($rootDir->readFile($relativeFile));
        return $resultRaw;
    } else {
       ...
    }
Мариус
источник
Можете ли вы поделиться частью своего кода, что вы пытаетесь прочитать файл из системы.
Дирен Васоя,
Я добавил немного кода, но он совершенно не имеет значения для вопроса. Вопрос как-то абстрактный. что я должен использовать вместо basename, чтобы сниффер кода не жаловался?
Мариус
Это похоже только на разрешение.
Ашиш Джагнани
Это не имеет ничего общего с разрешениями. Код работает правильно, но анализатор кода говорит, что не должен там использоваться basename. Пожалуйста, внимательно прочитайте вопрос.
Мариус

Ответы:

17

Мне тоже нужно было что-то подобное в последнее время. Единственное решение, которое я нашел, чтобы получить basenameи dirnameиспользовал:

\ Magento \ Framework \ Filesystem \ Io \ File

protected function someFunction()
{
    /** @var \Magento\Framework\Filesystem\Io\File $fileSystemIo **/
    $fileInfo = $this->fileSystemIo->getPathInfo('<absolutePath>');
    $basename = $fileInfo['basename'] 
    $dirname = $fileInfo['dirname'];
}

До этого я пытался использовать Magento\Framework\Filesystem\Directory\Writeи getDriver()безуспешно. С ними вы можете получить почти все, но не basename.

Jalogut
источник
ДА. Вот и все. Спасибо. Я присужду награду, как только мне позволят.
Мариус
Мариус, ты действительно собираешься реализовать это таким образом? [\ Magento \ Framework \ Filesystem \ Io \ File-> getpathinfo] [1] буквально вызывает только [pathinfo] [2], который, в свою очередь, вызывает basename и dirname [1]: github.com/magento/magento2/blob/develop/ lib / internal / Magento /… [2]: github.com/php/php-src/blob/master/ext/standard/string.c#L1662
Ричард
1
@Ричард. Я видел это. Сейчас мне нужно / я хочу избегать определенных функций. И в моем конкретном случае это прекрасно подходит, потому что у меня уже был экземпляр \Magento\Framework\Filesystem\Io\Fileинъекции в моем собственном классе для другой функциональности. Я просто не знал заранее о getPathInfoметоде.
Мариус
3

К счастью, git позволяет нам видеть, когда dirname и basename были запрещены , причина в том, что «Добавлены файлы»

Глядя на проблему для проекта ЭКГ, вы можете увидеть закрытые проблемы, такие как что-то плохое в file_exists? # 33 , Функции ошибок # 26 , что-то плохое в этих функциях? # 17 , Контекст / Объяснение для Правил # 12 , Использование функции iconv () запрещено # 14, что заставило бы меня думать, что первоначальный список запрещенных функций не получил слишком большого внимания, и magento, вероятно, поддаются изменению Запрещенный список.

Поиск по базе кода m2 показывает ~ = 78 результатов для базового имени, смеси переменных и кода, вызывающего базовое имя, включая мое любимое .

Я думаю, что если бы я был на вашем месте, я бы опубликовал вопрос на github и спросил бы zlik, думает ли он, что они принадлежат ему, или если M2 предоставляет оболочку

Ричард
источник
2

Вы можете использовать объект SplFileInfo()класса, может быть, это будет работать.

$info = new SplFileInfo('/path/to/foo.txt');
var_dump($info->getFilename())

может быть, это будет работать.

Вы также можете сослаться на этот URL.

чираг
источник
Спасибо за это. Это выглядит чище, но у вас есть пример кода, который делает это? Я хочу следовать основным стандартам.
Мариус
Вы можете сослаться на php.net/manual/en/splfileinfo.getfilename.php этот URL.
Чираг
2

Мое предложение будет использовать Magento/Backupмодуль в качестве примера.

Было бы интересно взглянуть на способ написания класса действий загрузки, поскольку он также имеет дело с реальными файлами для загрузки:

public function execute()
{
    /* @var $backup \Magento\Backup\Model\Backup */
    $backup = $this->_backupModelFactory->create(
        $this->getRequest()->getParam('time'),
        $this->getRequest()->getParam('type')
    );

    if (!$backup->getTime() || !$backup->exists()) {
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        $resultRedirect->setPath('backup/*');
        return $resultRedirect;
    }

    $fileName = $this->_objectManager->get('Magento\Backup\Helper\Data')->generateBackupDownloadName($backup);

    $this->_fileFactory->create(
        $fileName,
        null,
        DirectoryList::VAR_DIR,
        'application/octet-stream',
        $backup->getSize()
    );

    /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
    $resultRaw = $this->resultRawFactory->create();
    $resultRaw->setContents($backup->output());
    return $resultRaw;
}

Для меня вы должны посмотреть, как этот метод генерирует файл для загрузки, используя \Magento\Framework\App\Response\Http\FileFactoryи generateBackupDownloadNameиз Magento\Backup\Helper\Data(обратите внимание на рекомендуемое использование OM;))

Еще один интересный бит

Еще одна интересная вещь, на которую стоит обратить внимание, это getStorageDataметодMagento\MediaStorage\Model\ResourceModel\File\Storage\File которых сам по себе вызывает непосредственно dirnameи , basenameно если вы вызвать этот метод ядра в модуле, вы не получите запрещенные ошибки;)

public function getStorageData($dir = '/')
{
    $files = [];
    $directories = [];
    $directoryInstance = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA);
    if ($directoryInstance->isDirectory($dir)) {
        foreach ($directoryInstance->readRecursively($dir) as $path) {
            $itemName = basename($path);
            if ($itemName == '.svn' || $itemName == '.htaccess') {
                continue;
            }
            if ($directoryInstance->isDirectory($path)) {
                $directories[] = [
                    'name' => $itemName,
                    'path' => dirname($path) == '.' ? '/' : dirname($path),
                ];
            } else {
                $files[] = $path;
            }
        }
    }

    return ['files' => $files, 'directories' => $directories];
}

В аналогичной идее есть также collectFileInfoотMagento\MediaStorage\Helper\File\Media

Рафаэль в цифровом пианизме
источник
generateBackupDownloadNameиспользует некоторые магические геттеры из резервной модели. Поэтому им нужно было вызвать магических сеттеров раньше. Я не вижу ничего связанного с базовым именем или альтернативой ему.
Мариус
@Marius см. Мой обновленный ответ для другого возможного пути
Рафаэль в Digital Pianism
Это может сработать. Я попробую и вернусь с результатами.
Мариус
@Marius также чек collectFileInfoот Magento\MediaStorage\Helper\File\Media;)
Рафаэль в Digital Pianism
collectFileInfoне поможет мне, потому что он ожидает файл в папке мультимедиа. Мой находится в папке var. Также не getStorageDataимеет ничего общего с тем, что мне нужно. Я не хочу собирать все файлы в папку. У меня уже есть имя файла.
Мариус