webiny / storage
Webiny 存储组件
Requires
- php: ^7
- webiny/config: ~1.6
- webiny/service-manager: ~1.6
- webiny/std-lib: ~1.6
Requires (Dev)
- mybuilder/phpunit-accelerator: dev-master
- phpunit/phpunit: ~6
- webiny/amazon: ~1.6
Suggests
- webiny/amazon: Allows you to store files on Amazon AWS S3
README
存储组件是一个存储抽象层,简化了您与文件和目录交互的方式。
安装组件
安装组件的最佳方式是使用 Composer。
composer require webiny/storage
要获取软件包的附加版本,请访问Packagist 页面。
用法
您需要使用存储驱动程序来访问不同的存储提供商,如本地磁盘、Amazon、Rackspace 等。
Webiny 框架提供 LocalStorageDriver
和 S3StorageDriver
,但使用内置接口集可以帮助您快速开发新的驱动程序。
以下驱动程序接口可用
DriverInterface
- 主要存储驱动程序接口TouchableInterface
- 用于支持touch
功能的驱动程序(修改时间的变化)SizeAwareInterface
- 用于可以访问文件size
的驱动程序DirectoryAwareInterface
- 用于可以处理目录的驱动程序AbsolutePathInterface
- 用于可以提供绝对文件路径的驱动程序(例如:/var/www/app/storage/myFile.txt)
配置存储服务
使用存储的最佳方式是定义一个存储服务。以下是一个使用 LocalStorageDriver
和 S3StorageDriver
定义服务的示例:注意:您可以使用 DIR 来动态构建文件路径。DIR 将被替换为包含当前配置文件的目录路径。
Storage: # You can optionally specify parameters for use in services definitions Parameters: Storage.Class: \Webiny\Component\Storage\Storage Storage.S3DriverArgs: - yourAccessKeyID - yourSecretAccessKey - webiny # Bucket name - false # Date folder structure - http://d47gcb3uej2zar.cloudfront.net # CDN domain Services: LocalStorage: Class: %Storage.Class% Arguments: Driver: Object: \Webiny\Component\Storage\Driver\Local\LocalStorageDriver ObjectArguments: - __DIR__/../../Public/Uploads # Absolute root path - http://admin.w3.com/Uploads # Web root path - false # DateFolderStructure - true # Create folder if it doesn't exist CloudStorage: Class: %Storage.Class% Arguments: Driver: Object: \Webiny\Component\Storage\Driver\AmazonS3\S3StorageDriver ObjectArguments: %Storage.S3DriverArgs% Tags: [cloud]
(这只是定义服务的一种方式。有关定义服务的详细文档,请参阅 ServiceManager
组件。)
使用您的新存储
为了使本地存储更容易、更灵活,有两个类:`\Webiny\Component\Storage\File\File` 和 `\Webiny\Component\Storage\Directory\Directory`。这两个类作为包装器,因此您永远不需要直接调用存储。此外,它们包含您将需要的在文件和目录上执行操作的方法。
让我们看看如何存储一个新的文件
// use StorageTrait // Get your storage service. Storage name is part of the service name after 'Storage.' $storage = $this->storage('LocalStorage'); // Create a file object with a key (file name) and a $storage instance $file = new File('file.txt', $storage); $contents = file_get_contents('https://w3schools.org.cn/images/w3schoolslogoNEW310113.gif'); $file->setContents($contents);
调用 setContents($contents)
后,内容将立即写入存储,并返回一个 bool
。
处理目录
有时您需要读取整个目录,按名称、扩展名等过滤文件。为此类型操作有一个特殊接口,`\Webiny\Component\Storage\Directory\DirectoryInterface
`。
由于并非所有存储引擎都支持目录,因此没有此接口的通用实现。然而,有一个名为 `Directory
` 的实现,它与本地文件存储配合得很好。读取目录有两种模式:`recursive`(递归)和`non-recursive`(非递归)。
Recursive
会递归地读取整个目录结构,并构建一个一维数组(目录对象不会被创建,但会返回它们的子文件)。当您需要一次性读取所有文件或按名称、扩展名等进行过滤时,这非常有用。Non-recursive
只会读取当前目录,并返回子 `Directory
` 和 `File
` 对象。然后您可以通过遍历子 `Directory
` 对象来深入。
读取目录(非递归模式)
// Get your storage service $storage = $this->storage('LocalStorage'); // Create a directory object with a key (directory name), $storage instance $dir = new Directory('2013', $storage); // Loop through directory object foreach($dir as $item){ if($item->isDirectory()){ // Do something with child Directory object } else { // Do something with File object } }
注意:直到您实际使用对象,目录文件不会被从存储中检索。
过滤文件(递归模式)
// Get your storage service $storage = $this->storage('LocalStorage'); // Read recursively $dir = new Directory('2013', $storage, true); // Get only PDF files $pdfFiles = $dir->filter('*.pdf'); // Count ZIP files $zipFiles = $dir->filter('*.zip')->count(); // Get files starting with 'log_' $logFiles = $dir->filter('log_*'); // You can also pass the result of filter directly to loops as `filter()` returns a new Directory object foreach($dir->filter('*.txt') as $file){ // Do something with your file }
注意:调用 `filter()
` 不会更改原始的 `Directory
` 对象,而是创建一个新的带有过滤结果的新 `Directory
` 对象,因此一旦您读取了根目录,您就可以使用任何条件多次进行过滤。
// Get your storage service $storage = $this->storage('LocalStorage'); // Read recursively and don't filter $dir = new Directory('2013', $storage, true); // Now you can manipulate the whole directory // Get number of all ZIP files in the directory tree $zipFiles = $dir->filter('*.zip')->count(); // Get number of all RAR files in the directory tree $zipFiles = $dir->filter('*.rar')->count(); // Get number of all LOG files in the directory tree $zipFiles = $dir->filter('*.log')->count(); // Now output all files in the directory without filtering them foreach($dir as $file){ echo $file->getKey(); }
删除目录
删除目录(这是递归进行的)非常简单
// Get your storage service $storage = $this->storage('LocalStorage'); // Get directory $dir = new Directory('2013', $storage); // This will delete the whole directory structure and fire FILE_DELETED event for each file along the way $dir->delete(); // If you don't want the events to be fired, pass as second parameter `false`: $dir->delete(false);
存储事件
当对文件执行某些操作时,会触发3种类型的事件
wf.storage.file_saved
(StorageEvent::FILE_SAVED)- 文件成功保存后触发。wf.storage.file_renamed
(StorageEvent::FILE_RENAMED)- 文件重命名后触发。wf.storage.file_deleted
(StorageEvent::FILE_DELETED)- 文件删除后触发。
所有3个事件都将\Webiny\Component\Storage\StorageEvent
的实例传递给它们的事件处理器。一旦处理器执行,您可以使用$event->getFile()
方法访问文件对象。
class Test { use EventManagerTrait; public function index(){ // Listen for StorageEvent::FILE_SAVED $this->eventManager()->listen(StorageEvent::FILE_SAVED)->handler(function(StorageEvent $event){ // Get the file object $file = $event->getFile(); }); } }
StorageEvent::FILE_RENAMED
事件还会将一个名为oldKey
的特别属性赋给事件对象,该属性包含重命名前的文件键值(这有助于您更新数据库记录等)。
class Test { use EventManagerTrait; public function index(){ // Listen for StorageEvent::FILE_RENAMED $this->eventManager()->listen(StorageEvent::FILE_RENAMED)->handler(function(StorageEvent $event){ // Get the file object $file = $event->getFile(); // $file now contains the file object with new key, and we need to get the old key $oldKey = $event->oldKey; $newKey = $file->getKey(); }); } }
资源
要运行单元测试,您需要使用以下命令
$ cd path/to/Webiny/Component/Storage/
$ composer.phar install
$ phpunit