PHPackages                             codebar-ag/laravel-flysystem-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. [File &amp; Storage](/categories/file-storage)
4. /
5. codebar-ag/laravel-flysystem-cloudinary

ActiveLibrary[File &amp; Storage](/categories/file-storage)

codebar-ag/laravel-flysystem-cloudinary
=======================================

Cloudinary Flysystem 3 integration with Laravel

v13.0.0(3mo ago)1229.3k↑46.3%7[2 PRs](https://github.com/codebar-ag/laravel-flysystem-cloudinary/pulls)1MITPHPPHP 8.3.\*|8.4.\*|8.5.\*CI passing

Since May 24Pushed 5d ago1 watchersCompare

[ Source](https://github.com/codebar-ag/laravel-flysystem-cloudinary)[ Packagist](https://packagist.org/packages/codebar-ag/laravel-flysystem-cloudinary)[ Docs](https://github.com/codebar-ag/laravel-flysystem-cloudinary)[ RSS](/packages/codebar-ag-laravel-flysystem-cloudinary/feed)WikiDiscussions main Synced 2d ago

READMEChangelog (10)Dependencies (39)Versions (53)Used By (1)

[![](https://camo.githubusercontent.com/3f6cd1b7d34968a6bd5f5334d201321c6c7023d86e8f2cccaba0a213d059f963/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c253230466c7973797374656d253230436c6f7564696e6172792e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d636f64656261722d61672532466c61726176656c2d666c7973797374656d2d636c6f7564696e617279267061747465726e3d63697263756974426f617264267374796c653d7374796c655f32266465736372697074696f6e3d416e2b6f70696e696f6e617465642b7761792b746f2b696e746567726174652b436c6f7564696e6172792b776974682b7468652b4c61726176656c2b66696c6573797374656d266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313530707826696d616765733d636c6f7564267769647468733d35303026686569676874733d353030)](https://camo.githubusercontent.com/3f6cd1b7d34968a6bd5f5334d201321c6c7023d86e8f2cccaba0a213d059f963/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c253230466c7973797374656d253230436c6f7564696e6172792e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d636f64656261722d61672532466c61726176656c2d666c7973797374656d2d636c6f7564696e617279267061747465726e3d63697263756974426f617264267374796c653d7374796c655f32266465736372697074696f6e3d416e2b6f70696e696f6e617465642b7761792b746f2b696e746567726174652b436c6f7564696e6172792b776974682b7468652b4c61726176656c2b66696c6573797374656d266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313530707826696d616765733d636c6f7564267769647468733d35303026686569676874733d353030)

[![Latest Version on Packagist](https://camo.githubusercontent.com/6b4cbfb45d535d5531f13819e2632c5af591713aaf7ac526256b302e376507b9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636f64656261722d61672f6c61726176656c2d666c7973797374656d2d636c6f7564696e6172792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codebar-ag/laravel-flysystem-cloudinary)[![Total Downloads](https://camo.githubusercontent.com/87d4c05a60370fccd1172e5e136fc07fd32456c8eb07e8446f010b0a6cb09409/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f636f64656261722d61672f6c61726176656c2d666c7973797374656d2d636c6f7564696e6172792e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codebar-ag/laravel-flysystem-cloudinary)[![GitHub-Tests](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/run-tests.yml/badge.svg?branch=main)](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/run-tests.yml)[![GitHub Code Style](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/fix-php-code-style-issues.yml/badge.svg?branch=main)](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/fix-php-code-style-issues.yml)[![PHPStan](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/phpstan.yml/badge.svg)](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/phpstan.yml)[![Dependency Review](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/codebar-ag/laravel-flysystem-cloudinary/actions/workflows/dependency-review.yml)

💡 What is Cloudinary?
---------------------

[](#-what-is-cloudinary)

Cloudinary is basically a fantastic way to store and serve assets like images or videos. You can upload your full resolution image to Cloudinary, and they handle the optimization for you. The only thing you have to do is to add additional parameters to your url 😉

🛠 Requirements
--------------

[](#-requirements)

- Cloudinary Account

PackagePHPLaravelFlysystemv13.08.3.\* | 8.4.\* | 8.5.\*13.x3.xv12.08.2.\* | 8.3.\* | 8.4.\*12.x3.xv11.08.2.\* | 8.3.\*11.x3.xv4.08.2.\* | 8.3.\*11.x3.xv3.08.2.\*10.x3.xv2.08.1.\*9.x3.xv1.08.0.\*8.x1.1⚙️ Installation
---------------

[](#️-installation)

You can install the package via composer:

```
composer require codebar-ag/laravel-flysystem-cloudinary
```

Add the following disk to your filesystem "disks" list in your `filesystems.php`configuration:

```
    'disks' => [
        //

        'cloudinary' => [
            'driver' => 'cloudinary',
            'cloud_name' => env('CLOUDINARY_CLOUD_NAME'),
            'api_key' => env('CLOUDINARY_API_KEY'),
            'api_secret' => env('CLOUDINARY_API_SECRET'),
            'url' => [
                'secure' => (bool) env('CLOUDINARY_SECURE_URL', true),
            ],
        ],

    ],
```

Add the following environment variables to your `.env` file:

```
FILESYSTEM_DISK=cloudinary

CLOUDINARY_CLOUD_NAME=my-cloud-name
CLOUDINARY_API_KEY=my-api-key
CLOUDINARY_API_SECRET=my-api-secret
```

Older Laravel apps may still use `FILESYSTEM_DRIVER`; Laravel 9+ prefers `FILESYSTEM_DISK`.

Flysystem 3 and Laravel 13
--------------------------

[](#flysystem-3-and-laravel-13)

This package registers a **League Flysystem v3** adapter with Laravel’s `Storage` facade.

- **Exceptions:** On failure, `read` / `readStream` throw `UnableToReadFile`; `copy` throws `UnableToCopyFile`; `delete` throws `UnableToDeleteFile`; `createDirectory` / `deleteDirectory` throw `UnableToCreateDirectory` / `UnableToDeleteDirectory` (see [CHANGELOG](CHANGELOG.md)).
- **`deleteDirectory`:** Cloudinary’s Admin API only deletes **empty** folders. The adapter first destroys **shallow-listed files** under the logical path, then calls `delete_folder`—aligned with the legacy `deleteDir()` behaviour. Listing is shallow; deeply nested trees may need extra steps depending on how assets are organised.
- **`listContents`:** **Shallow** listing only; the `$deep` argument is ignored. Each Admin API `assets` call uses `max_results` =&gt; 500 **without** `next_cursor` pagination, so very large prefixes may not return a complete list.
- **`write` / `writeStream` vs `update` / `updateStream`:** Only `write` and `writeStream` set `lastUploadMetadata()` and the public `$meta` property. `update` and `updateStream` return the normalized metadata `array` from the upload (or `false` on failure) but **do not** update `lastUploadMetadata()`—it keeps the value from the last `write` / `writeStream`. Use the return value of `update` / `updateStream` when you need fresh metadata.
- **Other helpers:** `lastCopySucceeded()` and `lastDeleteSucceeded()` (and legacy public `$copied` / `$deleted`) reflect the outcome of the latest `copy` / `delete` calls on this adapter instance.

### Cloudinary folder modes

[](#cloudinary-folder-modes)

This adapter lists assets with the Admin API using **public ID `prefix`** and manages folders with **`subFolders` / `create_folder` / `delete_folder`**, which matches **legacy fixed folder mode** and typical public-ID paths. If your Cloudinary product environment uses **dynamic folder mode** only, some behaviours may differ; see [Folder modes](https://cloudinary.com/documentation/folder_modes) and the [Admin API](https://cloudinary.com/documentation/admin_api#folders).

### Continuous integration and integration tests

[](#continuous-integration-and-integration-tests)

The test suite includes optional **integration** tests that call the live Cloudinary API. They run only when `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET` are set to real values (for example via GitHub Actions secrets). The default `composer test` command excludes the `integration` group; run `vendor/bin/pest` without `--exclude-group` to include them locally.

🏗 File extension problem
------------------------

[](#-file-extension-problem)

Let's look at the following example:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->put('cat.jpg', $contents);
```

This will generate following URL with double extensions:

```
https://res.cloudinary.com/my-cloud-name/image/upload/v1/cat.jpg.jpg

```

To prevent this you should store your images without the file extension:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->put('cat', $contents);
```

This is now much better:

```
https://res.cloudinary.com/my-cloud-name/image/upload/v1/cat.jpg

```

### 🪐 How to use with Nova

[](#-how-to-use-with-nova)

We have a package for use with Laravel Nova: [Laravel Flysystem Cloudinary Nova](https://github.com/codebar-ag/laravel-flysystem-cloudinary-nova)

🗂 How to use folder prefix
--------------------------

[](#-how-to-use-folder-prefix)

Imagine the following example. We have different clients but want to store the assets in the same Cloudinary account. Normally we have to prefix every path with the correct client folder name. Fortunately, the package helps us here. We can configure a folder in our environment file like this:

```
CLOUDINARY_FOLDER=client_cat
```

Now all our assets will be prefixed with the `client_cat/` folder. When we store following image:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->put('meow', $contents);
```

It will produce following URL:

```
https://res.cloudinary.com/my-cloud-name/image/upload/v1/client_cat/meow.jpg

```

In the Media Library it is stored in `client_cat/meow` and you can retrieve the image with `meow`:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->getAdapter()->getUrl('meow');
```

You can use Cloudinary tranformation and options when retrieving the image:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->getAdapter()->getUrl([
    'path' => 'meow',
    'options' => ['w_250', 'h_250', 'c_thumb'],
]);
```

You can find all options in the [official documentation](https://cloudinary.com/documentation/transformation_reference)

This should increase the trust to store and retrieve your assets from the correct folder.

🔋 Rate limit gotchas
--------------------

[](#-rate-limit-gotchas)

All files in Cloudinary are stored with a resource type. There are three kinds of it: `image`, `raw` and `video`. For example if we want to check if a video exists, we need to make up to 3 requests. Every type needs to be checked on their own with a separate request.

Keep this in mind because the admin API is rate limited to 500 calls per hour.

The package does check in following sequence:

- `image` ➡️ `raw` ➡️ `video`

⚙️ Optional Parameters
----------------------

[](#️-optional-parameters)

Cloudinary has a lot of optional parameters to customize the upload. You can find all options in the [official documentation](https://cloudinary.com/documentation/image_upload_api_reference#upload_optional_parameters)optional parameters section.

You can pass all parameters as an array to the `put` method:

```
use Illuminate\Support\Facades\Storage;

Storage::disk('cloudinary')->put('meow', $contents, [
    'options' => [
        'notification_url' => 'https://mysite.example.com/notify_endpoint',
        'async' => true,
    ],
]);
```

`Note: if you find yourself using the same parameters for all requests, you should consider adding them to the config file. (see below)`

🔧 Configuration file
--------------------

[](#-configuration-file)

You can publish the config file with:

```
php artisan vendor:publish --tag="flysystem-cloudinary-config"
```

This is the contents of the published config file:

```
