Package Data | |
---|---|
Maintainer Username: | expstudio |
Maintainer Contact: | waycs16@gmail.com (Watee Wichiennit) |
Package Create Date: | 2014-05-20 |
Package Last Update: | 2014-06-22 |
Home Page: | |
Language: | PHP |
License: | MIT |
Last Refreshed: | 2025-02-17 03:01:54 |
Package Statistics | |
---|---|
Total Downloads: | 99 |
Monthly Downloads: | 0 |
Daily Downloads: | 0 |
Total Stars: | 3 |
Total Watchers: | 2 |
Total Forks: | 1 |
Total Open Issues: | 0 |
#LaraClip
Attachment upload package for Laravel 4 with PHP5.3.x support.
LaraClip was downgrade from Codesleeve/Stapler by Watee Wichiennit.
LaraClip currently requires php >= 5.3 (LaraClip is take out traits and go back to normal class inheritance).
LaraClip is distributed as a composer package, which is how it should be used in your app.
Install the package using Composer. Edit your project's composer.json
file to require expstudio/laraclip
.
"require": {
"laravel/framework": "4.*",
"expstudio/laraclip": "dev-master"
}
Once this operation completes, the final step is to add the service provider. Open app/config/app.php
, and add a new item to the providers array.
'Expstudio\LaraClip\LaraClipServiceProvider'
Do not use new PHP5.4+ array syntax ([] square bracket). Use old style array ( array() ) instead.
In the document root of your application (most likely the public folder), create a folder named system and grant your application write permissions to it.
In your model:
use Expstudio\LaraClip\LaraClip;
class User extends LaraClip {
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('image', array(
'styles' => array(
'large' => '450x450#',
'thumb' => '100x100#'
)
));
parent::__construct($attributes);
}
}
Make sure that the
hasAttachedFile()
method is called right beforeparent::__construct()
of your model.
From the command line, use the migration generator:
php artisan laraclip:fasten users avatar
php artisan migrate
In your new view:
<?= Form::open(['url' => action('UsersController@store'), 'method' => 'POST', 'files' => true]) ?>
<?= Form::file('avatar') ?>
<?= Form::submit('save') ?>
<?= Form::close() ?>
In your controller:
public function store()
{
// Create a new user, assigning the uploaded file field ('named avatar in the form')
// to the 'avatar' property of the user model.
$user = User::create(['avatar' => Input::file('avatar')]);
}
In your show view:
<img src="<?= $user->avatar->url() ?>" >
<img src="<?= $user->avatar->url('medium') ?>" >
<img src="<?= $user->avatar->url('thumb') ?>" >
To detach (reset) a file, simply call the clear() method of the attachment attribute before saving (you may also assign the constant LARACLIP_NULL):
$user->avatar->clear();
$user->save();
or
$user->avatar = LARACLIP_NULL;
$user->save();
This will ensure the the corresponding attachment fields in the database table record are cleared and the current file is removed from storage. The database table record itself will not be destroyed and can be used normally (or even assigned a new file upload) as needed.
LaraClip works by attaching file uploads to database table records. This is done by defining attachments inside the table's corresponding model and then assigning uploaded files (from your forms) as properties (named after the attachments) on the model before saving it. In essence, this allows uloaded files to be treated just like any other property on the model; laraclip will abstract away all of the file processing, storage, etc so you can focus on the rest of your project without having to worry about where your files are at or how to retrieve them.
A model can have multiple attachments defined (avatar, photo, foo, etc) and in turn each attachment can have multiple sizes (styles) defined. When an image or file is uploaded, LaraClip will handle all the file processing (moving, resizing, etc) and provide an attachment object (as a model property) with methods for working with the uploaded file. To accomplish this, four fields (named after the attachemnt) will need to be created (via laraclip:fasten or manually) in the corresponding table for any model containing a file attachment. For example, for an attachment named 'avatar' defined inside a model named 'User', the following fields would need to be added to the 'users' table:
Inside your table migration file, something like this should suffice:
$table->string("avatar_file_name")->nullable();
$table->integer("avatar_file_size")->nullable();
$table->string("avatar_content_type")->nullable();
$table->timestamp("avatar_updated_at")->nullable();
Configuration is available on both a per attachment basis or globally through the configuration file settings. LaraClip is very flexible about how it processes configuration; global configuration options can be overriden on a per attachment basis so tha you can easily cascade settings you would like to have on all attachments while still having the freedom to customize an individual attachment's configuration. To get started, the first thing you'll probably want to do is publish the default configuration options to your app/config directory.
php artisan config:publish expstudio/laraclip
Having done this, you should now be able to configure LaraClip however you see fit wihout fear of future updates overriding your configuration files.
The following configuration settings apply to laraclip in general.
Default values:
Filesystem (local disk) is the default storage option for laraclip. When using it, the following configuration settings are available:
Default values:
As your web application grows, you may find yourself in need of more robust file storage than what's provided by the local filesystem (e.g you're using multiple server instances and need a shared location for storing/accessing uploaded file assets). LaraClip provides a simple mechanism for easily storing and retreiving file objects with Amazon Simple Storage Service (Amazon S3). In fact, aside from a few extra configuration settings, there's really no difference between s3 storage and filesystem storage when interacting with your attachments. To get started with s3 storage you'll first need to add the AWS SDK to your composer.json file:
"require": {
"laravel/framework": "4.0.*",
"expstudio/laraclip": "dev-master",
"aws/aws-sdk-php": "2.4.*@dev"
}
Next, change the storage setting in config/laraclip.php from 'filesystem' to 's3' (keep in mind, this can be done per attachment if you want to use s3 for a specific attachment only). After that's done, crack open config/s3.php for a list of s3 storage settings:
Default values:
With LaraClip, uploaded files are accessed by configuring/defining path, url, and default_url strings which point to you uploaded file assets. This is done via string interpolations. Currently, the following interpolations are available for use:
LaraClip makes use of the imagine image library for all image processing. Out of the box, the following image processing patterns/directives will be recognized when defining LaraClip styles:
To create styles for an attachment, simply define them (you may use any style name you like: foo, bar, baz, etc) inside the attachment's styles array using a combination of the directives defined above:
'styles' => array(
'thumbnail' => '50x50',
'large' => '150x150',
'landscape' => '150',
'portrait' => 'portrait' => 'x150',
'foo' => '75x75',
'fooCropped' => '75x75#'
)
For more customized image processing you may also pass a callable type as the value for a given style definition. LaraClip will automatically inject in the uploaded file object instance as well as the Imagine\Image\ImagineInterface object instance for you to work with. When you're done with your processing, simply return an instance of Imagine\Image\ImageInterface from the callable. Using a callable for a style definition provides an incredibly amount of flexibilty when it comes to image processing. As an example of this, let's create a watermarked image using a closure (we'll do a smidge of image processing with Imagine):
'styles' => array(
'watermarked' => function($file, $imagine) {
$watermark = $imagine->open('/path/to/images/watermark.png'); // Create an instance of ImageInterface for the watermark image.
$image = $imagine->open($file->getRealPath()); // Create an instance of ImageInterface for the uploaded image.
$size = $image->getSize(); // Get the size of the uploaded image.
$watermarkSize = $watermark->getSize(); // Get the size of the watermark image.
// Calculate the placement of the watermark (we're aiming for the bottom right corner here).
$bottomRight = new Imagine\Image\Point($size->getWidth() - $watermarkSize->getWidth(), $size->getHeight() - $watermarkSize->getHeight());
// Paste the watermark onto the image.
$image->paste($watermark, $bottomRight);
// Return the Imagine\Image\ImageInterface instance.
return $image;
}
)
Create an attachment named 'picture', with both thumbnail (100x100) and large (300x300) styles, using custom url and default_url configurations.
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('picture', array(
'styles' => array(
'thumbnail' => '100x100',
'large' => '300x300'
),
'url' => '/system/:attachment/:id_partition/:style/:filename',
'default_url' => '/:attachment/:style/missing.jpg'
));
parent::__construct($attributes);
}
Create an attachment named 'picture', with both thumbnail (100x100) and large (300x300) styles, using custom url and default_url configurations, with the keep_old_files flag set to true (so that older file uploads aren't deleted from the file system) and image cropping turned on.
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('picture', array(
'styles' => array(
'thumbnail' => '100x100#',
'large' => '300x300#'
),
'url' => '/system/:attachment/:id_partition/:style/:filename',
'default_url' => '/:attachment/:style/missing.jpg',
'keep_old_files' => true
));
parent::__construct($attributes);
}
To store this on s3, you'll need to set a few s3 specific configuraiton options (the url interpolation will no longer be necessary when using s3 storage):
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('picture', array(
'styles' => array(
'thumbnail' => '100x100#',
'large' => '300x300#'
),
'default_url' => '/:attachment/:style/missing.jpg',
'storage' => 's3',
'key' => 'yourPublicKey',
'secret' => 'yourSecreteKey',
'bucket' => 'your.s3.bucket',
'keep_old_files' => true
));
parent::__construct($attributes);
}
LaraClip makes it easy to manage multiple file uploads as well. In laraclip, attachments (and the uploaded file objects they represent) are tied directly to database records. Because of this, processing multiple file uploades is simply a matter of defining the correct Eloquent relationships between models.
As an example of how this works, let's assume that we have a system where users need to have multiple profile pictures (let's say 3). Also, let's assume that users need to have the ability to upload all three of their photos from the user creation form. To do this, we'll need two tables (users and profile_pictures) and we'll need to set their relationships such that profile pictures belong to a user and a user has many profile pictures. By doing this, uploaded images can be attached to the ProfilePicture model and instances of the User model can in turn access the uploaded files via their hasMany relationship to the ProfilePicture model. Here's what this looks like:
In models/user.php:
// A user has many profile pictures.
public function profilePictures(){
return $this->hasMany('ProfilePicture');
}
In models/ProfilePicture.php:
public function __construct(array $attributes = array()) {
// Profile pictures have an attached file (we'll call it photo).
$this->hasAttachedFile('photo', array(
'styles' => array(
'thumbnail' => '100x100#'
)
));
parent::__construct($attributes);
}
// A profile picture belongs to a user.
public function user(){
return $this->belongsTo('User');
}
In the user create view:
<?= Form::open(['url' => '/users', 'method' => 'post', 'files' => true]) ?>
<?= Form::text('first_name') ?>
<?= Form::text('last_name') ?>
<?= Form::file('photos[]') ?>
<?= Form::file('photos[]') ?>
<?= Form::file('photos[]') ?>
<?= Form::close() ?>
In controllers/UsersController.php
public function store()
{
// Create the new user
$user = new User(Input::get());
$user->save();
// Loop through each of the uploaded files:
// 1. Create a new ProfilePicture instance.
// 2. Attach the file to the new instance (laraclip will process it once it's saved).
// 3. Attach the ProfilePicture instance to the user and save it.
foreach(Input::file('photos') as $photo)
{
$profilePicture = new ProfilePicture(); // (1)
$profilePicture->photo = $photo; // (2)
$user->profilePictures()->save($profilePicture); // (3)
}
}
Displaying uploaded files is also easy. When working with a model instance, each attachment can be accessed as a property on the model. An attachment object provides methods for seamlessly accessing the properties, paths, and urls of the underlying uploaded file object. As an example, for an attachment named 'photo', the path(), url(), createdAt(), contentType(), size(), and originalFilename() methods would be available on the model to which the file was attached. Continuing our example from above, we can loop through a user's profile pictures display each of the uploaded files like this:
// Display a resized thumbnail style image belonging to a user record:
<img src="<?= asset($profilePicture->photo->url('thumbnail')) ?>">
// Display the original image style (unmodified image):
<img src="<?= asset($profilePicture->photo->url('original')) ?>">
// This also displays the unmodified original image (unless the :default_style interpolation has been set to a different style):
<img src="<?= asset($profilePicture->photo->url()) ?>">
We can also retrieve the file path, size, original filename, etc of an uploaded file:
$profilePicture->photo->path('thumbnail');
$profilePicture->photo->size();
$profilePicture->photo->originalFilename();
As of LaraClip v1.0.0-Beta4, remote images can now be fetched by assigning an absolute URL to an attachment property that's defined on a model:
$profilePicture->photo = "http://foo.com/bar.jpg";
This is very useful when working with third party API's such as facebook, twitter, etc. Note that this feature requires that the CURL extension is included as part of your PHP installation.
When working with attachments, there may come a point where you wish to do things outside of the normal workflow. For example, suppose you wish to clear out an attachment (empty the attachment fields in the underlying table record and remove the uploaded file from storage) without having to destroy the record itself. As mentioned above, you can always set the attachment attribute to LARACLIP_NULL on the record before saving, however this only works if you save the record itself afterwards. In situations where you wish to clear the uploaded file from storage without saving the record, you can use the attachment's destroy method:
// Remove all of the attachment's uploaded files and empty the attacment attributes on the model:
$profilePicture->photo->destroy();
// For finer grained control, you can remove thumbnail files only (attachment attributes in the model will not be emptied).
$profilePicture->photo->destroy(['thumbnail']);
You may also reprocess uploaded images on an attachment by calling the reprocess() command (this is very useful for adding new styles to an existing attachment type where records have already been uploaded).
// Programmatically reprocess an attachment's uploaded images:
$profilePicture->photo->reprocess();
This may also be achieved via a call to the laraclip:refresh command.
Reprocess all attachments for the ProfilePicture model: php artisan laraclip:refresh ProfilePicture
Reprocess only the photo attachment on the ProfilePicture model: php artisan laraclip:refresh TestPhoto --attachments="photo"
Reprocess a list of attachments on the ProfilePicture model: php artisan laraclip:refresh TestPhoto --attachments="foo, bar, baz, etc"