josbeir/cakephp-filesystem

CakePHP 4.0+ 文件系统插件

安装次数: 11,222

依赖者: 0

建议者: 0

安全性: 0

星标: 20

关注者: 6

分支: 10

开放问题: 3

类型:cakephp-plugin

3.0.2 2023-02-07 13:06 UTC

This package is not auto-updated.

Last update: 2024-09-23 22:03:12 UTC


README

Software License Build Status codecov Latest Stable Version Total Downloads

CakePHP 文件系统插件

CakePHP 文件系统插件,使用 Flysystem 作为后端。

原因

  • 在您的应用程序中轻松访问 Flysystem 文件系统
  • 上传归一化,接受 $_FILES、Zend\Diactoros\UploadedFile 或本地文件系统上的路径
  • 文件由可自定义和可 JSON 序列化的实体表示,多个文件通过自定义 Collection 实例返回。
  • 有一个 trait 可用,您可以在应用程序的任何地方使用它
  • 上传期间可自定义路径/文件名格式,支持自定义格式化器,附带 Default 和 EntityFormatter。

需求

  • CakePHP 4.x
  • PHP 7.2

安装

您可以使用 composer 将此插件安装到您的 CakePHP 应用程序中。

安装 composer 包的推荐方法是

composer require josbeir/cakephp-filesystem

配置

应在您的 Configure 实例中提供文件系统配置数组。您可以创建一个 config/filesystems.php 文件,内容如下。请确保在 bootstrap.php 中使用 Configure::load('filesystems', 'default'); 加载该文件。

为每个 'filesystem' 定义的配置选项直接传递给 Filesystem.php 类。当使用 FilesystemAwareTrait / FilesystemRegistry 类时,必须设置 default 配置。

<?php
return [
    'Filesystem' => [
        'default' => [
            'adapter' => 'League\Flysystem\Local\LocalFilesystemAdapter', // default
            'adapterArguments' => [ WWW_ROOT . 'files' ]
        ],
        'other' => [
            'adapter' => 'League\Flysystem\Local\LocalFilesystemAdapter',
            'adapterArguments' => [ WWW_ROOT . 'cache' ],
            'entityClass' => '\My\Cool\EntityClass',
            'formatter' => '\My\Cool\Formatter'
        ]
    ]
];

简单的上传示例

可以从任何使用 FilesystemAwareTrait 并调用 MyClass::getFilesystem($configKey)FilesystemRegistry::get() 的位置访问 Filesystem 实例。

在这个例子中,我们使用一个虚构的 'myfs' 文件系统定义,如果您将其留空,则在调用 getFilesystem() 时将使用默认 FS。

通过 POST 提交的上传数据

 [
    'tmp_name' => '/tmp/blabla',
    'filename' => 'lame filename.png',
    'error' => 0,
    'size' => 1337,
    'type' => 'image/png'
]

示例控制器

<?php
namespace App\Controller;

use Josbeir\Filesystem\FilesystemAwareTrait;

class MyController extends AppController {

    use FilesystemAwareTrait;

    public function upload()
    {
        $fileEntity = $this->getFilesystem('myfs')->upload($this->request->getData('upload'));

        debug($fileEntity);
    }
}

结果

上述示例的结果将输出一个文件实体类

object(Josbeir\Filesystem\FileEntity) {

    'uuid' => 'a105663a-f1a5-40ab-8716-fac211fb01fd',
    'path' => 'articles/now_im_called_bar.png',
    'filename' => 'lame filename.png',
    'filesize' => (int) 28277,
    'mime' => 'image/png',
    'hash' => '6b16dafccd78955892d3eae973b49c6c',
    'meta' => null,
    'created' => object(Cake\I18n\Time) {

        'time' => '2018-05-27T15:31:54+00:00',
        'timezone' => '+00:00',
        'fixedNowTime' => false

    }

}

实体属性

当文件成功上传时返回一个可 JSON 序列化的 FileEntity ArrayObject。属性可以通过 get** 和 set** 以及 has** 访问、检查和操作

$entity->hasUuid('a105663a-f1a5-40ab-8716-fac211fb01fd');
$entity->getUuid() // a105663a-f1a5-40ab-8716-fac211fb01fd
$entity->setUuid('a105663a-f1a5-40ab-8716-fac211fb01fd');
...
...

对实体调用 json_encode

// json_encode($entitiy);
{
    "uuid": "3ae258dd-ab1d-425c-b3b0-450f0c702d64",
    "path": "dummy.png",
    "filename": "dummy.png",
    "size": 59992,
    "mime": "image\/png",
    "hash": "3ba92ed92481b4fc68842a2b3dcee525",
    "created": "2018-06-03T09:27:41+00:00",
    "meta": null
}

重建实体

如果您将文件实体作为 JSON 对象保存在某处,则可以使用 Filemanager::newEntity 重建实体

$entity = $this->getFilesystem()->newEntity([
    'uuid' => 'a105663a-f1a5-40ab-8716-fac211fb01fd',
    'path' => 'articles/now_im_called_bar.png',
    'filename' => 'lame filename.png',
    'filesize' => 28277,
    'mime' => 'image/png',
    'hash' => '6b16dafccd78955892d3eae973b49c6c',
    'created' => '2018-05-27T15:31:54+00:00',
    "meta": [
        "extra" => "stuf"
    ]
]);

重建实体的 Collection

$entities = FileEntityCollection::createFromArray($entities [, string $filesystem]);

使用自己的实体

通过实现 FileEntityInterface 类并设置配置中的实体类 FQCN,可以创建自己的实体。

使用 Cake ORM 实体代替内置实体类的示例

如果您想将实体存储在 ORM 中,可以轻松地将实体类与 ORM 替换。唯一的要求是实体实现 FileEntityInterface 类。

return [
    'Filesystem' => [
        'default' => [
            'entityClass' => 'App\Model\Entity\MyFileEntity'
        ]
]

然后确保您的 ORM 实体实现 FileEntityInterface 并其所需的方法 'getPath'

namespace App\Model\Entity;

use Cake\ORM\Entity;
use Josbeir\Filesystem\FileEntityInterface;

class MyFileEntity extends Entity implements FileEntityInterface
{
    public function getPath() : string
    {
        return $this->path;
    }

    public function setPath(string $path) : FileEntityInterface
    {
        $this->set('path', $path);

        return $this;
    }
}

现在,在上传和使用文件时,您可以与 ORM 实体一起工作。

格式化器

在上传过程中,使用格式化器来构建路径和文件名。例如,如果您使用EntityFormatter,则可以使用实体中可用的变量来构建文件名。

$entity = $this->Posts->get(1);

$fileEntity = $this->getFilesystem()->upload(TMP . 'myfile.png', [
    'formatter' => 'Entity', // formatter to use
    'data' => $entity // data to pass to the formatter
]);

默认的EntityFormatter模式是{entity-source}/{file-name}.{file-ext},结果为posts/myfile.png

设置格式化器

格式化器是用于在上传过程中命名和清理文件路径的简单类,此插件目前包含两个格式化器。

  • DefaultFormatter,这仅返回'清理后的'文件名
  • EntityFormatter,扩展默认格式化器,期望使用EntityInterface作为数据,并用于根据实体数据格式化文件名。
$entity = $this->Posts->get(1);

$this->getFilesystem()
    ->upload(TMP . 'myfile.png', [
        'formatter' => 'Entity',
        'data' => $entity,
        'pattern' => '{entity-source}/{date-y}-{date-m}-{date-d}-{file-name}-{custom}.{file-ext}',
        'replacements' => [ 'custom' => 'key' ] // extra replacement patterns
    ]);

结果应类似于posts/2018-05-26-myfile-key.png

创建自定义格式化器类

创建自己的格式化器类相对简单。该类应实现FormatterInterface。有关更多信息,请检查DefaultFormatterEntityFormatter类。

示例自定义格式化器

<?php
namespace \Path\To\Formatters

use Josbeir\Filesystem\DefaultFormatter;

class MyFormatter extends DefaultFormatter
{
    // Extra settings?
    protected $_defaultConfig = [
        'mysetting1' => 'hello'
        'mysetting2' => 'world'
    ];

    public function getPath() : string
    {
        $setting = $this->getConfig('mysetting1');
        $setting2 = $this->getConfig('mysetting2');

        return $setting . DS . $setting2 . DS . $this->getBaseName();
    }
}

在您的应用程序中使用自定义格式化器类

格式化器的FQCN可以在文件系统配置中设置或每次调用setFormatter时设置。

$file = $this->getFilesystem()
    ->setFormatter('\Path\To\Formatters\MyFormatter')
    ->upload($file, [
        'mysetting2' => 'cool',
    ]);

debug($file->getPath()) // hello/cool/myfile.png

方法

Filesystem类本身实现了一些关于Flysystem文件系统类的便利方法。

其他方法被代理。如果您希望直接使用Flysystem实例,请使用getDisk()。

// Upload a file
// Will fire Filesystem.beforeUpload and Filesystem.afterUpload
$this->getFilesystem()->upload($data, $config);

// Upload multiple files and returns a FileEntityCollection
// Will fire Filesystem.beforeUpload and Filesystem.afterUpload (after each file upload)
$this->getFilesystem()->uploadMany($files, $config);

// Copy an entity
// Will fire Filesystem.beforeCopy and Filesystem.afterCopy
$this->getFilesystem()->copy($entity, $config);

// Rename an entity
// Will fire Filesystem.beforeRename and Filesystem.afterRename
$this->getFilesystem()->rename($entity, $config);

// Delete an entity from the FS
// Will fire Filesystem.beforeDelete and Filesystem.afterDelete
$this->getFilesystem()->delete($entity);

// Check if a file entity exists on the FS
$this->getFilesystem()->exists($entity);

// Get Flysystem FS instance
$this->getFilesystem()->getDisk();

// Get Flysystem adatapter
$this->getFilesystem()->getAdapter();

// Set the formatter class name to be used
$this->getFilesystem()->setFormatter($name);

// Return a new formatter instance
$this->getFilesystem()->newFormatter($filename, $config);

// Reset formatter and adapter to default configuration
$this->getFilesystem()->reset();

事件

在对文件实体执行操作时将分发事件。目前实现了以下事件

附加功能

更改实体中使用的哈希算法

可以使用文件系统实例配置中的'normalizer'参数将选项传递给FileSourceNormalizer。

<?php
return [
    'Filesystem' => [
        'default' => [
            'adapter' => 'League\Flysystem\Local\LocalFilesystemAdapter',
            'adapterArguments' => [ WWW_ROOT . 'assets' . DS . 'local' ],
            'normalizer' => [
                'hashingAlgo' => 'sha1'
            ]
        ]
    ]
]

访问 Flysytem 对象

因为此插件在核心使用flysystem,所以可以轻松与其他flysystem兼容的代码集成。可以直接使用Filesystem::getDisk()访问flysystem。

例如,我们可以使用Admad的glide插件,并使用配置的文件系统作为源和缓存。

首先设置默认和缓存配置

<?php
return [
    'Filesystem' => [
        'default' => [
            'adapter' => 'League\Flysystem\Local\LocalFilesystemAdapter',
            'adapterArguments' => [ WWW_ROOT . 'assets' . DS . 'local' ],
            'entityClass' => 'App\Model\Entity\FilesystemFile'
        ],
        'cache' => [
            'adapter' => 'League\Flysystem\Local\LocalFilesystemAdapter',
            'adapterArguments' => [ WWW_ROOT . 'assets' . DS . 'cached' ],
        ]
    ]
];

然后使用上面提到的配置文件系统设置Glide中间件

use FilesystemAwareTrait;

..
..

$routes->registerMiddleware('glide', new GlideMiddleware([
    'server' => [
        'source' => $this->getFilesystem()->getDisk(),
        'cache' => $this->getFilesystem('cache')->getDisk()
    ]
]));

$routes->scope('/images', [ 'cache' => false ], function ($routes) {
    $routes->applyMiddleware('glide');
    $routes->connect('/*');
});

贡献

在提交PR之前,请确保