lcf8381595's avatar

[L5] Validate Request Rules for both create and update?

for two form post methord store() , update() I want use the same one Validate Request Class to validate these two post form.

and my Validate Class is:

use Illuminate\Foundation\Http\FormRequest;
class StoreBlogPostRequest extends FormRequest  {
    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        return [
                'title' => 'required',
             'body' => 'required',
                'thumb'=> 'required',
                'published_at'=>'required|date'
        ];
    }
}

it is work well for store() method, it require above four fields. but for update() method, I want use the same validate class, but allow thumb field empty(not required), how can I do that?

0 likes
9 replies
JohnRivs's avatar

You want to use the StoreBlogPostRequest class for both store and update method, but you want 'thumb' to be not required?

You're gonna need 2 classes. Nothing wrong with StoreBlogPostRequest and UpdateBlogPostRequest.

You could probably set some code to check what method is calling the form request class, but it's gonna be ugly..

milon's avatar

Here is the solution I do for one of my project. I just copy-paste it.

<?php namespace ePOS\Validators;

use Laracasts\Validation\FormValidator;

class CompanyValidator extends FormValidator{
    protected $createRules = [
        'name'      => 'required',
        'email'     => 'required|email|unique:company',
        'phone'     => 'required',
        'address'   => '',
        'website'   => 'url'
    ];

    protected $updateRules = [
        'name'      => 'required',
        'email'     => 'required|email|unique:company',
        'phone'     => 'required',
        'address'   => '',
        'website'   => 'url'
    ];

    protected $rules = [];

    public function createValidate($data){
        $this->rules = $this->createRules;
        return $this->validate($data);
    }

    public function updateValidate($data, $id){
        $this->updateRules['email'] = "required|email|unique:company,email,$id";
        $this->rules = $this->updateRules;
        return $this->validate($data);
    }
}
JohnRivs's avatar

@milon I think he wants to use a form request, not just a Validator Service class.

milon's avatar

You can change form request class as I mentioned.

Jeffberry's avatar
Level 4

Well, if you think about it what is unique when updating a post that you don't have when creating the post? I would say the "post_id" is. You could try something like this:

use Illuminate\Foundation\Http\FormRequest;
class StoreBlogPostRequest extends FormRequest  {
    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        $rules = [
                'title' => 'required',
                'body' => 'required',
                'published_at'=>'required|date'
        ];

        if (!$this->has('post_id'))
        {
            $rules += ['thumb'=> 'required'];
        }

    return $rules;
    }
}

This is basically just saying if I don't have a post ID (meaning you are creating a post) then require a thumb. This is assuming your id column is "post_id". You can/should change "post_id" to whatever your column name is for your unique key.

nolros's avatar

You can also use some of the Laravel Validator validation methods. I think Jeff's is easier, but Chris Fidao has an interesting approach that I've used before:

use Illuminate\Foundation\Http\FormRequest;
class StoreBlogPostRequest extends FormRequest  {

    // We setup the sometime rule 
    protected $sometimes = array(
        array(
            'field'             => 'post_id',
            'rule'          => 'required',
            'callback'      => 'checkIfPostExists'
        ),
    );

    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        $rules = [
                'title' => 'required',
                'body' => 'required',
                'published_at'=>'required|date'
        ];

    return $rules;
    }

// method to check if it the post is set
 public function checkIfPostExists($input)
 {
     return isset($input->post_id);
}

// use validators passes and sometimes to assess
public function passes()
{
    $validator = $this->validator->make(
        $this->data,
        $this->rules,
        $this->messages
    );

    //This loop is all I added to the original method
    foreach ($this->sometimes as $sometime) {
        $validator->sometime(
            $sometime['field'],
            $sometime['rule'],
            function($input) use ($sometime)
            {
                return $this->$sometime['callback']($input);
            }
        );
    }

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

    return true;
}

}
bestmomo's avatar

Maybe an OO version :

abstract class BlogPostRequest extends FormRequest {
    public function authorize()
    {
        return true;
    }
    public function rules()
    {
        return [
                'title' => 'required',
                'body' => 'required',
                'published_at'=> 'required|date'
        ];
    }
}

class UpdateBlogPostRequest extends BlogPostRequest  {}

class StoreBlogPostRequest extends BlogPostRequest  {
    public function rules()
    {
        return array_merge(parent::rules(), ['thumb'=> 'required']);
    }
}
4 likes
bw1984's avatar

Late to the party here but i spent a while googling this issue and this was the best thread i found, despite it being over 9 years old. Anyway, heres the solution i went with, inspired by the solution by @jeffberry

public function rules(): array
    {
        $rules = [
            'name' => ['required', 'max:255'],
            'address' => ['required'],
            'postcode' => ['required', 'max:11'],
            'phone_number' => ['required', 'max:25'],
        ];

        // if updating existing record make all fields optional

        if($this->method() == 'PUT')
        {
            foreach($rules as $field => $ruleset)
            {
                $rules[$field][] = 'sometimes';
            }
        }

        return $rules;
    }

this checks to see if the method being used is 'PUT' and if so, adds the validation rule 'sometimes' to all rules. I couldnt reply on matching the URL or looking for the presence of a resource ID because i dont pass one to the update method.

Please or to participate in this conversation.