skip to Main Content

I have an order detail that includes multiple product listings. I want to ensure that users cannot select the same product for a single order. For example, here is the result of the dd($request) function.

+request: SymfonyComponentHttpFoundationInputBag {#45
#parameters: array:16 [
  "_token" => "El3iq45CsoEPRXxwaAOv072O0bWARb5WUNx3Lmfe"
  "warehouse_id" => "1"
  "customer_id" => "1"
  "order_date" => "2023-08-24 19:20"
  "shipping_address" => "q"
  "product_id0" => "1"
  "qty0" => "1"
  "stock_outstanding0" => "99"
  "unit_price0" => "65000"
  "total_price0" => "65000"
  "count_item" => "1"
  "product_id1" => "1"
  "qty1" => "1"
  "stock_outstanding1" => "100"
  "unit_price1" => "65000"
  "total_price1" => "65000"
]
}

As you can see, there are two product IDs, product_id0 and product_id1, that have the same value.

"product_id0" => "1"
"product_id1" => "1"

I want a validator to check if it has the same value, it will abort the order. I have implemented validation, but it still seems to be incorrect. This is because if product_id0 and product_id1 have different values, such as

"product_id0" => "1"
"product_id1" => "2"

It keep send the message Validation Work

Here the validation i made

$isValid = true;

    for ($g = 0; $g <= $request->count_item; $g++) {
        $validator = Validator::make($request->all(), [
            'warehouse_id' => 'required',
            'customer_id' => 'required',
            'order_date' => 'required',
            'shipping_address' => 'required',
            "product_id{$g}.*" => 'distinct',
        ]);

        if ($validator->fails()) {
            $isValid = false;
            break;
        }
    }

    if ($isValid) {
        return response()->json([
            'status' => true,
            'message' => 'Validation Work',
        ]);
    } else {
        return response()->json([
            'status' => false,
            'message' => 'Validation Failed',
        ]);
    }

Also i made another validation but still dont work

$tempId = [];
    $tempArray = [];

    for ($g=0; $g <= $request->count_item; $g++) { 
        $tempId[] = $request['product_id' . $g];

        if(in_array($tempId, $tempArray)){
            return response()->json([
                'status' => true,
                'message' => 'True validation work',
            ]);
        }else{
            return response()->json([
                'status' => false,
                'message' => 'False validation failed',
            ]);
            $tempArray[] = $tempId;
            dd($tempArray);
            exit;
        }
    }

2

Answers


  1. You’re validating each product at a time, so it won’t be able to match it against the others. Instead, build up the validation array before you actually validate it. product_id{$g} is a single item, so don’t use .*, since that’s used for arrays.

    $rules = [
        'warehouse_id' => 'required',
        'customer_id' => 'required',
        'order_date' => 'required',
        'shipping_address' => 'required',
    ];
    for ($g = 0; $g <= $request->count_item; $g++) {
        $rules["product_id{$g}"] = 'distinct';
    }
    $validator = Validator::make($request->all(), $rules );
    
    if ($validator->fails()) {
        $isValid = false;
    }
    

    You could also turn your products in your form to be an array with products[], then use 'products.*'=> 'distinct' instead of building up the rules based on the item count.

    Login or Signup to reply.
  2. The distinct rule only works on arrays of values. You’re not using an array, as you’ve put each value in it’s own variable (product_id0 vs product_id[0]).

    I would suggest changing your request to use an array so you can take advantage of the distinct rule.

    Change the name on your input to product[0][id] and product[1][id], and then your validation rule would be product.*.id => 'distinct'. Also, you’d have a valid array of products to loop through, instead of having to dynamically build variable names.


    If you can’t modify the request coming in, you could build up a new array to validate on the server side. However, if you do this, the error bag keys won’t match the inputs on the screen, so you’d need to account for that if you’re trying to show error messages for the fields on the screen.

    // Build your new data array.
    $data = $request->all();
    for ($g = 0; $g <= $request->count_item; $g++) {
        $data['product'][$g]['id'] = $data["product_id{$g}"];
    }
    
    // Now validate the data array.
    $validator = Validator::make($data, [
        'warehouse_id' => 'required',
        'customer_id' => 'required',
        'order_date' => 'required',
        'shipping_address' => 'required',
        'product.*.id' => 'distinct',
    ]);
    

    Finally, if neither of these is a valid option, you can use the different validation. This will be a little trickier if you can have a dynamic amount of products. The different validation lets you specify that one field must be different than another, so you’d need to specify that p0 is different than p1, p2, …, pN, and then p1 is different than p2, p3, …, pN, etc.

    $rules = [
        'warehouse_id' => 'required',
        'customer_id' => 'required',
        'order_date' => 'required',
        'shipping_address' => 'required',
    ];
    // Outer loop goes from 0 -> N-1
    for ($g = 0; $g < $request->count_item; $g++) {
        // Inner loop goes from Outer+1 to N
        for ($h = $g + 1; $h <= $request->count_item; $h++) {
            $rules["product_id{$g}"] = "different:product_id{$h}";
        }
    }
    
    $validator = Validator::make($request->all(), $rules);
    

    NB: all untested code. May contain syntax/logic errors.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search