Laravel 5.1: No supported encrypter found

RuntimeException in compiled.php line 6904:No supported encrypter found. The cipher and / or key length are invalid.

This errors occurs when you don’t have an application key defined, to do so run key:generate artisan command.

Advertisements

Getter & Setter Methods in Eloquent

As I mentioned before, Laravel offers this 2 methods to handle how information is displayed or changed before insert.

The rules are simple: you declare them by appending “set_”  or “get_” to the intended attribute’s name.

Setter example and usage

To format a date:

public function get_date_start()
{

   return date('M d, Y', $this->get_attribute('date_start')));

}

Now everytime you use $object->date_start, it will be formatted accordingly.

Getter example and usage

To encrypt a password before inserting in the database:

public function set_password($password) 
{ 
    $this->set_attribute('password', Hash::make($password)); 
}

How to organize base controllers

Situation: we have an application with multiple modules, each one needs a base controller that will handle common stuff for them, I prefer having a folder called “base_controllers” in application folder to keep it organized.

By default, Laravel’s base controller is in controllers folder(base.php) and it’s mapped in start.php with Autoloader::map().

To implement my way follow these 3 simple steps:

1. Delete base.php from controllers(if you don’t need it anymore)

2. Create base_controllers folder in /application/base_controllers and create the base controllers you need e.g. Base1.php and Base2.php:


Base1_Controller extends Controller {}
Base2_Controller extends Controller {}

3. To make it work(controllers to extend them) we have to ways:

3.1 In start.php with Autoloader::map() each one individually:


Autoloader::map(array(
     'Base1_Controller' => path('app').'base_controllers/Base1.php',
     'Base2_Controller' => path('app').'base_controllers/Base2.php',
));

3.2 In start.php with Autoloader::directories():


Autoloader::directories(array(
       path('app').'models',
       path('app').'libraries',
       path('app').'base_controllers',
));

Note: Laravel’s autoloader will search the directories using the PSR-0 naming convention.

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.

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