zenstruck / filesystem
league/flysystem 的包装器,具有替代 API 和附加功能。
Requires
- php: >=8.1
- league/flysystem: ^3.11
- zenstruck/image: ^1.0
- zenstruck/stream: ^1.2
- zenstruck/temp-file: ^1.2.1
- zenstruck/uri: ^2.2
Requires (Dev)
- doctrine/doctrine-bundle: ^2.8
- doctrine/orm: ^2.14|^3.0
- league/flysystem-async-aws-s3: ^3.10
- league/flysystem-ftp: ^3.10
- league/flysystem-memory: ^3.10
- league/flysystem-read-only: ^3.10
- league/flysystem-sftp-v3: ^3.10
- league/flysystem-ziparchive: ^3.12
- league/glide: ^2.2
- league/mime-type-detection: >=1.8
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9.6.18
- srwiez/thumbhash: ^1.2
- symfony/browser-kit: ^6.4|^7.0
- symfony/form: ^6.4|^7.0
- symfony/framework-bundle: ^6.4|^7.0
- symfony/mime: ^6.4|^7.0
- symfony/phpunit-bridge: ^6.1|^7.0
- symfony/serializer: ^6.4|^7.0
- symfony/stopwatch: ^6.4|^7.0
- symfony/string: ^6.4|^7.0
- symfony/twig-bundle: ^6.4|^7.0
- symfony/validator: ^6.4|^7.0
- symfony/var-dumper: ^6.4|^7.0
- symfony/yaml: ^6.4|^7.0
- twig/twig: ^3.6
- zenstruck/assert: ^1.2
- zenstruck/console-test: ^1.4
- zenstruck/foundry: ^1.30.3
This package is auto-updated.
Last update: 2024-09-16 00:40:32 UTC
README
此库是对优秀的 league/flysystem 文件存储抽象 库的包装。它提供了一个 替代 API,以下是一些主要变更:
- 主要区别在于
Directory
、File
和Image
对象的概念。这些都是单个 文件系统节点 的包装器,提供信息、元数据以及更多功能。它们可以传递(即发送到您的模板)或甚至用作 Doctrine 类型。 - 合并某些 Flysystem 方法。例如,
delete()
删除文件和目录,write()
可以写入字符串和流(+更多)。 - 简化了将文件系统文件用作 真实、本地文件 的使用。许多第三方库在处理文件时需要本地文件。
此外,还提供了以下功能:
- 文件系统 包装器 以添加附加功能(例如
MultiFilesystem
和LoggableFilesystem
)。 - 强大的 测试辅助工具。
ZipFile
/TarFile
代表一个本地 zip/tar(.gz/bz2) 文件,它同时作为文件系统 和 真实文件。- Doctrine 集成.
- Symfony 集成
安装
composer require zenstruck/filesystem
API
文件系统
/** @var \Zenstruck\Filesystem $filesystem */ // read operations $filesystem->has('some/path'); // bool $filesystem->node('some/path'); // Zenstruck\Filesystem\Node\File|Zenstruck\Filesystem\Node\Directory or throws NodeNotFound $filesystem->file('some/path.txt'); // Zenstruck\Filesystem\Node\File or throws NodeNotFound or NodeTypeMismatch (if exists but not a file) $filesystem->image('some/path.png'); // Zenstruck\Filesystem\Node\File\Image or throws NodeNotFound or NodeTypeMismatch (if exists but not an image) $filesystem->directory('some/path'); // Zenstruck\Filesystem\Node\Directory or throws NodeNotFound or NodeTypeMismatch (if exists but not a directory) // write operations (returns Zenstruck\Filesystem\File) $filesystem->write('some/path.txt', 'string contents'); // write a string $filesystem->write('some/path.txt', $resource); // write a resource $filesystem->write('some/path.txt', new \SplFileInfo('path/to/local/file.txt')); // write a local file $filesystem->write('some/path.txt', $file); // write a Zenstruck\Filesystem\Node\File $filesystem->copy('from/file.txt', 'dest/file.txt'); // Zenstruck\Filesystem\Node\File (dest/file.txt) $filesystem->move('from/file.txt', 'dest/file.txt'); // Zenstruck\Filesystem\Node\File (dest/file.txt) $filesystem->delete('some/file.txt'); // returns self $filesystem->delete('some/directory'); // returns self // mkdir operations (returns Zenstruck\Filesystem\Node\Directory) $filesystem->mkdir('some/directory'); // create an empty directory $filesystem->mkdir('some/prefix', $directory); // create directory with files from Zenstruck\Filesystem\Node\Directory $filesystem->mkdir('some/prefix', new \SplFileInfo('path/to/local/directory')); // create directory with files from local directory $filesystem->chmod('some/file.txt', 'private'); // Zenstruck\Filesystem\Node (some/file.txt) // utility methods $filesystem->name(); // string - human-readable name for the filesystem
节点
接口:Zenstruck\Filesystem\Node
。
/** @var \Zenstruck\Filesystem\Node $node */ $node->path(); // Zenstruck\Filesystem\Node\Path $node->path()->toString(); // string - the full path (string) $node->path(); // same as above $node->path()->name(); // string - filename with extension $node->path()->basename(); // string - filename without extension $node->path()->extension(); // string|null - file extension $node->path()->dirname(); // string - the parent directory $node->dsn(); // Zenstruck\Filesystem\Node\Dsn $node->dsn()->toString(); // string - <filesystem-name>://<full-path> (string) $node->dsn(); // same as above $node->dsn()->path(); // Zenstruck\Filesystem\Node\Path $node->dsn()->filesystem(); // string - name of the filesystem this node belongs to $node->directory(); // Zenstruck\Filesystem\Node\Directory|null - parent directory object $node->visibility(); // string - ie "public" or "private" $node->lastModified(); // \DateTimeImmutable (in currently configured timezone) $node->isDirectory(); // bool $node->isFile(); // bool $node->isImage(); // bool $node->exists(); // bool $node->ensureExists(); // static or throws NodeNotFound $node->refresh(); // static and clears any cached metadata $node->ensureDirectory(); // Zenstruck\Filesystem\Node\Directory or throws NodeTypeMismatch (if not a directory) $node->ensureFile(); // Zenstruck\Filesystem\Node\File or throws NodeTypeMismatch (if not a file) $node->ensureImage(); // Zenstruck\Filesystem\Node\Image or throws NodeTypeMismatch (if not an image)
文件
接口:Zenstruck\Filesystem\Node\File
(继承自 Node
)。
/** @var \Zenstruck\Filesystem\Node\File $file */ $file->contents(); // string - the file's contents $file->stream(); // \Zenstruck\Stream - wrapper for a resource $file->read(); // "raw" resource $file->size(); // int $file->guessExtension(); // string|null - returns extension if available or attempts to guess from mime-type $file->checksum(); // string - using FilesystemAdapter's default algorithm $file->checksum('md5'); // string - specify the algorithm $file->publicUrl(); // string (needs to be configured) $file->temporaryUrl(new \DateTimeImmutable('+30 minutes')); // string - expiring url (needs to be configured) $file->temporaryUrl('+30 minutes'); // equivalent to above $file->tempFile(); // \SplFileInfo - temporary local file that's deleted at the end of the script
注意
有关 File::tempFile()
的更多详细信息,请参阅 zenstruck/temp-file
。
注意
有关 File::stream()
的更多详细信息,请参阅 zenstruck/stream
。
PendingFile
类:Zenstruck\Filesystem\Node\File\PendingFile
(继承自 \SplFileInfo
并实现 File
)。
use Zenstruck\Filesystem\Node\File\PendingFile; $file = new PendingFile('/path/to/local/file.txt'); $file->path()->toString(); // "/path/to/local/file.txt" /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $uploadedFile */ $file = new PendingFile($uploadedFile); $file->path()->toString(); // $uploadedFile->getClientOriginalName()
图像
接口:Zenstruck\Filesystem\Node\File\Image
(继承自 File
)。
/** @var \Zenstruck\Filesystem\Node\File\Image $image */ $image->dimensions(); // Zenstruck\Image\Dimensions $image->dimensions()->height(); // int $image->dimensions()->width(); // int $image->dimensions()->pixels(); // int $image->dimensions()->aspectRatio(); // float $image->dimensions()->isSquare(); // bool $image->dimensions()->isPortrait(); // bool $image->dimensions()->isLandscape(); // bool $image->exif(); // array - image exif data if available $image->iptc(); // array - image iptc data if available $thumbHash = $image->thumbHash(); // Zenstruck\Image\Hash\ThumbHash (requires srwiez/thumbhash) $thumbHash->dataUri(); // string - data uri for the thumb $thumbHash->key(); // string - hash for the thumb (to store in database/cache) $image->transformUrl('filter-name'); // string (needs to be configured) $image->transformUrl(['w' => 100, 'h' => 50]); // string (needs to be configured) $image->transform( function(ManipulationObject $image) { // make manipulations return $image; } ); // PendingImage
注意
有关 Image::transform()
和 Image::thumbHash()
的更多详细信息,请参阅 zenstruck/image
。
PendingImage
类:Zenstruck\Filesystem\Node\File\Image\PendingImage
(继承自 PendingFile
并实现 Image
)。
use Zenstruck\Filesystem\Node\File\Image\PendingImage; $image = new PendingImage('/path/to/local/file.txt'); $image = new PendingImage($symfonyUploadedFile); // transform and overwrite $image->transformInPlace( function(ManipulationObject $image) { // make manipulations return $image; } ); // self
目录
接口:Zenstruck\Filesystem\Node\Directory
(继承自 Node
)。
/** @var Zenstruck\Filesystem\Node\Directory $directory */ // iterate over nodes (non-recursive) foreach ($directory as $node) { /** @var Zenstruck\Filesystem\Node $node */ } // iterate over only files (non-recursive) foreach ($directory->files() as $file) { /** @var Zenstruck\Filesystem\Node\File $file */ } // iterate over only directories (non-recursive) foreach ($directory->directories() as $dir) { /** @var Zenstruck\Filesystem\Node\Directory $dir */ } // recursively iterate foreach ($directory->recursive() as $node) { /** @var Zenstruck\Filesystem\Node $node */ } // advanced filter $directories = $directory ->recursive() ->files() ->largerThan('10M') ->smallerThan('1G') ->olderThan('30 days ago') ->newerThan('20 days ago') ->matchingFilename('*.twig') ->notMatchingFilename('*.txt.twig') ->matchingPath('/files/') ->notMatchingPath('/exclude/') ->filter(function(File $file) { // custom filter if ($someCondition) { return false; // exclude } return true; // include }) ; // get first matching node $directories->first(); // null|\Zenstruck\Filesystem\Node
注意
大多数高级过滤器需要 symfony/finder
(composer require symfony/finder
)。
文件系统
FlysystemFilesystem
use Zenstruck\Filesystem\FlysystemFilesystem; /** @var \League\Flysystem\FilesystemOperator $operator */ /** @var \League\Flysystem\FilesystemAdapter $adapter */ // create from an already configured Flysystem Filesystem Operator $filesystem = new FlysystemFilesystem($operator); // create from an already configured Flysystem Filesystem Adapter $filesystem = new FlysystemFilesystem($operator); // create for local directory $filesystem = new FlysystemFilesystem('/path/to/local/dir'); // create for dsn (see available DSNs below) $filesystem = new FlysystemFilesystem('flysystem+ftp://user:pass@host.com:21/root');
文件系统 DSN
ScopedFilesystem
use Zenstruck\Filesystem\ScopedFilesystem; /** @var \Zenstruck\Filesystem $primaryFilesystem */ $scopedFilesystem = new ScopedFilesystem($primaryFilesystem, 'some/prefix'); // paths are prefixed $scopedFilesystem ->write('file.txt', 'content') ->path()->toString(); // "some/prefix/file.txt" ; // prefix is stripped from path $scopedFilesystem ->write('some/prefix/file.txt', 'content') ->path()->toString(); // "some/prefix/file.txt" ;
MultiFilesystem
use Zenstruck\Filesystem\MultiFilesystem; /** @var \Zenstruck\Filesystem $filesystem1 */ /** @var \Zenstruck\Filesystem $filesystem2 */ $filesystem = new MultiFilesystem([ 'filesystem1' => $filesystem1, 'filesystem2' => $filesystem2, ]); // prefix paths with a "scheme" as the filesystem's name $filesystem->file('filesystem1://some/file.txt'); // File from "filesystem1" $filesystem->file('filesystem2://another/file.txt'); // File from "filesystem2" // can copy and move across filesystems $filesystem->copy('filesystem1://file.txt', 'filesystem2://file.txt'); $filesystem->move('filesystem1://file.txt', 'filesystem2://file.txt'); // set a default filesystem for when no scheme is set $filesystem = new MultiFilesystem( [ 'filesystem1' => $filesystem1, 'filesystem2' => $filesystem2, ], default: 'filesystem2' ); $filesystem->file('another/file.txt'); // File from "filesystem2"
LoggableFilesystem
注意
需要 psr/log-implementation
。
use Zenstruck\Filesystem\LoggableFilesystem; use Zenstruck\Filesystem\Operation; use Psr\Log\LogLevel; /** @var \Zenstruck\Filesystem $inner */ /** @var \Psr\Log\LoggerInterface $logger */ $filesystem = new LoggableFilesystem($inner, $logger); // operations are logged $filesystem->write('file.txt', 'content'); // logged as '[info] Writing "string" to "file.txt" on filesystem "<filesystem-name>"' // customize the log levels for each operation $filesystem = new LoggableFilesystem($inner, $logger, [ Operation::READ => false, // disable logging read operations Operation::WRITE => LogLevel::DEBUG, Operation::MOVE => LogLevel::ALERT, Operation::COPY => LogLevel::CRITICAL, Operation::DELETE => LogLevel::EMERGENCY, Operation::CHMOD => LogLevel::ERROR, Operation::MKDIR => LogLevel::NOTICE, ]);
EventDispatcherFilesystem
注意
需要 psr/event-dispatcher-implementation
。
use Zenstruck\Filesystem\Event\EventDispatcherFilesystem; use Zenstruck\Filesystem\Operation; /** @var \Zenstruck\Filesystem $inner */ /** @var \Psr\EventDispatcher\EventDispatcherInterface $dispatcher */ $filesystem = new EventDispatcherFilesystem($inner, $dispatcher, [ // set these to false or exclude to disable dispatching operation's event Operation::WRITE => true, Operation::COPY => true, Operation::MOVE => true, Operation::DELETE => true, Operation::CHMOD => true, Operation::MKDIR => true, ]); $filesystem->write('foo', 'bar'); // PreWriteEvent/PostWriteEvent dispatched $filesystem->mkdir('bar'); // PreMkdirEvent/PostMkdirEvent dispatched $filesystem->chmod('foo', 'public'); // PreChmodEvent/PostChmodEvent dispatched $filesystem->copy('foo', 'file.png'); // PreCopyEvent/PostCopyEvent dispatched $filesystem->delete('foo'); // PreDeleteEvent/PostDeleteEvent dispatched $filesystem->move('file.png', 'file2.png'); // PreMoveEvent/PostMoveEvent dispatched ;
注意
查看事件类以了解它们提供了哪些功能。
注意
可以操作 Pre*Event
属性。
ZipFile
注意
需要 league/flysystem-ziparchive
(composer require league/flysystem-ziparchive
)。
这是一个特殊文件系统,包装本地 zip 存档。它既作为 Filesystem
对象也作为 \SplFileInfo
对象。
use Zenstruck\Filesystem\Archive\ZipFile; $archive = new ZipFile('/local/path/to/archive.zip'); $archive->file('some/file.txt'); $archive->write('another/file.txt', 'content'); (string) $archive; // /local/path/to/archive.zip
如果没有指定路径,将创建一个临时存档文件(脚本结束时删除)。
use Zenstruck\Filesystem\Archive\ZipFile; $archive = new ZipFile(); $archive->write('some/file.txt', 'content'); $archive->write('another/file.txt', 'content'); (string) $archive; // /tmp/...
可以通过 事务 对写操作进行排队和提交。
use Zenstruck\Filesystem\Archive\ZipFile; $archive = new ZipFile(); $archive->beginTransaction(); // start the transaction $archive->write('some/file.txt', 'content'); $archive->write('another/file.txt', 'content'); $archive->commit(); // actually writes the above files // optionally pass a progress callback to commit $archive->commit(function() use ($progress) { // callback is called at most, 100 times $progress->advance(); });
静态辅助函数,用于快速创建 zip
存档。
use Zenstruck\Filesystem\Archive\ZipFile; // compress a local file $zipFile = ZipFile::compress(new \SplFileInfo('/some/local/file.txt')); // ZipFile (temp file deleted on script end) // compress a local directory (all files (recursive) in "some/local/directory" are added to archive) $zipFile = ZipFile::compress(new \SplFileInfo('some/local/directory')); /** @var \Zenstruck\Filesystem\Node\File $file */ // compress a filesystem file $zipFile = ZipFile::compress($file); /** @var \Zenstruck\Filesystem\Node\Directory $directory */ // compress a filesystem directory $zipFile = ZipFile::compress($directory); // compress several local/filesystem files $zipFile = ZipFile::compress([ new \SplFileInfo('/some/local/file.txt'), $file, 'customize/path.txt' => $file, // use a string array key to set the path for the file ]); // customize the output filename (will not be deleted at end of script) $zipFile = ZipFile::compress(..., filename: 'path/to/archive.zip');
TarFile
注意
需要 league/flysystem-read-only
(composer require league/flysystem-read-only
)。
这是一个特殊文件系统,包装现有的本地 tar(.gz/bz2) 存档。它既作为 只读 的 Filesystem
对象也作为 \SplFileInfo
对象。
use Zenstruck\Filesystem\Archive\TarFile; $archive = new TarFile('/local/path/to/archive.tar'); $archive = new TarFile('/local/path/to/archive.tar.gz'); $archive = new TarFile('/local/path/to/archive.tar.bz2'); $archive->file('some/file.txt'); // \Zenstruck\Filesystem\Node\File
TestFilesystem
该文件系统包装另一个文件系统,并为测试提供断言。在使用 PHPUnit 时,这些断言将被转换为 PHPUnit 断言。
注意
使用断言需要 zenstruck/assert
(composer require --dev zenstruck/assert
)。
use Zenstruck\Filesystem\Test\TestFilesystem; use Zenstruck\Filesystem\Test\Node\TestDirectory; use Zenstruck\Filesystem\Test\Node\TestFile use Zenstruck\Filesystem\Test\Node\TestImage; /** @var \Zenstruck\Filesystem $filesystem */ $filesystem = new TestFilesystem($filesystem); $filesystem ->assertExists('foo') ->assertNotExists('invalid') ->assertFileExists('file1.txt') ->assertDirectoryExists('foo') ->assertImageExists('symfony.png') ->assertSame('symfony.png', 'fixture://symfony.png') ->assertNotSame('file1.txt', 'fixture://symfony.png') ->assertDirectoryExists('foo', function(TestDirectory $dir) { $dir ->assertCount(4) ->files()->assertCount(2) ; $dir ->recursive() ->assertCount(5) ->files()->assertCount(3) ; }) ->assertFileExists('file1.txt', function(TestFile $file) { $file ->assertVisibilityIs('public') ->assertChecksum($file->checksum()->toString()) ->assertContentIs('contents1') ->assertContentIsNot('foo') ->assertContentContains('1') ->assertContentDoesNotContain('foo') ->assertMimeTypeIs('text/plain') ->assertMimeTypeIsNot('foo') ->assertLastModified('2023-01-01 08:54') ->assertLastModified(function(\DateTimeInterface $actual) { // ... }) ->assertSize(9) ; }) ->assertImageExists('symfony.png', function(TestImage $image) { $image ->assertHeight(678) ->assertWidth(563) ; }) ; $file = $filesystem->realFile('symfony.png'); // \SplFileInfo('/tmp/symfony.png') - deleted at the end of the script
InteractsWithFilesystem
在单元测试中使用 InteractsWithFilesystem
特性可以快速提供内存中的文件系统。
注意
默认情况下,需要 league/flysystem-memory
(composer require --dev league/flysystem-memory
)。
use PHPUnit\Framework\TestCase; use Zenstruck\Filesystem\Test\InteractsWithFilesystem; class MyTest extends TestCase { use InteractsWithFilesystem; public function test_1(): void { $filesystem = $this->filesystem(); // instance of TestFilesystem wrapping an in-memory filesystem $filesystem->write('file.txt', 'content'); $filesystem->assertExists('file.txt'); } }
FilesystemProvider
要为测试提供自己的文件系统,让测试(或基测试用例)实现 FilesystemProvider
。
use PHPUnit\Framework\TestCase; use Zenstruck\Filesystem; use Zenstruck\Filesystem\Test\InteractsWithFilesystem; use Zenstruck\Filesystem\Test\FilesystemProvider; class MyTest extends TestCase implements FilesystemProvider { use InteractsWithFilesystem; public function test_1(): void { $filesystem = $this->filesystem(); // instance of TestFilesystem wrapping the AdapterFilesystem defined below $filesystem->write('file.txt', 'content'); $filesystem->assertExists('file.txt'); } public function createFilesystem(): Filesystem|FilesystemAdapter|string; { return '/some/temp/dir'; } }
注意
默认情况下,提供的文件系统在每次测试之前不会重置。请参阅 ResetFilesystem
以启用此行为。
FixtureFilesystemProvider
文件系统测试的一个常见需求是有一组已知存根文件,这些文件在测试中使用。让测试的(或基测试用例)实现 FixtureFilesystemProvider
以在测试中提供。
use PHPUnit\Framework\TestCase; use Zenstruck\Filesystem; use Zenstruck\Filesystem\Test\InteractsWithFilesystem; use Zenstruck\Filesystem\Test\FixtureFilesystemProvider; class MyTest extends TestCase implements FixtureFilesystemProvider { use InteractsWithFilesystem; public function test_1(): void { $filesystem = $this->filesystem(); // instance of TestFilesystem wrapping a MultiFilesystem $filesystem->write('file.txt', 'content'); // accesses your test filesystem $filesystem->assertExists('file.txt'); $filesystem->copy('fixture://some/file.txt', 'file.txt'); // copy a fixture to your test filesystem } public function createFixtureFilesystem(): Filesystem|FilesystemAdapter|string; { return __DIR__.'/../fixtures'; } }
注意
如果可用 league/flysystem-read-only
适配器,它将用于包装存根适配器,以确保您不会意外覆盖/删除存根文件(composer require --dev league/flysystem-read-only
)。
ResetFilesystem
如果使用自己的 FilesystemProvider
,可以使用 ResetFilesystem
特性在每次测试之前清除您的文件系统。
use PHPUnit\Framework\TestCase; use Zenstruck\Filesystem; use Zenstruck\Filesystem\Test\ResetFilesystem use Zenstruck\Filesystem\Test\InteractsWithFilesystem; use Zenstruck\Filesystem\Test\FilesystemProvider; class MyTest extends TestCase implements FilesystemProvider { use InteractsWithFilesystem, ResetFilesystem; public function test_1(): void { $this->filesystem()->write('file.txt', 'content') $this->filesystem()->assertExists('file.txt') } public function test_2(): void { $this->filesystem()->assertNotExists('file.txt'); // file created in test_1 was deleted before this test } public function createFilesystem(): Filesystem|FilesystemAdapter|string; { return '/some/temp/dir'; } }
Symfony 集成
响应
提供有用的自定义 Symfony 响应。
FileResponse
将文件系统 File
作为响应发送。
use Zenstruck\Filesystem\Symfony\HttpFoundation\FileResponse; /** @var \Zenstruck\Filesystem\File $file */ $response = new FileResponse($file); // auto-adds content-type/last-modified headers // create inline/attachment responses $response = FileResponse::attachment($file); // auto names by the filename (file.txt) $response = FileResponse::inline($file); // auto names by the filename (file.txt) // customize the filename used for the content-disposition header $response = FileResponse::attachment($file, 'different-name.txt'); $response = FileResponse::inline($file, 'different-name.txt');
ArchiveResponse
将 zip 文件发送作为响应。可以使用本地文件、本地目录、File
的实例或 Directory
的实例创建。
use Zenstruck\Filesystem\Symfony\HttpFoundation\ArchiveResponse; /** @var \SplFileInfo|\Zenstruck\Filesystem\Node\File|\Zenstruck\Filesystem\Node\Directory $what */ $response = ArchiveResponse::zip($what); $response = ArchiveResponse::zip($what, 'data.zip'); // customize the content-disposition name (defaults to archive.zip)
验证器
提供了 PendingFile
和 PendingImage
验证器。约束与 Symfony 本地 File
和 Image
约束的 API 相同。
use Zenstruck\Filesystem\Symfony\Validator\PendingFileConstraint; use Zenstruck\Filesystem\Symfony\Validator\PendingImageConstraint; /** @var \Symfony\Component\Validator\Validator\ValidatorInterface $validator */ /** @var \Zenstruck\Filesystem\Node\File $file */ /** @var \Zenstruck\Filesystem\Node\File\Image $image */ $validator->validate($file, new PendingFileConstraint(maxSize: '1M'))); $validator->validate($image, new PendingImageConstraint(maxWidth: 200, maxHeight: 200)));
捆绑包
配置
服务
序列化器
表单类型
PendingFileType
PendingImageType
命令
zenstruck:filesystem:purge
路由
公共URL路由
临时URL路由
转换URL路由
RouteTransformUrlGenerator
Doctrine 集成
功能/集成测试
TODO:关于 Mock::pendingFile()/pendingImage()
的说明。TODO:关于 Foundry\LazyMock::pendingFile()/pendingImage()
的说明。
测试性能
完整默认包配置
zenstruck_filesystem: # Filesystem configurations filesystems: # Prototype name: # Flysystem adapter DSN or, if prefixed with "@" flysystem adapter service id dsn: ~ # Required # Examples: # - '%kernel.project_dir%/public/files' # - 'flysystem+ftp://foo:bar@example.com/path' # - 'flysystem+s3://accessKeyId:accessKeySecret@bucket/prefix#us-east-1' # - 'static-in-memory' # - 'scoped:<name>:<prefix>' # - '@my_adapter_service' # Extra global adapter filesystem config config: [] # Lazily load the filesystem when the first call occurs lazy: true # Public URL generator for this filesystem public_url: # URL prefix or multiple prefixes to use for this filesystem (can be an array) prefix: # Examples: # - /files # - 'https://cdn1.example.com' # - 'https://cdn2.example.com' # Service id for a League\Flysystem\UrlGeneration\PublicUrlGenerator service: null # Generate with a route route: # Route name name: ~ # Required # Route parameters parameters: [] # Sign by default? sign: false # Default expiry expires: null # Example: '+ 30 minutes' # Enables cache busting for public urls version: enabled: false # The metadata to use for versioning metadata: last_modified # One of "last_modified"; "size"; "checksum" # The query parameter to use for versioning parameter: v # Temporary URL generator for this filesystem temporary_url: # Service id for a League\Flysystem\UrlGeneration\TemporaryUrlGenerator service: null # Generate with a route route: # Route name name: ~ # Required # Route parameters parameters: [] # Image Transform URL generator for this filesystem image_url: # Service id for a League\Flysystem\UrlGeneration\PublicUrlGenerator service: null # Generate with a route route: # Route name name: ~ # Required # Route parameters parameters: [] # Sign by default? sign: false # Default expiry expires: null # Example: '+ 30 minutes' # Dispatch filesystem operation events events: enabled: false write: true delete: true mkdir: true chmod: true copy: true move: true # Log filesystem operations log: enabled: true read: debug # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" write: info # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" move: ~ # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" copy: ~ # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" delete: ~ # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" chmod: ~ # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" mkdir: ~ # One of false; "emergency"; "alert"; "critical"; "error"; "warning"; "notice"; "info"; "debug" # If true, and using the ResetFilesystem trait # in your KernelTestCase's, delete this filesystem # before each test. reset_before_tests: false # Default filesystem name used to autowire Zenstruck\Filesystem default_filesystem: null # Doctrine configuration doctrine: enabled: true # Global lifecycle events (can be disabled on a property-by-property basis) lifecycle: # Whether to auto load file type columns during object load autoload: true # Whether to delete files on object removal delete_on_remove: true
向后兼容承诺
此库遵循 Symfony的BC承诺,以下为例外情况
Zenstruck/Filesystem
及其任何实现被视为 内部 用于 实现/扩展。Zenstruck/Filesystem/Node
及其任何实现被视为 内部 用于 实现/扩展。