Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Imagify Php Laravel Package

wp-media/imagify-php

Official PHP client for the Imagify API. Optimize images outside WordPress by compressing, resizing, and converting them to WebP through Imagify's service. Install via Composer and add image optimization to any PHP application.

Deep Wiki
Context7

Getting Started

Install the library through Composer and pin the version explicitly, because the last tagged release is from September 2017 and there is no active maintenance:

composer require wp-media/imagify-php

Where to look first:

  1. The API key flow. Imagify authenticates with an account API key (generated in the Imagify dashboard under Account → API). The library does not discover credentials for you; you will always construct the client with a key.
  2. src/ for the client class. The publicly documented entry point is the client object (typically instantiated as something like new Imagify($apiKey) or new Client($apiKey) depending on the tagged version). Open that file and read the public methods before anything else — the API surface is small and the docblocks are the most reliable "documentation" you have.
  3. The vendor's HTTP transport. The client wraps Guzzle (or the WP HTTP API). Confirming which one tells you how to inject mocks in tests and where to configure timeouts.
  4. Imagify's own REST docs (imagify.io → API) for the endpoints the wrapper exposes: image upload/optimization, optimization status, quota.

The minimal first use case — optimize one image and read back the result:

use WPMedia\Imagify\Imagify; // confirm namespace/class in src/

$client = new Imagify(config('services.imagify.key'));

$result = $client->optimize(new SplFileInfo(storage_path('app/public/hero.jpg')));

if ($result->isSuccess()) {
    // persist the optimized file / its URL, then serve from storage
}

Start by proving out the two calls you will call most: optimize (returns a compressed payload and/or a reference to a stored image) and quota (getQuota()-style call). If those two round-trip cleanly against a real key, everything else in the package is detail.

Implementation Patterns

Wrap it behind a service, never call it from controllers. The package is a thin HTTP wrapper; give yourself a single ImagifyService that owns the client, key, and error translation. This isolates the day you replace the abandoned dependency.

final class ImagifyService
{
    public function __construct(private Imagify $client) {}

    public function optimize(string $path): OptimizedImage
    {
        try {
            $response = $this->client->optimize(new SplFileInfo($path));
        } catch (ImagifyException $e) {
            throw new ImageOptimizationFailed($path, $e);
        }
        // map library DTO -> your own DTO
    }
}

Bind it as a singleton in a service provider so the underlying HTTP client and connection are reused:

$this->app->singleton(Imagify::class, fn () => new Imagify(config('services.imagify.key')));

Keep the key in config/services.php and .env, not in the constructor call site. The library has no config layer of its own, so Laravel's config cache is your only guard against accidentally hardcoding it.

Treat the API as asynchronous and eventual. Image optimization is not instant. The reliable workflow for bulk media is:

  1. Upload/reference the original (or point Imagify at a URL if the client supports URL-based optimization).
  2. Store the returned image identifier / job reference in a media_assets table.
  3. Poll the status endpoint (or re-fetch the asset) on a queued job with backoff — not in the request that uploaded the file.
  4. On success, download the optimized variant once and write it to disk; on failure, mark the row and let a retry command pick it up.

Use queued jobs for anything beyond a single ad-hoc file. A OptimizeImageJob with $tries = 3, an exponential backoff(), and a unique job lock per asset ID prevents duplicate submissions when uploads and edits race. The library itself does not deduplicate.

Store optimized results yourself. The value of the package is the compression call; the durable artifact is your own file on disk or object storage. Never let a page render depend on a live Imagify call — that is a latency and availability dependency on a third party, and it will also silently burn quota on cache misses.

Check quota before batch runs, not inside the loop. If the client exposes a quota/limits method, call it once at the top of a batch command and abort with a clear message when the remaining allowance is below the batch size.

Testing pattern: because the client is constructor-injected, swap it for a fake in ImagifyService tests and reserve real HTTP calls for a small, opt-in integration suite (@group external) run against a test account. Do not rely on the library having its own mock client — verify before assuming.

Gotchas and Tips

This package is effectively unmaintained. A 2017 release predates PSR-18, modern Guzzle 7, and PHP 8 attribute/type changes. Expect to hit:

  • Guzzle version conflicts with current Laravel/framework dependencies. You may need composer require with an explicit Guzzle constraint, or a replace/dependency bump after a careful read of the transport code.
  • Deprecation warnings on PHP 8.1+ (implicit nullable parameters, dynamic properties). Suppress narrowly or patch in a fork; do not globally silence deprecations.
  • Hard-coded php:// stream handling or SplFileInfo assumptions that break for remote/storage-backed files. Convert S3/object-storage assets to a local temp file before calling optimize().

Vendor or fork it. With 12 stars and no releases since 2017, do not depend on upstream bugfixes. Fork into your VCS, tag it 0.0.0+vendored, and reference it via repositories in composer.json. This is the single highest-leverage decision for a package of this maturity.

Timeouts and retries are on you. The wrapper is unlikely to set sensible cURL timeouts for large image uploads. Configure the underlying handler with a generous connect timeout and an overall timeout sized to your maximum allowed file — a 10 MB JPEG over a slow link will otherwise fail mid-upload with an opaque cURL error. Distinguish retryable (timeout, 5xx, 429) from terminal (401 invalid key, 413 too large, 422 unsupported format) in one place.

Errors surface as exceptions or raw response objects, depending on version. Read the client's error path before writing try/catch: some methods throw on non-2xx, others return a response you must inspect. Normalize both into one exception type at your service boundary so callers never branch on library internals.

API key leakage is easy. The key is a long-lived account secret with no per-scope permissions. Never log the client object, and redact Authorization/api_key headers in your exception handler — stack traces from Guzzle requests will otherwise carry the header into logs.

File-format and size guards belong in your code. The API will reject unsupported formats (animated GIFs, some CMYK JPEGs, SVG) and oversized files, but you pay a round trip to learn that. Validate mime type and dimensions locally first, and skip optimization for files already below a threshold where compression gains nothing.

Watch what "success" means. A 200 from the API may mean "accepted for processing", not "optimized". Always confirm the returned payload references a real, fetchable optimized asset before you overwrite the original — keep the original until the optimized file is verified on disk.

Extension points are thin. There is no event system, no pluggable transport interface, and no config object. The practical extension surface is: subclass/replace the client, inject a configured Guzzle client if the constructor accepts one, and wrap the whole thing in your own service layer. Plan accordingly rather than hoping for hooks.

Have an exit plan. Given the score and age, design ImagifyService as an interface with the package behind one implementation. If Imagify changes its API or you outgrow the wrapper, you can drop in a direct Guzzle implementation or a maintained alternative without touching call sites.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json