1
votes

I'm using laravel 5.2 and i'm using Form Request that given by laravel vendor to make my code clean, so i don't have many code on my controller :

public function store( CouponRequest $request )
{
    DB::beginTransaction();
    try {
        $coupon = Coupon::create( $request->all() );

        DB::commit();
        return redirect()->route('admin.coupons.index');
    } catch (\Exception $e) {
        DB::rollback();
        return redirect()->back()->withInput();
    }

And this is my sample code about my request form :

public function rules()
{
    switch ( strtolower( $this->method ) ) {
        case 'post':
        {
            return [
                'code' => 'required|unique:coupons,code',
                'name' => 'required',
                'start_year' => 'required',
                'start_month' => 'required',
                'start_day' => 'required',
                'start_time' => 'required',
                'finish_year' => 'required',
                'finish_month' => 'required',
                'finish_day' => 'required',
                'finish_time' => 'required',
                'using_time' => 'required',
                'type' => 'required',
                'free_shipment' => 'required',
                'target' => 'required',
                'target_user' => 'required'
            ];
        }
        case 'put':
        {
            return [
                'code' => 'required',
                'name' => 'required',
                'start_year' => 'required',
                'start_month' => 'required',
                'start_day' => 'required',
                'start_time' => 'required',
                'finish_year' => 'required',
                'finish_month' => 'required',
                'finish_day' => 'required',
                'finish_time' => 'required',
                'using_time' => 'required',
                'type' => 'required',
                'free_shipment' => 'required',
                'target' => 'required',
                'target_user' => 'required'
            ];
        }
        default:
        {
            return [];
        }
    }
}

Where should i place this command? :

$start_date = Carbon::create( $request->start_year, $request->start_month, $request->start_day );
$start_date->setTimeFromTimeString( $request->start_time );
$finish_date = Carbon::create( $request->finish_year, $request->finish_month, $request->finish_day );
$finish_date->setTimeFromTimeString( $request->finish_time );

If i place this code before validation, i could be error when some field not filled well by users.

So what i want is to place this code after validation success, but i don't want to place it at my controller.

Is there FormRequest function that can be called after validation success to modify my request??

I think it's not good when there's much code at controller, so i want to minimalize my controller code.

1
you can use a middleware - dios231
the work flow will like this : middleware -> form request -> controller right? so if i place my code at middleware, it will not validate - Yudi Yohanes Septian Gotama
Don't do that. Middleware provide a mechanism for filtering HTTP requests entering your application. Not transforming http requests. You will end up with a confusing code base. You can write a service instead. That will also make your controller much more cleaner and SOLID. - Hilmi Erdem KEREN
Who is using the $start_date and $finish_date? Are you persisting it or using it? - Lionel Chan
@HilmiErdemKEREN has right, I probably misunderstood your question. You can create a service and inject it to controller. Service container will take care for the wirring - dios231

1 Answers

1
votes

I am going to attempt this using FormRequest. If the intention here is to both validate and assign start_date and finish_date, this is probably the plausible way of doing so in Laravel:

public function rules()
{
    switch ( strtolower( $this->method ) ) {
        case 'post':
        {
            return [
                'code' => 'required|unique:coupons,code',
                'name' => 'required',
                'start_year' => 'required',
                'start_month' => 'required',
                'start_day' => 'required',
                'start_time' => 'required',
                'finish_year' => 'required',
                'finish_month' => 'required',
                'finish_day' => 'required',
                'finish_time' => 'required',
                'using_time' => 'required',
                'type' => 'required',
                'free_shipment' => 'required',
                'target' => 'required',
                'target_user' => 'required'
            ];
        }
        case 'put':
        {
            return [
                'code' => 'required',
                'name' => 'required',
                'start_year' => 'required',
                'start_month' => 'required',
                'start_day' => 'required',
                'start_time' => 'required',
                'finish_year' => 'required',
                'finish_month' => 'required',
                'finish_day' => 'required',
                'finish_time' => 'required',
                'using_time' => 'required',
                'type' => 'required',
                'free_shipment' => 'required',
                'target' => 'required',
                'target_user' => 'required'
            ];
        }
        default:
        {
            return [];
        }
    }
}

/**
 * @inheritDoc
 *
 * This method overrides Laravel's defeault FormRequest
 * to create validator with `after()` hook
 */
protected function validator($validator)
{
    $validator
        ->make(
            $this->validationData(), $this->rules(), $this->messages(), $this->attributes()
        )
        ->after(function($validator) {

            if ($date = $this->getCarbonInstanceFromPrefix('start')) {
                $request->start_date = $date;
            } else {
                $validator->errors()
                    ->add('start_year', 'Invalid starting date and time');
            }

            if ($date = $this->getCarbonInstanceFromPrefix('finish')) {
                $request->finish_year = $date;
            } else {
                $validator->errors()
                    ->add('finish_year', 'Invalid finish date and time');
            }

        });
}

/**
 * Retrieve carbon instance from current request, using prefix
 *
 * @param  string $prefix
 *
 * @return Carbon|null
 */
protected function getCarbonInstanceFromPrefix($prefix = '')
{
    try {
        $date = Carbon::create( 
            $request->get($prefix . '_year'), 
            $request->get($prefix . '_month'), 
            $request->get($prefix . '_day') 
        );
        $date->setTimeFromTimeString( $request->get($prefix . '_time') );
        return $date;
    } catch (\Exception $e) {
        return null;
    }
}

Quick Explanation

FormRequest essentially extends from Illuminate\Foundation\Http\FormRequest and can override the method where instance of Validator is created. By creating your custom validator, you can attach after() event to both validate each date inputs, and also assign additional parameter to request in one go.