0

Is there a more elegant and shorter way to save bulk results to the database without using the foreach interaction. The method is already huge and I am trying to break it down into smaller units for easier maintenance.

    /**
     * Store a newly created resource in storage.
     */
    public function store(ProductPostRequest $request)
    {
        // Product main image
        if($request->hasFile('image'))
        {
            $image = $this->_uploadProductImage($request);
        }

        $data = [
            'name' => $request->input('name'),
            'model' => $request->input('model'),
            'code' => $request->input('code'),
            'slug' => $request->input('slug'),
            'image' => $image ?? '',
            'manufacturer_id' => $request->input('manufacturer_id'),
            'price' => $request->input('price'),
            'discount_price' => $request->input('discount_price'),
            'status' => $request->input('status'),
            'description' => $request->input('description'),
            'short_description' => $request->input('short_description'),
            'meta_title' => $request->input('meta_title'),
            'meta_description' => $request->input('meta_description'),
            'stock_status' => $request->input('stock_status'),
            'featured' => $request->input('featured')
        ];

        $product = Product::create($data);
        $product->categories()->attach($request->input('categories'));

        // Save product gallery images
        if($request->hasFile('gallery'))
        {
            $path = config('ecommerce.product_upload_dir').'/'.Str::slug($request->input('name'), '-');

            foreach ($request->file('gallery') as $item) {
                $product->gallery()->create([
                    'image' =>  $path.'/'.$item->getClientOriginalName(),
                ]);
            }
        }


        return redirect()->route('product.index')
            ->with('success', 'The product'. $product->name .' has been successfully created.');
    }

This part i want to make simpler

foreach ($request->file('gallery') as $item) {
   $product->gallery()->create([
        'image' =>  $path.'/'.$item->getClientOriginalName(),
    ]);
}

Does Laravel have a method that will do this?

Ivan
  • 5,139
  • 11
  • 53
  • 86
  • 1
    `createMany()`: https://laravel.com/docs/10.x/eloquent-relationships#the-create-method (scroll down a bit). Although you'd probably still have to use some kind of loop or array map to actually define the multiple `['image' => '...']` for use within that method... So that doesn't quite fit the requirement "without a `foreach`". IMO, I think your original is pretty simply/concise/clear. – Tim Lewis Jul 27 '23 at 17:46
  • Thank you, I did not notice this method. The problem is that my column structure in the database is a little different. The query is multiple image uploads `gallery[]` where I need to specify the column name `image`. Using this method I cannot achieve what I want. This is fine if all my fields have the same name as in the request – Ivan Jul 27 '23 at 17:55
  • 1
    You could, but you'd essentially have to do `$product->gallery()->createMany(collect($request->file('gallery', []))->map(function ($item) use ($path) { return ['image' => $path.'/'.$item->getClientOriginalName()]; }));` (untested, might need an extra `[]` around all of it). Or `array_map` if you don't want to use a `Collection`'s `map()` method, etc. – Tim Lewis Jul 27 '23 at 17:59
  • In any case, I get the same code length again. I will have to decide what to do with these two possibilities. Anyway, thanks, I learned something new – Ivan Jul 27 '23 at 18:02
  • 1
    Haha yup, it's only marginally better. And if you also have to handle the image upload (seeing as this is `$request->file(...)`), you might as well stick with the `foreach()` approach. But no problem; happy to provide some insight! – Tim Lewis Jul 27 '23 at 18:04
  • Sidenote, you can do `foreach ($request->file('gallery', [])` and remove the check `if($request->hasFile('gallery')) { ... }`; the 2nd parameter of `->file()` (and `->input()`) is a fallback if nothing is there, and an empty `foreach([])` will simply do nothing. – Tim Lewis Jul 27 '23 at 18:05

0 Answers0