mozex / iminify-php
PHP client for the Iminify image optimization API, with an optimizer for Spatie's image packages
Fund package maintenance!
Requires
- php: ^8.2.0
- composer-runtime-api: ^2.0
- php-http/discovery: ^1.20
- psr/http-client: ^1.0.3
- psr/http-client-implementation: ^1.0.1
- psr/http-factory: ^1.1
- psr/http-factory-implementation: ^1.0
- psr/http-message: ^1.1|^2.0
Requires (Dev)
- guzzlehttp/guzzle: ^7.9.3|^8.0
- guzzlehttp/psr7: ^2.7|^3.0
- laravel/pint: ^1.14
- pestphp/pest: ^3.8.2|^4.0.0|^5.0.0
- pestphp/pest-plugin-type-coverage: ^3.5|^4.0.0|^5.0.1
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^11.5|^12.0|^13.0
- psr/log: ^1.1.4|^2.0|^3.0
- spatie/image: ^3.8
- spatie/image-optimizer: ^1.10
Suggests
- phpunit/phpunit: For the assertions of Testing\FakeClient
- spatie/image: To optimize an image through Spatie\IminifyOptimizer as you save it, and for Browsershot to do the same
- spatie/image-optimizer: For Spatie\IminifyOptimizer, which needs version 1.10 or newer
Provides
None
Conflicts
- spatie/image-optimizer: <1.10.0
Replaces
None
README
Iminify PHP
The PHP client for the Iminify image optimization API. Send an image, wait for it and save the smaller file in a few lines, and reach the rest of the API too: upload groups, page scans, site crawls, weekly checks, your account and webhook signatures. It also has an optimizer for Spatie's image packages, so a chain, spatie/image or Browsershot can compress through Iminify with no binaries on the server.
Read the full documentation at www.iminify.com: every guide and reference page, updated with each release.
Using Laravel? Iminify Laravel puts this client in your app's container behind an
Iminifyfacade, and plugs Iminify into Spatie's Media Library and laravel-image-optimizer.
Table of Contents
- Introduction
- Usage
- Integrations
- Reference
Support This Project
I maintain this package along with several other open-source PHP packages used by thousands of developers every day.
If my packages save you time or help your business, consider sponsoring my work on GitHub Sponsors. Your support lets me keep these packages updated, respond to issues quickly, and ship new features.
Business sponsors get logo placement in package READMEs. See sponsorship tiers →
What You Get
The API works in the background, so every long-running record has a wait() that backs off between reads, waits out a short rate limit and stops at the timeout you give it.
A refusal throws its own exception: DailyLimitReachedException for a spent daily allowance, RateLimitedException with its $retryAfter for a short limit, ValidationException with its $errors for a bad field, and the rest.
IminifyOptimizer takes jpegoptim's place in a Spatie chain, so the server needs no binaries, and a failure leaves the file exactly as it was. For your own tests, FakeClient answers from a queue through the real resources, so your code reads the same objects and catches the same exceptions as it does for real.
It's built on PSR-18, so it uses Guzzle, Symfony's client or whatever your project already has.
Installation
Requires PHP 8.2+ - see all version requirements
composer require mozex/iminify-php
The client needs a PSR-18 HTTP client and PSR-17 factories, and finds what your project has. A project with neither needs one, such as composer require guzzlehttp/guzzle. You also need an API key from Settings, API Tokens on www.iminify.com.
Quick Start
Send an image, wait for it and save the result:
use Mozex\Iminify\Iminify; $client = Iminify::factory() ->withApiKey(getenv('IMINIFY_API_KEY')) ->withTimeout(300) ->make(); $image = $client->images()->upload('photos/team.jpg', ['format' => 'webp']); $image = $client->images()->wait($image); if ($image->hasResult()) { $client->images()->download($image)->saveTo('photos/team.webp'); } echo "{$image->status->value}, saved {$image->savedPercent}%";
Give the client a timeout: PSR-18 has none of its own, and wait() only checks its clock between reads, so a stalled read otherwise blocks forever. It covers a whole request, an upload or a download included, so set it with your largest file in mind.
Handling a refusal
use Mozex\Iminify\Exceptions\DailyLimitReachedException; use Mozex\Iminify\Exceptions\RateLimitedException; try { $image = $client->images()->upload('photos/team.jpg'); } catch (RateLimitedException $exception) { sleep($exception->retryAfter ?? 5); $image = $client->images()->upload('photos/team.jpg'); } catch (DailyLimitReachedException) { // Out for today }
Upload groups
One image and every size and format you keep of it, counted as one image:
use Mozex\Iminify\Enums\GroupFormat; use Mozex\Iminify\Http\Upload; $upload = Upload::fromPath('photos/team.jpg'); $group = $client->groups()->create([ 'source' => ['format' => 'jpg', 'size' => $upload->size(), 'width' => 2560, 'height' => 1707], 'outputs' => [ ['name' => 'full', 'width' => 2560, 'height' => 1707], ['name' => 'medium', 'width' => 300, 'height' => 200], ], 'formats' => [GroupFormat::Original, GroupFormat::Webp], ]); $group = $client->groups()->sendSource($group, $upload); $group = $client->groups()->wait($group); $client->groups()->download($group)->saveTo('photos/team.zip');
The width and height are yours to work out, because the API wants them as displayed and getimagesize() gives them as stored.
Spatie's image optimizer
use Mozex\Iminify\Spatie\IminifyOptimizer; use Spatie\ImageOptimizer\OptimizerChain; $chain = (new OptimizerChain)->addOptimizer(new IminifyOptimizer([ 'api_key' => getenv('IMINIFY_API_KEY'), ])); $chain->optimize('photos/team.jpg');
Build the chain this way rather than through OptimizerChainFactory::create(), which silently ignores a list holding only this optimizer.
Your own tests
use Mozex\Iminify\Testing\FakeClient; use Mozex\Iminify\Testing\Fixtures; $client = new FakeClient([Fixtures::image()]); $image = $client->images()->get('abc'); $client->assertSent('GET', 'images/abc');
Webhooks
use Mozex\Iminify\Webhooks\WebhookVerifier; $event = (new WebhookVerifier($secret))->verify($rawBody, $signatureHeader);
That's the common path. Scans, crawls, weekly checks and every option are in the documentation.
Resources
Visit the documentation at www.iminify.com for every guide and reference page, updated from this repository with each release.
- Requirements: PHP and dependency versions
- Changelog: Release history with linked pull requests and diffs
- Questions & Issues: Bug reports, feature requests, and help
- Security: Report vulnerabilities directly via email
License
The MIT License (MIT). Please see License File for more information.
