How to upload images or other files with Laravel

Uploading files with Laravel is very simple, everything you need is already built in.

The view:


    echo Form::open_for_files('upload', 'POST');

    echo Form::label('file', 'File:');
    echo Form::file('image');

    echo Form::submit('Upload');

    echo Form::close();

Note that we used “open_for_files()” which generates the form with ‘enctype=”multipart/form-data”‘ needed to upload files.

The Controller

We process the form just like any other form, Laravel’s Validator library has validation options for files, for this tutorial we make use of “image” rule to specify that the file should be an image and “max:” which represents the max file size in kilobytes.

Another useful rule for files is “mimes:” which we use to check for specific extensions, e.g. “mimes:jpg, png”, for this tutorial will keep it simple.

If you need to access the file and it’s attributes use Input::file(). e.g. Input::file(‘picture.size’); To retrieve all items from $_FILES use Input::file().

For uploading we use Input::upload() method that takes 3 parameters: the name of the input, the path were to upload the file and the file name(with extension)

    /*
     * Validate
     */
    $rules = array(
        'image' => 'image|max:300'
    );

    $inputs = array(
        'image' => Input::file('image')
    );

    $validation = Validator::make($inputs, $rules);

    if( $validation->passes() )
    {

        //set the name of the file
        $filename = Input::file('image.name');

        //Upload the file
        Input::upload('image', 'public/uploads', $filename);

    }//if it validate

It’s that simple.
Note: This code only represents the uploading process and doesn’t handle situations like when for example the validation fails.

Advertisements

Compare 2 dates from input in validation Part 2

I found a better way to implement this by modifying validate_after and validate_before to check if the given value(the one used to compare against) exists as an input.

Use the same code from this tutorial except we don’t need the custom message(don’t forget the method that builds it),  we use the native  validate_after and validate_before and the extended Validator will contain:

 


<?php

class Validator extends Laravel\Validator
{

    /**
     * Validate the date is before a given date.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @param  array   $parameters
     * @return bool
     */
    protected function validate_before($attribute, $value, $parameters)
    {

        /*
         * If a input with the name equal to the value we compare with, we
         * use it, otherwise we proceed as usual
         */

        if( isset( $this->attributes[ $parameters[0] ] ) )
        {

          $value_to_compare = $this->attributes[ $parameters[0] ];

        }//if we have an input with this name
        else
        {

            $value_to_compare = $parameters[0];

        }//we compare with the provided value

        return ( strtotime( $value ) < strtotime( $value_to_compare ) );

    }//validate_before

    /**
     * Validate the date is after a given date.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @param  array   $parameters
     * @return bool
     */
    protected function validate_after($attribute, $value, $parameters)
    {
        /*
         * If a input with the name equal to the value we compare with, we
         * use it, otherwise we proceed as usual
         */

        if( isset( $this->attributes[ $parameters[0] ] ) )
        {

            $value_to_compare = $this->attributes[ $parameters[0] ];

        }//if we have an input with this name
        else
        {

            $value_to_compare = $parameters[0];

        }//we compare with the provided value

        return ( strtotime( $value ) > strtotime( $value_to_compare ) );

    }//validate_after

}//end class

Compare 2 dates from input in validation

Note: a better way to achieve this was posted here

This tutorial will show you how to create a custom validation rule in Laravel to compare 2 dates, e.g. when you want to check if a start date is before end date.

First create a file named Validator.php in libraries and comment(or remove) the alias from config/application.php. This will overwrite the Validation class, the autoload from Laravel will search Validator in libraries.

Next add the following code to the file:

<?php

class Validator extends Laravel\Validator
{

    /**
     * Validate that a date is before another one
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @param  array   $parameters
     * @return bool
     */
    public function validate_before_date($attribute, $value, $parameters)
    {

        return strtotime( $value ) < strtotime( $this->attributes[ $parameters[0] ] );

    }//validate_before_date

    /**
     * Replace all place-holders for the different rule.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array   $parameters
     * @return string
     */
    protected function replace_before_date($message, $attribute, $rule, $parameters)
    {

        return str_replace(':other', $this->attribute($parameters[0]), $message);

    }//replace_before_date

}//end class

Explications:
validate_before_date($attribute, $value, $parameters)

$value is the value of the date you want to compare (e.g. start date)
$parameters will be an array of values passed to validations after “:” (e.g. for ‘start_date’ => ‘before_date:end_date’, $parameters[0] will be equal to ‘end_date’).
$this->attributes[] contains all inputs(The first parameter from Validator::make())

replace_before_date($message, $attribute, $rule, $parameters)

This method is used when generating error message, we want to replace “:other” with $parameters[0] which will be equal to the input we want to compare against.
To add the custom error message:

$messages = array(
    'before_date' => ":attribute must be before :other"
);

To use it pass it as the third parameter:


$validation = Validator::make($inputs, $rules, $messages);

Or add it to the validation language file in custom array:

 'custom' => array(
          'before_date' => ":attribute must be before :other"
 )
 

Example

Copy paste the code below to test it, the validation should fail

$inputs = array(
  'start_date' => '2013-01-20',
  'end_date'   => '2013-01-15'
);

$rules = array(
  'start_date' => 'required|before_date:end_date',
  'end_date'   => 'required'
);

$messages = array(
  'before_date' => ":attribute must be before :other"
);

$validation = Validator::make($inputs, $rules, $messages);

if( $validation->fails() )
{

  echo '<pre>';
  print_r($validation->errors);
  echo '</pre>';

}//if it didn't validate

How to use mysql_insert_id in Laravel

At this moment the docs are very vague about this, searching “mysql_insert_id” won’t return anything but if you look through the docs you’ll find multiple ways to get that id:

With PDO

$id = DB::connection('mysql')->pdo->lastInsertId();

With insert_get_id() method that works with Fluent or Eloquent objects(will work only if the name of the auto-incrementing column is “id”):

$id = DB::table('users')->insert_get_id(array('name' => 'John Doe'));

With Eloquent’s create() method, which returns the model instance for the newly inserted record, or false if the insert failed.

$user = User::create(array('name' => 'John Doe'));

$user->id;

How to make database transaction with Laravel

This is another important feature that is missing from the docs(at least at this moment), but you can find it on API docs.  I’ve found that there are 2 ways:

With PDO:

DB::connection()->pdo->beginTransaction();

DB::connection()->pdo->commit();

DB::connection()->pdo->rollBack();

More info about it here

Or with DB object:

DB::transaction(function() use ($user_id)
{
    DB::table('user')->delete($user_id);
    DB::table('user_permissions')->where('user_id', '=', $user_id)->delete();
});

DB::transcation() uses PDO to perform the transaction.

How to switch language

With Laravel, this can be done easily in 2 steps:

1. First define in config/application.php in “languages” array all the languages your app supports.

2. Whenever you want a different language to be used (e.g. by validation errors) prepend to your url the language, for example if you want Arabic to be used instead of the default one (defined in config/application.php in “language”) on /user/add route change route to /ar/user/add

Helpers library

Note: this information is not available in the official docs, I found it by browsing through the source of laravel which I highly recomend for a better understanding of the framework.

The class is under laravel folder / helpers.php. I will not list all functions, only those I found very useful:

To retrieve a language line:

__($line);

To dump a value and exit:

dd($value);

To remove an array item with “dot” notation:

array_forget($array, 'user.data.name');

Convert an Eloquent model to JSON object:

eloquent_to_json($model);

Get the file size of a file in a human readable form (Bytes, KiB etc):

get_file_size($size);

And many more, feel free to explore, the library and the whole framework is very well commented.