0

The Problem

I'm working on Invoice Lines. When the line type is 'Text Only' the price and quantity fields should be blank.

When the line type is 'Item' the price and quantity fields are required.

What Laravel already does:

The required_if function works perfectly for saying "OK it's an item line, require the quantity and price.

What I need:

A function which works similarly but expects the field to be empty, preventing users from putting prices and quantities against text-only lines.

How I am using the rules:

class StoreInvoiceRequestDetail extends FormRequest
{
   public function rules()
    {
        return [
            'type_id'               => 'required|integer|exists:invoice_request_detail_types,id',
            'item_price'            => [
                'nullable',
                'numeric',
                'empty_if:type_id,'.InvoiceRequestDetailType::TEXT_ONLY.',Line Type,Text Only',
                'required_if:type_id,'.InvoiceRequestDetailType::ITEM.'Line Type,Item',
            ],
            'item_quantity'         => [
                'nullable',
                'numeric',
                'empty_if:type_id,'.InvoiceRequestDetailType::TEXT_ONLY.',Line Type,Text Only',
                'required_if:type_id,'.InvoiceRequestDetailType::ITEM.',Line Type,Item',
            ],
            'description'           => 'required|string|min:3|max:'.ApplicationConstant::STRING_LONG,
            'invoice_request_id'    => 'required|integer|exists:invoice_requests,id',
        ];
    }
}
Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36

1 Answers1

0

This works:

Usage

    'item_price' => 'empty_if:type_id,1,Line Type,Text Only',

Extenders

        Validator::extend('empty_if', function ($attribute, $value, $parameters, $validator)
        {
            $other = $parameters[0];
            $otherValue = $parameters[1];
            return !(Input::get($other) == $otherValue &&! empty($attribute));
        });

        Validator::replacer('empty_if', function ($message, $attribute, $rule, $parameters) {
            $other = isset($parameters[2]) ? $parameters[2] : $parameters[0];
            $value = isset($parameters[3]) ? $parameters[3] : $parameters[1];
            return str_replace([':other', ':value'], [ $other, $value ], $message);
        });

Validator Lang

 'empty_if'             => 'The :attribute must be empty when :other is ":value"',

I've added field name and value alias options in the replacers for ease of use, however technically I should have probably just called my field invoice_request_line_type_id instead of just type_id. The values lang isn't really going to work for me in this instance which is a trap, because it won't get translated, but you could insert those values from Lang into the validator anyway.

Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36