PHPackages                             djam90/user-image-handling - 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. djam90/user-image-handling

ActiveLibrary

djam90/user-image-handling
==========================

Handle user-uploaded images in Laravel

3.0.1(4y ago)111PHPPHP &gt;=5.4.0

Since Apr 5Pushed 4y ago1 watchersCompare

[ Source](https://github.com/djam90/user-image-handling)[ Packagist](https://packagist.org/packages/djam90/user-image-handling)[ RSS](/packages/djam90-user-image-handling/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (4)Versions (8)Used By (0)

This package is incomplete

Installation
------------

[](#installation)

- run `composer require serosensa/user-image-handling @dev`
- run `php artisan vendor:publish --tag=userimage-js-assets`
- add `require('./user-image/userImageApp.js')` to the main app.js file before the main vue instance is created but after vue is required
- run `php artisan vendor:publish --tag=userimage-sass-assets`
- add `@import "user-image/user-image"` in the vendor section of your main scss sheet (after your settings but before any custom styling)

Usage &amp; Functionality
-------------------------

[](#usage--functionality)

- This package ships with a number of default routes and a default UserImageController
- You may use these default routes and associated methods, or copy the relevant method from UserImageController and modify as required.
- If you choose to create your own controller, you can still utilise useful methods from the ImageService. To access methods from eg the ImageService, extend the UserImageBaseController `class MyImageController extends UserImageBaseController`
- Uploading an image is considered as a separate step from creating a database record of the image. Ensure both steps are completed so that images can be retrieved.

\###Default Behaviour

#### Image Upload

[](#image-upload)

Use the `file-upload-fetch` component, posting to fetch-image-upload and using UserImageController@fetchImageUpload Component receives json of file data including location and emits event `file-upload` to its parent //TODO use v-model to pass this nicely It is the responsibility of the parent to catch this event and use the data as appropriate (eg creating a database record)

#### Saving an image record

[](#saving-an-image-record)

Pass the fileData generated by file-upload-fetch to ImageService@saveImageRecords; Will save image records to the default `UploadedImages` table (see further info in this readme). You may pass a model name (eg Article) to tie the image to a specific related model in the database.

#### Upload and save record

[](#upload-and-save-record)

The method `UserImageController@fetchImageUploadAndRecord` handles both these steps by combining the functionality above. Simply create a route to this method and set the post-url on file-upload-fetch to this route.

### Upload an Image (Async)

[](#upload-an-image-async)

Upload a file and receive json which can be used to request the image from the server

- Use the `file-upload-fetch` vue component **Props**
    - postUrl (optional: default /fetch-file-upload)
    - NOT USED - fileDest - a writeable folder within the public disk
    - NOT USED parentIdentity (array: parent model, id) - used to ensure that the correct vue parent comp catches the event. Not used in controller
    - multiple (optional: default false)
- Displays a file-upload input
- the controller reached by the postUrl should save the image file to storage. The method `ImageService@fetchImageUpload` does this and returns json. See *ImageService Methods*
- Expects to receive json with file data after upload.
- TODO display the uploaded files in this component, plus existing uploaded files (optional)
- Emits an event `file-upload` to event bus with parentIdentity and fileData on successful upload. Parent can catch and use this data //TODO Add this data to parent with v-model instead

### Upload an Image (Post) (Not full tested)

[](#upload-an-image-post--not-full-tested)

- Use a regular file upload field posting to a controller.
- The controller may use `ImageService@imageUpload` to rename and resize the file, and `ImageService@saveImageRecords` to create database records in the UploadedImages table (see *ImageService Methods*)

### Save / Store an Image Record

[](#save--store-an-image-record)

- Once an image is uploaded, save a record of it to the relevant database table
- The data returned from `ImageService@imageUpload` may be used for this
- A default uploaded\_images table is created by this package (see *Image Storage &amp; Retieval*)
- The `ImageService@saveImageRecords` method can be used to save records to the default table (see *ImageService Methods*)
- There is also a default model for uploaded images (see *Default UploadedImages Model*)
- Alternatively, save a record to another table as required
- Images uploaded via the `file-upload-fetch` component will by default return the image data to the parent form. Create database records in the controller saving the parent form. Alternatively, set the file-upload-fetch postUrl to a controller which creates database records directly

### ImageService Methods

[](#imageservice-methods)

#### ImageService@imageUpload

[](#imageserviceimageupload)

**params**- request object - destination for files - name of field containing images (optional, default: images) - width to downscale image files to (optional, default: 2000px) Must be run once per file input field in the form Accepts either single or multiple images per file input. Does not run validation - validate before calling **Returns** array of file data, even if only 1 file in the field

#### ImageService@fetchImageUpload

[](#imageservicefetchimageupload)

Uses `ImageService@imageUpload` - same params Validates the image(s) **Returns** json of file data (TODO handle multiple files per field)

#### ImageService@saveImageRecords

[](#imageservicesaveimagerecords)

//TODO not tested Saves image records to the default `UploadedImages` table. **params**- uploaded image data (single image) - parent model object (optional, default:null) Uploaded images data is expected to contain details such as filename and path. The data returned from `ImageService@ImageUpload` is suitable Accepts an array of images, or a single image TODO does this work? is testing to see if image data is an array, but won't a single image still be an array? alt text below Accepts the data for a single image - should be run within a foreach loop for processing multiple images If a parent was sent, saves the name of the parent model and the parent Id to the image record. Else, these are null. **Returns** array of records, or single record

#### ImageService@imageEditorSave

[](#imageserviceimageeditorsave)

Processes the data sent by the `image-editor` component **params**- image instance (retreive the image in the calling controller and pass through) - request object **Returns** json of image data to be used by the component

### Image Storage and Retreival

[](#image-storage-and-retreival)

#### Default UploadedImages table

[](#default-uploadedimages-table)

//TODO - have to manually copy the migration, not working in package Stores a record of image data Used by `ImageService@saveImageRecords`Optionally related to a parent model and id - this can be used to retrieve images from the table, eg by calling `UploadedImage::where(parent_model, 'article')` or `UploadedImage::where('parent_model', 'article')->where('parent_id', $parentId)`Alternatively, store the `id` from this table in a pivot table to be accessed by any other model as required. It is also

**Required fields**- filename - path **Optional Fields**- filetype - filesize - category\_id - caption - is\_primary (default:0) - is\_shown (default: 1) - parent\_model - the name of the model which represents the parent - parent\_id - the id of the parent

#### Default UploadedImages model

[](#default-uploadedimages-model)

Extend this model to add any additional functionality required - `class MyUploadedImageModel extends Serosensa\UserImage\UploadedImage`. Sets dates and guarded on created\_at and updated\_at fields

- methods?

### Display / Edit Existing Images

[](#display--edit-existing-images)

#### Image-display Component

[](#image-display-component)

- Use the `image-display` vue component for each image (eg with v-for) **Props** - image
- Displays the image and associated data
    - use slot `info-panel-default` to override default data
    - use slot `info-panel-extra` to add additional data
    - also has a default slot outside of the info panel

#### Image-editor Component

[](#image-editor-component)

- within the image-display component, add the `image-editor` component **Props**
    - image,
    - postUrl (without image id or '/')
    - categories (optional)
- Allows for:
    - changing is\_shown value
    - changing is\_primary value
    - updating the caption
    - rotating the image
    - setting a category (optional via slot)
- Displays an edit button, with a modal to edit the image. Has some default options and a number of slots
    - slot `title`
    - slot `fields-default` displays the default edit fields. Override this if required.
    - slot `categories` if a category selector is required. If used, set `slot-scope="categoriesScope"`
    - slot `fields-extra` for any additional fields
    - slot `label_is_primary`
    - slot `label_is_shown`
    - slot `label_caption`
    - slot `subtext_caption` additional text below the caption Validation should be carried out in the controller / custom request as normal. On validation fail, laravel returns a json array of errors, which the editor window will display alongside the appropriate fields.

```

        Edit Image

```

##### Image Editor Categories

[](#image-editor-categories)

To display a category selector within the imageEditor:

- pass an array of categories the `categories` prop on image-editor
- each category must have at least an id and a name. The component generates a categoryName using the 'name' field of each category
- ensure the image has a `category_id` field
- add `slot-scope="categoriesScope"` to the element utilising the slot, which allows sharing of data between the slot and the parent. The example below creates radio buttons to select a category:

```

    Image Type:

        {{ option.name }}

```

#### Field-errors Component

[](#field-errors-component)

- use the `field-errors` component alongside any field that may return an error
- displays all errors for a given field
- pass in the errors object and the name of the field to display errors for

```

```

---

Fuller details
--------------

[](#fuller-details)

//TODO - some of this is superceeded by the above / needs updating

### JS files (vue / general frontend)

[](#js-files-vue--general-frontend)

- The file `userImageApp.js` registers all vue components provided by the package,
- Export this file by running `php artisan vendor:publish --tag=userimage-js-assets` - this will export all js files to `resources/assets/js/user-image`.
- WARNING if these files are directly modified as they may be over-written on package updates. To force an update and overwrite files, add `--force` to the publish command
- Require this file in the applications' main app.js `require('./user-image/userImageApp.js');` before the main vue instance is created but after vue is required

### Styling

[](#styling)

- include the \_user-image.scss sheet in your main sass file. Include this before your own style sheets so that you can easily override the styling
- Publish this file by running `php artisan vendor:publish --tag=userimage-sass-assets` - this will export scss files to `resources/assets/sass/user-image`

#### Icons

[](#icons)

- All icons in this package have the class `image-editor-icon`
- Icons can be re-coloured by setting values for `$user-image-icon-color-1` and `$user-image-icon-color-2` - set these values before pulling in the vendor style sheets (eg in settings) to override the defaults. Some icons will only use color1.
- You may also override styles by class to style icons in different contexts
- Icons exist as js files in /vendor/serosensa/icons which are pulled in by each template as required

Image Uploads - via ImageService
--------------------------------

[](#image-uploads---via-imageservice)

- the ImageService handles all aspects of image file uploads
- it must be passed the $request from the form in which image files were uploaded
- the service can handle multiple images being uploaded per field
- the service can handle multiple file upload fields per form if unique field names are set
- each upload field can have its own destination folder
- destination folders should be .gitignored as they will change on the server independently of source code
- the imageService saves files to the 'public' disk defined in config/filesystems. If this is the /app/public folder, files saved here are publicly visible via their url / filename

File Destinations / Writeable folders
-------------------------------------

[](#file-destinations--writeable-folders)

Folders in which uploaded files are to be saved must be writeable. To do this, `chmhod -R 777 public/foldername`

### Image Upload forms

[](#image-upload-forms)

- Forms containing file uploads must have `enctype="multipart/form-data` or the parameter files =&gt; true (if using LaravelCollective forms)
- To upload multiple images per field, add `multiple` to the field and `[]` to the field name in the view file

#### Default Field names - one file upload field only

[](#default-field-names---one-file-upload-field-only)

- by default, the `ImageService@imageUpload` function expects an upload field named `images`. This default can be used if there is only one upload field in the request, or an alternative name can be used and passed to the service.

#### Custom Field names - one or more file upload fields

[](#custom-field-names---one-or-more-file-upload-fields)

- the ImageService must be called once PER UPLOAD FIELD
- the file upload fields must have unique, custom names, eg `thumbnail`

### Image Upload in Controller

[](#image-upload-in-controller)

- See the ExampleController in the `/examples` directory for an example controller function
- The ImageService handles most of the image manipulation - the controller must simply call the ImageService, pass values, and save the resulting data.
- uploaded files should be validated (to ensure are correct image filetypes) before imageService@imageUpload is called. This package includes an `IsValidImageRequest` which you may use. This will return an errorbag `isValidImage` if validation fails.
- if imageService is mistakenly called with no files in the request, it will return null rather than generate an error
- the ImageService always returns a nested array of images data - regardless of number of files uploaded. Loop this array to extract data for each image.

#### ImageService@imageUpload Functionality

[](#imageserviceimageupload-functionality)

- Once Called, the imageservice:
- loops each image
- renames if a file by the same name already exists
- saves the file to the specified folder (after stripping any leading /, as this causes issues with saving the resized file)
- resizes the file to the specified max width (unless is an svg)
- returns an array containing a data array for each image
- this returned data should then be processed as required by the calling function - for instance, saving the filename to the database

Image Rotation
--------------

[](#image-rotation)

- The `image-editor` component pulls in the `image-rotation` component, but this is also available separately.
- The image-rotation component should be passed the database id of the image being editied, eg ``
- when a rotation button is clicked, the component emits an event which is collected by the editor and used to transform the image preview.
- a rotation value is added to the imageData and therefore passed to the controller where it can be used. See `ExampleController` for a demo - the `ImageService` handles the actual rotation, so this functionality can be called anywhere.
- When edits are saved, the `image-display` component catches the event emitted from the image-editor. This triggers a reload from disk of the updated image, so any changes (including rotation and any others which may be enabled in future) are reflected in the displayed image
- the `image-editor` component also reloads the image from disk and resets the rotation value, so it is 'fresh' when it is next loaded
- the reload from disk is accomplished by setting the src of the image to a `versionedImage` data object. This is set to the orignal filename on load, but overwritten by calling the `makeVersionedImage()` function whenever the image should be updated (eg on save of edits). This function appends a random version number to the end of the filename, causing a reload

---

TODO
----

[](#todo)

- Add form / styles package as a dependency (replace existing includes in this package?)
- IsValidImageRequest not properly tested - fetch file uploads validated in ImageService@fetchFileUpload

---

Useful References
-----------------

[](#useful-references)

- Creating a package -
- Laravel-specific package development, including info on publishing files -
- Developing a package locally -

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 71.4% 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 ~247 days

Recently: every ~287 days

Total

6

Last Release

1719d ago

Major Versions

1.0.0 → 2.0.02018-07-04

2.0.2 → 3.0.02021-08-24

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/979271?v=4)[Daniel Twigg](/maintainers/djam90)[@djam90](https://github.com/djam90)

---

Top Contributors

[![RandomWeasel](https://avatars.githubusercontent.com/u/16453825?v=4)](https://github.com/RandomWeasel "RandomWeasel (5 commits)")[![djam90](https://avatars.githubusercontent.com/u/979271?v=4)](https://github.com/djam90 "djam90 (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/djam90-user-image-handling/health.svg)

```
[![Health](https://phpackages.com/badges/djam90-user-image-handling/health.svg)](https://phpackages.com/packages/djam90-user-image-handling)
```

###  Alternatives

[bagisto/bagisto

Bagisto Laravel E-Commerce

26.2k161.6k7](/packages/bagisto-bagisto)[laravolt/avatar

Turn name, email, and any other string into initial-based avatar or gravatar.

2.0k5.4M31](/packages/laravolt-avatar)[unisharp/laravel-filemanager

A file upload/editor intended for use with Laravel 5 to 10 and CKEditor / TinyMCE

2.2k3.3M73](/packages/unisharp-laravel-filemanager)[aimeos/aimeos-core

Full-featured e-commerce components for high performance online shops

4.5k346.9k48](/packages/aimeos-aimeos-core)[intervention/image-laravel

Laravel Integration of Intervention Image

1496.5M100](/packages/intervention-image-laravel)[bkwld/croppa

Image thumbnail creation through specially formatted URLs for Laravel

510496.0k22](/packages/bkwld-croppa)

PHPackages © 2026

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