makeabledk / laravel-cloud-images
Installs: 6 192
Dependents: 0
Suggesters: 0
Security: 0
Stars: 58
Watchers: 6
Forks: 6
Open Issues: 0
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- illuminate/container: ^10.0|^11.0
- illuminate/filesystem: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
- spatie/laravel-google-cloud-storage: ^2.0
Requires (Dev)
- codedungeon/phpunit-result-printer: ^0.30.0
- doctrine/dbal: ^3.0
- intervention/image: ^2.4
- laravel/laravel: 10.*|11.*
- mockery/mockery: ^1.5
- phpunit/phpunit: 9.*
- rutorika/sortable: ^9.0|^10.0
Suggests
- intervention/image: Intervention image is required to read exif data
- rutorika/sortable: Required for using extended media library functionality
- dev-master
- v4.0.0
- v3.0.0
- v2.0.0
- v1.4.0
- v1.3.0
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.0
- v0.10.0
- v0.9.0
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.0
- v0.4.1
- v0.4.0
- v0.3.0
- v0.2.1
- v0.2.0
- v0.1.0
- dev-feat/laravel-10-11
- dev-feat/use-spatie-google-cloud-storage
- dev-feat/php-8
- dev-feat/github-actions
- dev-feat/laravel-8
- dev-feat/nova-field-use-request
- dev-feat/laravel-7
- dev-feat/nova-field
- dev-feat/deletion
- dev-feat/upgrade-laravel-6
- dev-feat/responsive-image-contract
- dev-feat/responsive-images
This package is auto-updated.
Last update: 2024-10-19 15:03:48 UTC
README
This package provides a convenient to manage Google App Engine Images API through Laravel.
Images API allows you to upload an image once to your GCS bucket and afterwards generate unlimited thumbnails just by requesting the specified size in the image-url. No delay, storage concerns or re-generate commands.
Important
Please checkout https://github.com/makeabledk/appengine-php-imageserver for more information on Images API and how to setup an imageserver for your project.
This package assumes you already have a configured App Engine imageserver and GCS Bucket.
Installation
You can install this package via composer:
composer require makeabledk/laravel-cloud-images
Add a new gcs
disk to your filesystems.php
config
'gcs' => [ 'driver' => 'gcs', 'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'your-project-id'), 'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE', '/path/to/service-account.json'), 'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'your-bucket'), ],
See https://github.com/spatie/laravel-google-cloud-storage for more details about configuring filesystems.php
.
Creating a Google Service Account
You can create a service account key file through these steps
- Head to your project's Google Cloud Console and locate IAM -> Service accounts
- Create a new service account with an appropriate name, ie.
sa-PROJECT-NAME-webapp-ENVIRONMENT
. - On the second step it prompts you to grant permissions. You should as a minimum grant
Storage Object Admin
permissions - Finally you should
Create key
and download a json key file. Place it in yourstorage
folder and set path infilesystems.php
accordingly
Upgrading from 0.16.x -> 0.17.0
This release introduces new database fields for responsive images. Please publish migrations and optionally generate placeholders.
php artisan vendor:publish --provider="Makeable\CloudImages\CloudImagesServiceProvider" php artisan migrate php artisan cloud-images:placeholders
Upgrading from 2.x --> 3.x
Starting with version 3 this package uses spatie/laravel-google-cloud-storage
instead of superbalist/laravel-google-cloud-storage
.
- Please ensure you refer to the configuration options in laravel-google-cloud-storage#installation.
- Specifically make sure you change your disk configuration in
config/filesystems.php
@gcs.key_file
-->gcs.key_file_path
.
Basic usage
Upload an image
Easily upload a \Illuminate\Http\File
or \Illuminate\Http\UploadedFile
to your GCS bucket and create an image-url for it.
$file = request()->file('image'); // assuming you uploaded a file through a form $uploaded = \CloudImage::upload($file); // filename will be a hash of the uploaded file $uploadedToPath = \CloudImage::upload($file, 'path/filename.jpg'); // optionally specify path and filename yourself echo $uploaded->url; // imageserver url, eg: http://lh3.googleusercontent.com/... echo $uploaded->path; // path in bucket
Delete an image
Using the delete
method will both delete the bucket file and destroy serving-image URL.
\CloudImage::delete('path/filename.jpg');
Note that image-serving URL's can take up to 24 hours to clear from cache
The good stuff: Generating images on the fly
Now that our image is served by Google, we can manipulate it on the fly.
All you have to do to start manipulating images, is an instance of ImageFactory
:
$image = \CloudImage::upload($file)->make(); // or ... $image = new \Makeable\CloudImages\ImageFactory($url);
Contain to max dimension
$image->maxDimension(150)->get();
Example result:
Crop to dimensions
$image->crop(300, 100)->get(); // Crop from top $image->cropCenter(300, 100)->get(); // Crop from center
Example result:
Stretch to dimensions
$image->scale(300, 100)->get();
Example result:
Blur
$image->blur(15)->get(); // Blur 15%
Example result:
Custom parameters (advanced)
If the functionality you need is not provided by the package, you can specify your own google-compatible parameters:
$image->original()->param('fv')->get(); // This image will be flipped vertically
Checkout our makeabledk/appengine-php-imageserver repository for more information on available parameters.
Media Library usage (recommended)
For the examples so far there has been no need to publish any migrations. You are completely free to only use this package for uploading and retrieving image files from Google.
However, while uploading and serving images is all well and good, you will likely need to store the references in your database and attach them to some existing models.
This package will likely provide you with most of the functionality you'll ever need for dealing with images in your application.
Extended installation
1. Install rutorika/sortable
package which is used to track sort-order (required)
composer require rutorika/sortable
2. Install intervention/image
to read and store exif-data on your images (optional)
composer require intervention/image
3. Publish and run migrations
php artisan vendor:publish --provider="Makeable\CloudImages\CloudImagesServiceProvider"
php artisan migrate
Uploading images
$image = \Makeable\CloudImages\Image::upload($file); // returns a persisted Image model instance (eloquent) echo $image->path; // bucket path echo $image->url; // image-serving url echo $image->meta; // exif data
Model attachment with multiple images
First, use the HasImages
trait on your parent model.
class Product extends Eloquent { use Makeable\CloudImages\HasImages; }
Now you have an images()
belongs-to-many relationship you can utilize as you normally would:
Product::first()->images()->attach(Image::first());
Ordering attached images
Images will be kept in the order you attach them. However, you are free to reorder them afterwards.
$product = Product::first(); $images = $product->images; // In this example we assume a collection of a few images $product->images()->moveBefore($images->get(2), $images->first());
Checkout the Sortable many to many section of the rutorika/sortable package.
Model attachment with a single image
If your model is expected to have just one image, you may use the convenient image()
helper provided by the same HasImages
trait.
class Product extends Eloquent { use Makeable\CloudImages\HasImages; }
// Always returns an Image instance - even if none uploaded $image = Product::first()->image();
On the Image
instance you may use the make()
method to generate the size you need.
// Returns a url (string) or NULL if no image attached $url = $image->make()->cropCenter(500, 400)->get();
Differentiating between image types
Sometimes you may wish to have different types of 'single images' on a model. Use the optional tag
parameter to achieve this behavior.
Product::first()->image('featured'); Product::first()->image('cover');
Note: Tagging is only intended through the image($tag)
helper as the rutorika/sortable
package does not differentiate between tags when applying order
.
Replacing images
Use the replaceWith
method on the Image
model to swap any Image
with another while preserving attachments.
This is especially useful in combination with the image()
helper:
Product::first()->image('featured')->replaceWith(Image::upload($file));
- If the product did not have a 'featured' image, it would simple attach the new one
- If the product did already have 'featured' image it would get replaced, and the old one deleted
Pro tip: Use an eloquent mutator to set the new image
class Product extends Eloquent { use \Makeable\CloudImages\HasImages; public function setImageAttribute($file) { return $this->image()->replaceWith(Image::upload($file)); } }
Product::first()->image = request('image'); // replace image with an UploadedFile 'image'
In your controller it would work seamlessly when validating and filling
the model (Laravel 5.5 example).
public function store(Request $request) { return Product::create( $request->validate([ 'image' => 'required|image', // ... some other fields ]) ); }
Configuring image sizes per model
Often times you want a few pre-configured sizes available. In this example we would like 'square' and 'wide' available on our Product
model.
We may extend the Image
model and use that on our Product->images()
relationship.
class Product extends Eloquent { use \Makeable\CloudImages\HasImages; protected $useImageClass = ProductImage::class; }
class ProductImage extends \Makeable\CloudImages\Image { public function getSquareAttribute() { return $this->make()->cropCenter(500, 500)->get(); } public function getWideAttribute() { return $this->make()->cropCenter(1200, 400)->get(); } }
Now you can access the sizes simply by referencing them as properties.
echo Product::first()->image()->square; // single image usage echo Product::first()->images->first()->wide; // multiple images usage
Remember to add the sizes to $appends
attribute if you want them available when casting to array:
class ProductImage extends Image { protected $appends = ['square', 'wide']; // ... }
In Laravel 5.5, ApiResources would be a great place to append your image sizes as well.
Responsive images
Given the previous example of a product image, we may use the responsive()
method to generate a collection of responsive image sizes.
By doing this, we can serve srcset
optimized images on our website.
// Returns collection of ImageFactory instances width contiously smaller images Product::first()->image()->make()->original()->responsive()->get(); // Returns contents of the html srcset attribute Product::first()->image()->make()->original()->responsive()->getSrcSet(); // Returns an array containing src, srcet and width attribute - especially useful for API responses Product::first()->image()->make()->original()->responsive()->toArray(); // Returns <img> element with srcset attribute Product::first()->image()->make()->original()->responsive()->toHtml(); (string) Product::first()->image()->make()->original()->responsive();
Of course all the available transformations are still available for responsive images.
Product::first()->image()->make()->crop(500, 400)->param('fv')->responsive()->get();
The approach for responsive images is heavily inspired by the spatie/laravel-medialibrary package and offer the same functionality (including placeholders).
Consider reading their documentation for a very thorough explanation of the concept.
Also be sure to checkout their demo here: Responsive images demo
Finally consider checking out ResponsiveTest.php for more usage examples this package offers.
Cleaning up old images
Deleting an image
When deleting an Image
instance, the CloudImage::delete()
method is automatically fired to delete the actual bucket file.
Deleting images with no attachment
Over time your images
table may get bloated with images that no longer has model-attachments to them.
Use the cloud-images:cleanup
command to delete images (along with the actual bucket files) that are no longer used.
php artisan cloud-images:cleanup
Testing
You can run the tests with:
composer test
Contributing
We are happy to receive pull requests for additional functionality. Please see CONTRIBUTING for details.
Credits
- Rasmus Christoffer Nielsen
- Spatie for their awesome spatie/laravel-medialibrary
- All Contributors
License
Attribution-ShareAlike 4.0 International. Please see License File for more information.