tobento / service-picture
为PHP应用程序提供图片支持。
Requires
- php: >=8.0
- league/mime-type-detection: ^1.15
- psr/log: ^1.1 || ^2.0 || ^3.0
- tobento/service-dir: ^1.0
- tobento/service-filesystem: ^1.0
- tobento/service-imager: ^1.0
- tobento/service-tag: ^1.0.5
Requires (Dev)
- guzzlehttp/psr7: ^2.7
- monolog/monolog: ^2.3
- phpunit/phpunit: ^9.5
- vimeo/psalm: ^4.0
README
图片服务为PHP应用程序提供创建和渲染图片的接口。它包含默认实现,但您可以根据需要创建特定实现。
目录
入门
使用以下命令运行项目以添加图片服务项目的最新版本。
composer require tobento/service-picture
要求
- PHP 8.0或更高版本
亮点
- 框架无关,与任何项目兼容
- 解耦设计
文档
图片创建器
图片创建器根据给定的定义创建图像,并返回一个包含图像的已创建图片,您可以将图像存储在任何您喜欢的地方。
创建图片创建器
图片创建器使用Imager Service创建图像。
use Tobento\Service\Imager\InterventionImage\ImagerFactory; use Tobento\Service\Picture\PictureCreator; $pictureCreator = new PictureCreator( imager: (new ImagerFactory())->createImager(), );
详细说明
use Psr\Log\LoggerInterface; use Tobento\Service\Imager\Action; use Tobento\Service\Imager\InterventionImage\ImagerFactory; use Tobento\Service\Picture\Exception\ResourceSizeException; use Tobento\Service\Picture\PictureCreator; use Tobento\Service\Picture\PictureCreatorInterface; $pictureCreator = new PictureCreator( imager: (new ImagerFactory())->createImager(), // You may define imager actions which are not allowed and will be skipped: disallowedActions: [ Action\Colorize::class, ], // You may adjust the supported mime types: supportedMimeTypes: [ 'image/png', 'image/jpeg', 'image/gif', 'image/webp', ], // You may set an upsize limit for resizing images: upsize: 1.2, // default is null (unlimited) // You may skip smaller sized images (except img src) // from generating at all to prevent unsharp images. skipSmallerSizedSrc: true, // false is default // You may verify sizes. If one of the defined image size // is too small, a ResourceSizeException will be thrown. verifySizes: true, // false is default // You may pass a logger for debugging: logger: null, // LoggerInterface ); var_dump($pictureCreator instanceof PictureCreatorInterface); // bool(true)
图片创建
从流创建图片
使用createFromStream
方法从PSR-7流创建图片
use Psr\Http\Message\StreamInterface; use Tobento\Service\Picture\CreatedPictureInterface; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\PictureInterface; $createdPicture = $pictureCreator->createFromStream( stream: $stream, // StreamInterface definition: $definition, // DefinitionInterface ); var_dump($createdPicture instanceof CreatedPictureInterface); // bool(true) var_dump($createdPicture instanceof PictureInterface); // bool(true)
查看定义部分以了解有关定义的更多信息。
查看图片部分以了解有关默认的PictureInterface::class
实现的更多信息。
从资源创建图片
使用createFromResource
方法从实现ResourceInterface
接口的任何资源创建图片
use Tobento\Service\Imager\ResourceInterface; use Tobento\Service\Picture\CreatedPictureInterface; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\PictureInterface; $createdPicture = $pictureCreator->createFromResource( resource: $resource, // ResourceInterface definition: $definition, // DefinitionInterface ); var_dump($createdPicture instanceof CreatedPictureInterface); // bool(true) var_dump($createdPicture instanceof PictureInterface); // bool(true)
查看Imager Service - Resource部分以了解有关它的更多信息。
查看定义部分以了解有关定义的更多信息。
查看图片部分以了解有关默认的PictureInterface::class
实现的更多信息。
支持的资源
已创建图片
已创建的图片包含所有创建的图像,您可以使用它以您所需的方式存储图像。
use Tobento\Service\Imager\Response\Encoded; use Tobento\Service\Picture\CreatedPictureInterface; use Tobento\Service\Picture\PictureInterface; var_dump($createdPicture instanceof CreatedPictureInterface); // bool(true) var_dump($createdPicture instanceof PictureInterface); // bool(true) foreach($createdPicture->srces() as $src) { var_dump($src instanceof SrcInterface); // bool(true) // The encoded image which was created: var_dump($src->encoded() instanceof Encoded); // bool(true) }
查看Encoded Response以了解有关它的更多信息。
定义
数组定义
数组定义是默认的图片定义。
use Tobento\Service\Picture\Definition\ArrayDefinition; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\PictureInterface; use Tobento\Service\Picture\Src; $definition = new ArrayDefinition(name: 'product:main', definition: [ 'img' => [ 'src' => [600, 600], // [width, height] // or width only, height will be resized keeping ratio 'src' => [600], // or height only, width will be resized keeping ratio 'src' => [null, 600], // or 'src' => [null, null], // keeps resource dimensions. // or using Src class 'src' => new Src( width: 600, // or null height: 600, // or null // you may set a mime type to convert to: mimeType: 'image/webp', // you may define quality and actions: options: ['quality' => 90, 'actions' => ['crop' => [300, 200, 10, 15]]] ), // img attributes: 'alt' => 'Alternative Text', 'class' => 'foo', 'data-foo' => 'foo', 'sizes' => '(max-width: 600px) 480px, 800px', 'loading' => 'lazy', 'srcset' => [ '480w' => [480], // same definition as img src '800w' => [800], ], ], // You may define any sources: 'sources' => [ [ 'media' => '(min-width: 800px)', 'srcset' => [ '' => [1200, 600], ], 'type' => 'image/webp', ], [ 'media' => '(max-width: 600px)', 'srcset' => [ '' => [600, 600], ], 'type' => 'image/webp', 'width' => '600', 'height' => '600', ], ], // Attributes for the picture tag: 'attributes' => [ 'class' => 'foo', ], // Options: 'options' => [ // You may define a global quality if not specified individually with the Src class: 'quality' => [ 'image/jpeg' => 70, 'image/webp' => 70, ], // You may convert all png to jpeg types if not defined individually: 'convert' => ['image/png' => 'image/jpeg'], // You may define imager actions used if not specified individually with the Src class: 'actions' => [ 'greyscale' => [], 'gamma' => ['gamma' => 5.5], ], ], ]); var_dump($definition instanceof DefinitionInterface); // bool(true) // Definition to picture: var_dump($definition->toPicture() instanceof PictureInterface); // bool(true)
带有像素密度描述符的示例
use Tobento\Service\Picture\Definition\ArrayDefinition; $definition = new ArrayDefinition(name: 'logo', definition: [ 'img' => [ 'src' => [250], 'srcset' => [ '' => [250], '2x' => [500], ], ], ]);
图片定义
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\Definition\PictureDefinition; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\PictureInterface; use Tobento\Service\Picture\Source; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\Src; use Tobento\Service\Picture\Srcset; $definition = new PictureDefinition( name: 'product', picture: new Picture( img: new Img( src: new Src( width: 600, // or null height: 600, // or null // you may set a mime type to convert to: mimeType: 'image/webp', // you may define quality and actions: options: ['quality' => 90, 'actions' => ['crop' => [300, 200, 10, 15]]], ), // you may define a srcset: srcset: new Srcset( new Src(width: 480, descriptor: '480w'), new Src(width: 800, descriptor: '800w'), ), attributes: [ 'sizes' => '(max-width: 600px) 480px, 800px', 'loading' => 'lazy', 'class' => 'foo', ], ), sources: new Sources( new Source( srcset: new Srcset( new Src(width: 1200, height: 600), ), attributes: [ 'media' => '(min-width: 800px)', 'type' => 'image/webp', ], ), new Source( srcset: new Srcset( new Src(width: 600, height: 600), ), attributes: [ 'media' => '(max-width: 600px)', 'type' => 'image/webp', ], ), ), attributes: [ 'class' => 'foo', ], options: [ // You may define a global quality if not specified individually with the Src class: 'quality' => [ 'image/jpeg' => 70, 'image/webp' => 70, ], // You may convert all png to jpeg types if not defined individually: 'convert' => ['image/png' => 'image/jpeg'], // You may define imager actions used if not specified individually with the Src class: 'actions' => [ 'greyscale' => [], 'gamma' => ['gamma' => 5.5], ], ], ) ); var_dump($definition instanceof DefinitionInterface); // bool(true) // Definition to picture: var_dump($definition->toPicture() instanceof PictureInterface); // bool(true)
定义
您可以使用以下定义类来添加、过滤和获取定义。
默认定义
use Tobento\Service\Picture\Definition\ArrayDefinition; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\Definitions\Definitions; use Tobento\Service\Picture\DefinitionsInterface; $definitions = new Definitions( 'product', // a definitions name new ArrayDefinition('product-main', ['img' => ['src' => [50]]]), // ... DefinitionInterface ); var_dump($definitions instanceof DefinitionsInterface); // bool(true)
JSON文件定义
JsonFilesDefinitions
类从给定目录中的JSON文件加载定义。
use Tobento\Service\Dir\Dir; use Tobento\Service\Dir\Dirs; use Tobento\Service\Picture\Definition\ArrayDefinition; use Tobento\Service\Picture\DefinitionInterface; use Tobento\Service\Picture\Definitions\JsonFilesDefinitions; use Tobento\Service\Picture\DefinitionsInterface; $definitions = new JsonFilesDefinitions( name: 'product', // a definitions name dirs: new Dirs(new Dir('dir/private/picture-definitions/')) ); var_dump($definitions instanceof DefinitionsInterface); // bool(true)
示例目录
private/
picture-definitions/
product.json
...
示例JSON定义
{
"img": {
"src": {
"width": 300,
"height": null,
"descriptor": null,
"mimeType": "image/png",
"url": null,
"path": null,
"options": []
},
"srcset": [
{
"width": 200
}
],
"attributes": {
"key": "value"
}
},
"sources": [
{
"srcset": [
{
"width": 200,
"height": null,
"descriptor": null,
"url": null,
"path": null,
"options": []
}
],
"attributes": {
"key": "value"
}
}
],
"attributes": {
"key": "value"
},
"options": {
"key": "value"
}
}
栈定义
use Tobento\Service\Picture\Definition\ArrayDefinition; use Tobento\Service\Picture\Definitions\Definitions; use Tobento\Service\Picture\Definitions\StackDefinitions; use Tobento\Service\Picture\DefinitionsInterface; $definitions = new StackDefinitions( 'name', // a definitions name new Definitions('product', new ArrayDefinition('product-main', ['img' => ['src' => [50]]])), // ... DefinitionsInterface ); var_dump($definitions instanceof DefinitionsInterface); // bool(true)
图片
图片类可用于创建、存储或渲染图片。
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\ImgInterface; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\PictureInterface; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\SourcesInterface; use Tobento\Service\Picture\Src; $picture = new Picture( img: new Img( src: new Src(), ), sources: new Sources(), attributes: [], options: [], ); var_dump($picture instanceof PictureInterface); // bool(true) // returns the img: var_dump($picture->img() instanceof ImgInterface); // bool(true) // returns a new instance with the given img: $picture = $picture->withImg(new Img(new Src())); // returns the sources: var_dump($picture->sources() instanceof SourcesInterface); // bool(true) // returns a new instance with the given sources: $picture = $picture->withSources(new Sources()); // returns the attributes: $attributes = $picture->attributes(); // returns a new instance with the given attributes: $picture = $picture->withAttributes([]); // returns the options: $options = $picture->options(); // returns a new instance with the given options: $picture = $picture->withOptions([]);
Srces
srces
方法返回一个包含所有收集的Src
类的生成器
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\Src; use Tobento\Service\Picture\SrcInterface; $picture = new Picture( img: new Img( src: new Src(), ), sources: new Sources(), ); foreach($picture->srces() as $src) { var_dump($src instanceof SrcInterface); // bool(true) }
toTag
toTag
方法返回一个新的创建的图片标签。
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\PictureTagInterface; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\Src; $picture = new Picture( img: new Img( src: new Src(), ), sources: new Sources(), ); var_dump($picture->toTag() instanceof PictureTagInterface); // bool(true)
查看图片标签部分以了解有关默认的PictureTagInterface::class
的更多信息。
jsonSerialize
jsonSerialize
方法将对象序列化为可以由 json_encode()
原生序列化的值。
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\Src; $picture = new Picture( img: new Img( src: new Src(), ), sources: new Sources(), ); $jsonSerialized = $picture->jsonSerialize();
Img
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\ImgInterface; use Tobento\Service\Picture\Src; use Tobento\Service\Picture\SrcInterface; use Tobento\Service\Picture\Srcset; use Tobento\Service\Picture\SrcsetInterface; $img = new Img( src: new Src(), // SrcInterface srcset: new Srcset(), // null|SrcsetInterface attributes: [], ); var_dump($img instanceof ImgInterface); // bool(true) // returns the src: var_dump($img->src() instanceof SrcInterface); // bool(true) // returns a new instance with the given src: $img = $img->withSrc(new Src()); // returns the srcset or null if none: var_dump($img->srcset() instanceof SrcsetInterface); // bool(true) // returns a new instance with the given srcset: $img = $img->withSrcset(new Srcset()); // returns the attributes: $attributes = $img->attributes(); // returns a new instance with the given attributes: $img = $img->withAttributes([]); // json serialize: $jsonSerialized = $img->jsonSerialize();
来源
use Tobento\Service\Picture\Source; use Tobento\Service\Picture\SourceInterface; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\SourcesInterface; use Tobento\Service\Picture\Srcset; use Tobento\Service\Picture\SrcInterface; $sources = new Sources( new Source(new Srcset()), new Source(new Srcset()), ); var_dump($sources instanceof SourcesInterface); // bool(true) // iterate sources: foreach($sources as $source) { var_dump($source instanceof SourceInterface); // bool(true) } // or foreach($sources->all() as $source) {} // count sources: var_dump($sources->count()); // int(2) // returns all collected Src classes: foreach($sources->srces() as $src) { var_dump($src instanceof SrcInterface); // bool(true) } // json serialize: $jsonSerialized = $sources->jsonSerialize();
源代码
use Tobento\Service\Picture\Source; use Tobento\Service\Picture\SourceInterface; use Tobento\Service\Picture\Srcset; use Tobento\Service\Picture\SrcsetInterface; $source = new Source( srcset: new Srcset(), attributes: [] ); var_dump($source instanceof SourceInterface); // bool(true) // returns the srcset or null if none: var_dump($source->srcset() instanceof SrcsetInterface); // bool(true) // returns a new instance with the given srcset: $source = $source->withSrcset(new Srcset()); // returns the attributes: $attributes = $source->attributes(); // returns a new instance with the given attributes: $source = $source->withAttributes([]); // json serialize: $jsonSerialized = $source->jsonSerialize();
Srcset
use Tobento\Service\Picture\Src; use Tobento\Service\Picture\SrcInterface; use Tobento\Service\Picture\Srcset; use Tobento\Service\Picture\SrcsetInterface; $srcset = new Srcset( new Src(width: 200, descriptor: '1x'), new Src(width: 400, descriptor: '2x'), ); var_dump($srcset instanceof SrcsetInterface); // bool(true) // iterate srces: foreach($srcset as $src) { var_dump($src instanceof SrcInterface); // bool(true) } // or foreach($srcset->all() as $src) {} // count srces: var_dump($srcset->count()); // int(2) // json serialize: $jsonSerialized = $srcset->jsonSerialize();
Src
use Tobento\Service\Imager\Response\Encoded; use Tobento\Service\Picture\Src; use Tobento\Service\Picture\SrcInterface; $src = new Src( width: 200, // null|int height: 200, // null|int descriptor: '200w', // null|string, may be used for srcset mimeType: 'image/jpeg', // null|string url: null, // null|string path: null, // null|string encoded: null, // null|Encoded options: [], ); var_dump($src instanceof SrcInterface); // bool(true) // returns the width or null if none: var_dump($src->width()); // int(200) // returns a new instance with the given width: $src = $src->withWidth(300); // or null // returns the height or null if none: var_dump($src->height()); // int(200) // returns a new instance with the given height: $src = $src->withHeight(300); // or null // returns the descriptor or null if none: var_dump($src->descriptor()); // string(4) "200w" // returns a new instance with the given descriptor: $src = $src->withDescriptor('1x'); // or null // returns the mimeType or null if none: var_dump($src->mimeType()); // string(10) "image/jpeg" // returns a new instance with the given mimeType: $src = $src->withMimeType('image/gif'); // or null // returns the url or null if none: var_dump($src->url()); // NULL or string // returns a new instance with the given url: $src = $src->withUrl('https://example.com/image.jpg'); // or null // returns the path or null if none: var_dump($src->path()); // NULL or string // returns a new instance with the given path: $src = $src->withPath('path/image.jpg'); // or null // returns the encoded or null if none: var_dump($src->encoded()); // NULL or Encoded // returns a new instance with the given encoded: $src = $src->withEncoded(null); // or Encoded // returns the options: var_dump($src->options()); // array(0) { } // returns a new instance with the given options: $src = $src->withOptions([]); // json serialize: $jsonSerialized = $src->jsonSerialize();
图片工厂
可以使用图片工厂来创建图片。
use Tobento\Service\Picture\PictureFactory; use Tobento\Service\Picture\PictureFactoryInterface; $factory = new PictureFactory( // you may throw exceptions if an error occurs: throwOnError: true, // false is default ); var_dump($factory instanceof PictureFactoryInterface); // bool(true)
从数组创建
使用 createFromArray
方法从给定的数组创建图片
use Tobento\Service\Picture\PictureFactory; use Tobento\Service\Picture\PictureInterface; $picture = (new PictureFactory())->createFromArray([ 'img' => [ 'src' => [ 'width' => 300, 'height' => null, 'descriptor' => '2x', // or null 'mimeType' => 'image/jpeg', // or null 'url' => null, 'path' => null, 'options' => [], ], 'srcset' => [ ['width' => 200], ], 'attributes' => ['key' => 'value'], ], 'sources' => [ [ 'srcset' => [ [ 'width' => 200, 'height' => null, 'descriptor' => null, 'url' => null, 'path' => null, 'options' => [], ], ], 'attributes' => ['key' => 'value'] ], ], 'attributes' => ['key' => 'value'], 'options' => ['key' => 'value'], ]); var_dump($picture instanceof PictureInterface); // bool(true)
图片标签工厂
可以使用图片标签工厂来创建图片标签。
use Tobento\Service\Picture\PictureTagFactory; use Tobento\Service\Picture\PictureTagFactoryInterface; $factory = new PictureTagFactory(); var_dump($factory instanceof PictureTagFactoryInterface); // bool(true)
从图片创建
使用 createFromPicture
方法从给定的图片创建图片标签
use Tobento\Service\Picture\Img; use Tobento\Service\Picture\Picture; use Tobento\Service\Picture\PictureTagFactory; use Tobento\Service\Picture\PictureTagInterface; use Tobento\Service\Picture\Sources; use Tobento\Service\Picture\Src; $picture = new Picture( img: new Img( src: new Src(url: 'https://example.com/image.jpg'), ), sources: new Sources(), ); $pictureTag = (new PictureTagFactory())->createFromPicture($picture); var_dump($pictureTag instanceof PictureTagInterface); // bool(true)
图片标签
图片标签渲染图片 HTML 标签。
use Tobento\Service\Picture\PictureTag; use Tobento\Service\Picture\PictureTagInterface; use Tobento\Service\Tag\Attributes; use Tobento\Service\Tag\Tag; use Tobento\Service\Tag\TagInterface; $picture = new PictureTag( new Tag(name: 'picture'), new Tag(name: 'img', attributes: new Attributes(['src' => 'image.jpg'])), new Tag(name: 'source', attributes: new Attributes(['srcset' => 'image.webp', 'type' => 'image/webp'])), new Tag(name: 'source', attributes: new Attributes(['srcset' => 'image.avif', 'type' => 'image/avif'])), ); var_dump($picture instanceof PictureTagInterface); // bool(true) var_dump($picture instanceof \Stringable); // bool(true) // returns the "picture" tag: var_dump($picture->tag() instanceof TagInterface); // bool(true) // returns a new instance with the given "picture" tag: $picture = $picture->withTag(new Tag('picture')); // returns the "img" tag: var_dump($picture->img() instanceof TagInterface); // bool(true) // returns a new instance with the given "img" tag: $picture = $picture->withImg(new Tag('img')); // returns the "source" tags: foreach($picture->sources() as $source) { var_dump($source instanceof TagInterface); // bool(true) } // returns a new instance with the given "source" tags: $picture = $picture->withSources( new Tag(name: 'source', attributes: new Attributes(['srcset' => 'image.webp', 'type' => 'image/webp'])), new Tag(name: 'source', attributes: new Attributes(['srcset' => 'image.avif', 'type' => 'image/avif'])), ); // returns a new instance with the given "picture" attribute: $picture = $picture->attr(name: 'data-foo', value: 'Foo'); // returns a new instance with the given "img" attribute: $picture = $picture->imgAttr(name: 'data-bar', value: 'Bar');
您可以查看 标签服务 - 标签接口 部分以了解关于 TagInterface::class
的更多信息。
渲染图片
<?= $picture->render() ?> // or just <?= $picture ?>
空图片标签
空图片标签根本不渲染任何内容,在某些情况下可能很有用。
use Tobento\Service\Picture\PictureTagInterface; use Tobento\Service\Picture\NullPictureTag; $picture = new NullPictureTag(); var_dump($picture instanceof PictureTagInterface); // bool(true) var_dump((string)$picture); // string(0) ""