PHPackages                             bgillieron/yii2-cloudinary - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. bgillieron/yii2-cloudinary

ActiveYii2-extension[Image &amp; Media](/categories/media)

bgillieron/yii2-cloudinary
==========================

A Yii2-friendly wrapper for Cloudinary’s PHP SDK: upload widget, responsive images, and media management.

v1.0.1(9mo ago)18MITPHP

Since Jun 26Pushed 9mo ago1 watchersCompare

[ Source](https://github.com/bgillieron/yii2-cloudinary)[ Packagist](https://packagist.org/packages/bgillieron/yii2-cloudinary)[ RSS](/packages/bgillieron-yii2-cloudinary/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (2)Versions (5)Used By (0)

Yii2Cloudinary
==============

[](#yii2cloudinary)

Cloudinary integration for the Yii2 PHP Framework.

This extension provides a Yii2-friendly wrapper around the official [Cloudinary PHP SDK](https://github.com/cloudinary/cloudinary_php), enabling seamless uploads, media management, and responsive image rendering in Yii2 projects.

---

📁 Project Structure
-------------------

[](#-project-structure)

```
yii2-cloudinary/
├── src/
│   ├── assets/
│   │   ├── photoswipe/
│   │   │   ├── photoswipe-lightbox.esm.min.js
│   │   │   ├── photoswipe.esm.min.js
│   │   │   ├── photoswipe.css
│   │   └── PhotoSwipeAsset.php
│   ├── components/
│   │   └── Yii2CloudinaryComponent.php
│   ├── controllers/
│   │   └── Yii2CloudinaryController.php
│   ├── messages/
│   │   ├── en/
│   │   │   └── uploadWidget.php
│   │   └── text.json
│   ├── migrations/
│   │   └── m250430_120000_create_cloudinary_media_tables.php
│   ├── models/
│   │   ├── CloudinaryImageMeta.php
│   │   ├── CloudinaryMedia.php
│   │   ├── CloudinaryMediaDesc.php
│   │   └── Module.php
├── cloudinary-media-migrations.md
├── composer.json
├── LICENSE
├── README.md
├── render-responsive-image.md
└── upload-widget-localization.md

```

---

🛠 Features
----------

[](#-features)

- Upload images and files to Cloudinary with a single call
- Automatically configure credentials via Yii component
- Drop-in Upload Widget integration with runtime options
- Responsive image rendering with automatic `srcset`
- Orientation-aware rendering via image meta
- PhotoSwipe support for lightbox galleries
- Database schema for multilingual media metadata
- Easily relate uploaded media to your own models
- Fully translatable Upload Widget UI

---

📦 Installation
--------------

[](#-installation)

Install the extension via Composer:

```
composer require bgillieron/yii2-cloudinary
```

---

🔧 Configuration
---------------

[](#-configuration)

Add the module and component to your Yii2 config:

```
'modules' => [
    'cloudinary' => [
        'class' => 'yii2cloudinary\Module',
    ],
],
'components' => [
    'yii2cloudinary' => [
        'class' => \yii2cloudinary\components\Yii2CloudinaryComponent::class,
        'cloudName' => $_ENV['CLOUDINARY_CLOUD_NAME'],
        'apiKey' => $_ENV['CLOUDINARY_API_KEY'],
        'apiSecret' => $_ENV['CLOUDINARY_API_SECRET'],
        'uploadPreset' => $_ENV['CLOUDINARY_UPLOAD_PRESET'],
        'uploadHandlerUrl' => '/cloudinary/yii2-cloudinary/upload-handler',
        'db_defaultPublished' => false,
        'db_defaultOrder' => 500,
        'relationSaverMap' => [
            'test-widget' => function ($media) {
                Yii::$app->db->createCommand()->insert('test_media_relation', [
                    'media_id' => $media->id,
                    'label' => 'Uploaded from test widget',
                ])->execute();
            },
        ],
    ],
],
```

---

🧱 Migrations
------------

[](#-migrations)

To create the necessary tables for storing Cloudinary media and metadata, run:

```
php yii migrate --migrationPath=@yii2cloudinary/migrations
```

This will create:

- `cloudinary_media`
- `cloudinary_media_desc`
- `cloudinary_image_meta`

📖 For full details on table structure and purpose, see [Cloudinary Media Migrations](./cloudinary-media-migrations.md).

---

🚀 Media Usage
-------------

[](#-media-usage)

### Uploading Files (Server-Side)

[](#uploading-files-server-side)

```
Yii::$app->yii2cloudinary->upload('/path/to/image.jpg', [
    'folder' => 'my-uploads',
    'tags' => ['profile', 'gallery'],
    'relationKey' => 'post-image',
]);
```

This method:

- Uploads the file to Cloudinary
- Saves the `cloudinary_media` record
- If `relationKey` is provided and defined in your config, invokes the matching relation handler

### 🔄 Uploading with Custom Payload

[](#-uploading-with-custom-payload)

You can pass extra metadata to control how the upload is saved:

```
Yii::$app->yii2cloudinary->upload('/path/to/image.jpg', [
    'folder' => 'product-images',
    'customPayload' => [
        'order' => 1,
        'published' => true,
        'product_id' => 123,
    ],
    'relationKey' => 'product-gallery',
]);
```

- `customPayload` is forwarded to both the database save and your `relationSaverMap` callback.
- This allows custom logic or model relation setup based on the upload context.

---

### 🔁 Saving Upload Result &amp; Creating Relations

[](#-saving-upload-result--creating-relations)

When a file is uploaded to Cloudinary, the extension automatically saves a corresponding record in the database (`cloudinary_media`) — but in most real-world projects, you’ll also want to associate that file with a specific model (like `Post`, `Product`, `User`, etc.).

To keep your application logic clean and flexible, this extension introduces the concept of **relation callbacks**, defined via the `relationSaverMap`.

#### 🧠 Why Use `relationSaverMap`?

[](#-why-use-relationsavermap)

- You may need different logic for different upload contexts (e.g. a product image, an avatar, a gallery).
- Each upload (or widget instance) can pass a `relationKey` to identify which logic should run.
- You configure these mappings once in your app config — no need to pass closures at runtime.

#### 🗂️ Define Any Number of Relation Handlers

[](#️-define-any-number-of-relation-handlers)

```
'relationSaverMap' => [
    'product-gallery' => function ($media, $payload) {
        Yii::$app->db->createCommand()->insert('product_media', [
            'media_id' => $media->id,
            'product_id' => $payload['product_id'] ?? null,
            'position' => $payload['order'] ?? 1,
        ])->execute();
    },
    'user-avatar' => fn($media) => Yii::$app->user->identity->link('avatar', $media),
    'post-image' => fn($media) => Post::findOne(5)->link('media', $media),
],
```

---

### Rendering a Responsive Image

[](#rendering-a-responsive-image)

```
echo Yii::$app->yii2cloudinary->renderResponsiveImage($media, [400, 800], [
    'class' => 'img-fluid',
]);
```

- Generates `` tag with optimized Cloudinary `srcset`
- Optional aspect ratio detection (e.g. `'4:3'`, `'1:1'`)
- Orientation-aware layout using image meta (landscape vs portrait)
- Lazy loading and format auto-selection supported

📖 See [Render Responsive Image](./render-responsive-image.md) for advanced usage and options.

---

🖼 Upload Widget &amp; UI
------------------------

[](#-upload-widget--ui)

### Rendering the Upload Widget

[](#rendering-the-upload-widget)

```
Yii::$app->yii2cloudinary->uploadWidget('upload_widget', [
    'relationKey' => 'product-gallery',
    'customPayload' => [
        'product_id' => 123,
        'order' => 1,
        'published' => true,
    ],
    'reloadAfterClose' => true,
]);
```

This registers the Cloudinary Upload Widget and binds it to the DOM element with the given ID.

Key behaviors:

- Automatically registers and loads Cloudinary’s JavaScript dependencies
- Uploads files to Cloudinary and sends metadata to your configured `uploadHandlerUrl` endpoint, which persists the media and optionally links it using your `relationSaverMap`
- If a `relationKey` is passed, it is forwarded to the server to trigger a matching callback from your `relationSaverMap`
- `customPayload` is included in the upload metadata for advanced save logic
- `reloadAfterClose` reloads the page when the widget is closed (optional)
- You can also pass `text` overrides for localization

---

#### 🔁 Upload Handler URL

[](#-upload-handler-url)

When a file is uploaded via the widget, Cloudinary sends the file to their CDN,
then triggers a callback with metadata that is posted to your app’s upload handler.

By default, this handler is set to:

```
'uploadHandlerUrl' => '/yii2cloudinary/upload-handler',
```

You can override this in your component config if needed:

```
'uploadHandlerUrl' => '/custom/path/to/upload-handler',
```

This endpoint must match the route defined by your `Yii2CloudinaryController::actionUploadHandler()`
and is responsible for saving the uploaded media record and executing your `relationSaverMap` logic.
Only change this if absolutely necessary — overriding it incorrectly will break key functionality of this module.

---

### 🌍 Upload Widget Localization

[](#-upload-widget-localization)

This extension supports:

- Default English UI via embedded translations
- App-level language overrides via `messages//uploadWidget.php`
- Runtime `text` overrides passed to `uploadWidget()`

📖 See [Upload Widget Localization](./upload-widget-localization.md) for a complete guide.

---

### 🖼 Lightbox Support (PhotoSwipe)

[](#-lightbox-support-photoswipe)

#### Register the ESM Asset Bundle

[](#register-the-esm-asset-bundle)

```
use yii2cloudinary\assets\PhotoSwipeAsset;

PhotoSwipeAsset::register($this);
```

#### Initialize in View

[](#initialize-in-view)

```
assetManager->getBundle(\yii2cloudinary\assets\PhotoSwipeAsset::class)->baseUrl; ?>

import PhotoSwipeLightbox from '/photoswipe-lightbox.esm.min.js';
import PhotoSwipe from '/photoswipe.esm.min.js';

const lightbox = new PhotoSwipeLightbox({
    gallery: '.my-gallery',
    children: 'a',
    pswpModule: PhotoSwipe,
    padding: 20,
    showHideAnimationType: 'zoom',
});

lightbox.init();

```

📌 *ES modules require explicit `import` and do not auto-run.*

---

⚙️ Advanced Access
------------------

[](#️-advanced-access)

### SDK Access

[](#sdk-access)

```
$cloudinary = Yii::$app->yii2cloudinary->getCloudinary();
$url = $cloudinary->image('your-public-id')->toUrl();
```

This returns the `Cloudinary\Cloudinary` instance for advanced transformations.

---

### Model Reference

[](#model-reference)

These models support multilingual metadata and responsive rendering:

- [`CloudinaryMedia`](src/models/CloudinaryMedia.php)
- [`CloudinaryMediaDesc`](src/models/CloudinaryMediaDesc.php)
- [`CloudinaryImageMeta`](src/models/CloudinaryImageMeta.php)

---

📝 License
---------

[](#-license)

MIT License © Brendon Gilliéron

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance56

Moderate activity, may be stable

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Total

2

Last Release

291d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/0ce32244e72a8a5a62f75f9727648ad273661a23f929196322bbc2eb72e35630?d=identicon)[bgillieron](/maintainers/bgillieron)

---

Top Contributors

[![bgillieron](https://avatars.githubusercontent.com/u/2003839?v=4)](https://github.com/bgillieron "bgillieron (8 commits)")

---

Tags

yii2widgetcloudinaryResponsive ImagesImage uploadMedia Managerphotoswipe

### Embed Badge

![Health badge](/badges/bgillieron-yii2-cloudinary/health.svg)

```
[![Health](https://phpackages.com/badges/bgillieron-yii2-cloudinary/health.svg)](https://phpackages.com/packages/bgillieron-yii2-cloudinary)
```

###  Alternatives

[yiimaker/yii2-social-share

Extension for sharing on social networks

48111.3k4](/packages/yiimaker-yii2-social-share)[bilginnet/yii2-cropper

Yii2 Bootstrap Cropper Input Widget

2232.1k](/packages/bilginnet-yii2-cropper)[demi/cropper

Yii2 wrapper for Image Cropper javascript library

1328.7k1](/packages/demi-cropper)[maxmirazh33/yii2-uploadable-cropable-image

Yii2 extension for upload and crop images

1020.8k](/packages/maxmirazh33-yii2-uploadable-cropable-image)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
