Fixing the save() Model method in laravel

Here  we need to fix is the save() method. Actually, the save() method totally ignores the validation procedure, and this is no good. So, this is my final version of the AweloquentModel class:

<?php

namespace App\Aweloquent;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class AweloquentModel extends Model {

  protected static $rules = [];
  protected static $messages = [];

  public $errors;

  public function __construct(array $attributes = [])
  {
    $attributes = $this->autoHydrate($attributes);

    parent::__construct($attributes);
  }

  public function save(array $options = [])
  {
    if($this->validate())
    {
      $this->smartPasswordHashing();
      $this->purgeConfirmationFields();

      return parent::save($options);
    }
    else
      return false;
  }

  public function validate()
  {
    static::$rules = $this->mergeValidationRules();

    $validator = Validator::make($this->attributes, static::$rules, static::$messages);

    if($validator->fails())
    {
      $this->errors = $validator->messages();
      return false;
    }

    return true;
  }

  private function autoHydrate(array $attributes)
  {
    // getting the request instance using the service container
    $request = app('Illuminate\Http\Request');

    // getting the request form data, except the token
    $requestData = $request->except('_token');

    foreach($requestData as $name => $value)
    {
      // manually specified attribute has priority over auto- 
	  hydrated one.
      if(!isset($attributes[$name]))
        $attributes[$name] = $value;
    }

    return $attributes;
  }

  private function mergeValidationRules()
  {
    // if updating, use "update" rules, "create" otherwise.
    if($this->exists)
      $mergedRules = array_merge_recursive(static::$rules['everytime'], static::$rules

      ['update']);
    else
      $mergedRules = array_merge_recursive(static::$rules['everytime'], static::$rules

    ['create']);

    $finalRules = [];

    foreach($mergedRules as $field => $rules){
      if(is_array($rules))
        $finalRules[$field] = implode("|", $rules);
      else
        $finalRules[$field] = $rules;
    }

    return $finalRules;
  }

  private function smartPasswordHashing()
  {
    if($this->attributes['password'])
      $this->attributes['password'] = Hash::make($this- >attributes['password']);
  }

  private function purgeConfirmationFields()
  {
    foreach($this->attributes as $name => $value)
    {
      if(Str::endsWith($name, '_confirmation'))
        unset($this->attributes[$name]);
    }
  }
}

Let’s analyze the save() method in detail:

public function save(array $options = [])
{
  if($this->validate())
  {
    $this->smartPasswordHashing();
    $this->purgeConfirmationFields();

    return parent::save($options);
  }
  else
    return false;
}

The first thing to do is to validate the entire input. After that, if everything is fine, passwords are hashed and the confirmation fields are purged, as we don’t need them anymore.

Finally, the parent::save() method is called, and the operation is complete.

Note

In order to create a perfect continuity with the parent class, I declared the save() method with the same signature as its parent (including the $options array parameter).

That’s it! The AweloquentModel class is finished, and you can use it as you want in your projects.

Pin It on Pinterest

Shares

Get the best in web dev

Join dunebook.com and recieve best in web dev , once a week FREE

An email has been Sent to your Inbox ! Please Confirm your Subscription :)