Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Left's avatar
Level 35

How to persist data using 3 different models in the same store method of single controller..

Hello guys!

I've got this problem where I have pretty large form to submit.

This single form holds the data witch belongs to three different tables in my database. Therefore I made 3 different Models for those tables to make use of Eloquent relationships.

To persist the data I need to use those 3 models all in the same store method in my controller I believe. I know I'm doing something wrong. This is already a very big block of code for a simple controller. I would like to simplify that a bit. Here is what I've got in my controller so far. Have a look.

  public function store(Request $request)
{

  $validated = $request->validate([
      'type_id' => 'required|digits_between:1,3',
      'imei_or_serial' => 'required|digits:15',
      'vendor' => 'required|alpha|max:20',
      'model' => 'required|string|max:20',
      'color' => 'required|string|max:20',
      'warranty_period' => 'required|string|max:20',
      'condition_id' => 'required',
      'accessories' => 'required|array',
      'warranty_period' => 'required|string|max:20',
      'purchase_dt' => 'required',
      'source_id' => 'required|digits_between:1,3',
      'purchase_price' => 'required|digits_between:2,4',
      'stock_price' => 'required|digits_between:2,4',
      'second_imei' => 'digits:15',
      'added_costs' => 'string|max:50',
      'comment' => 'string|max:255'
  ]);

  $device = Device::create([
    'type_id' => $validated['type_id'],
    'imei_or_serial' => $validated['imei_or_serial'],
    'second_imei' => isset($validated['second_imei']) ? $validated['second_imei'] : null,
    'vendor' => $validated['producent'],
    'model' => $validated['model'],
    'color' => $validated['color'],
    'accessories' => json_encode($validated['accessories'], JSON_UNESCAPED_UNICODE),
  ]);
  
  Purchase::create([
    'device_id' => $device->id,
    'shop_id' => Auth::user()->id,
    'source_id' => $validated['source_id'],
    'condition_id' => $validated['condition_id'],
    'purchase_dt' => Carbon::now(),
    'added_costs' => isset($validated['added_costs']) ? $validated['added_costs'] : 0,
    'purchase_price' => $validated['purchase_price'],
    'warranty_period' => $validated['warranty_period'],
    'comment' => isset($validated['comment']) ? $validated['comment'] : null
  ]);

  Depot::create([
    'device_id' => $device->id,
    'shop_id' => Auth::user()->id,
    'stock_price' => $validated['stock_price']
  ]);

  return redirect()->back();
}

I would be more then happy if you could give me some advice on that.

0 likes
4 replies
bobbybouwmann's avatar
Level 88

I think you have three options here

1: Extra the creation of the models to separated methods in the same controller class. You will still have everything in the controller, but the store method will be more readable 2: Move the creation of the models to the model itself. Create a method on the model that handles the creation. This way it's out of your controller and everything about it the creation lives in your model 3: Create a service class that handles the creation. You can move all this logic to a separated class that handles everything for you. This way you can reuse it on other places as well. You can then put everything in smaller methods

In general you can already clean up your code by moving the validation to a Request class. You can find more about that here: https://laravel.com/docs/5.8/validation#form-request-validation

1 like
aurawindsurfing's avatar

hey @left

Just a quick improvement would be to skip all values that you just copy from request and replace them with $request->all() then add all the exceptions you have for each of the fields. SOmething like that:

  $device = Device::create([array_merge(
  $request->all(),
  'second_imei' => isset($validated['second_imei']) ? $validated['second_imei'] : null,
  'accessories' => json_encode($validated['accessories'], JSON_UNESCAPED_UNICODE),
  )]);
1 like
Left's avatar
Level 35

Thank you very much for your suggestions. I think I will go with the second one. Seems pretty clean to me.

That Request class is also a life saver in that kind of situations. Pretty neat.

One more thing. From my experience is it better to make that new method static like the original store method is or just go with regular one?

Left's avatar
Level 35

Didn't know this is possible. Great to learn that. Thank you!

Please or to participate in this conversation.