1

I'm trying to create a function that will replicate/clone/duplicate a product including all it's properties and it's shipping options.

However, I succeeded to duplicate the product but the shipping options are not replicated. See my codes below;

Any help will be highly appreciated

Thanks

public function CreateProductPost(Request $request){
  if (Auth::user()->vendor == false) {
    return redirect()->route('profile');
  }
  if ($request->name == null) {
    session()->flash('errormessage','Product name is required');
    return redirect()->back()->withInput();
  }
  if (mb_strlen($request->name) > 60) {
    session()->flash('errormessage','Product name cannot be longer than 60 characters.');
    return redirect()->back()->withInput();
  }
  if ($request->category_id == null) {
    session()->flash('errormessage','Product category is required');
      $shippingoptions[] = $opt;
    }
  }
  $product = new Product;
  $product->name = $request->name;
  $product->uniqueid = random_int(10000, 99999);
  $product->category_id = $category->id;
  $product->description = $request->description;
  $product->refund_policy = $request->refund_policy;
  $product->fromc = $request->fromc;
  $product->tocount = $request->tocount;
  $product->price = $request->price;
  $product->currency = $request->currency;
  $product->inventory = $request->inventory;
  if ($request->image !== null) {
    $product->image = $request->image->store('uploads','public');
  }
  $product->buyout = 0;
  $product->fe = $fe;
  $product->seller_id = Auth::user()->id;
  $product->save();
  foreach ($shippingoptions as $opt) {
    $so = new ShippingOption();
    $so->product_id = $product->id;
    $so->desc = $opt['desc'];
    $so->days = $opt['days'];
    $so->price = $opt['price'];
    $so->save();
  }
  session()->flash('successmessage','Product successfully        created');
  return redirect()->route('products');
}
function DuplicateProductPost($uniqueid, Request $request){
      $product = Product::where('uniqueid',$uniqueid)->first();
      if ($product == null) {
        return redirect()->route('products');
      }
      if (Auth::user()->id !== $product->seller->id) {
        return redirect()->route('products');
      }
      $newProduct = $product->replicate();
      $newProduct->uniqueid = random_int(10000, 99999);
      $newProduct->save();
      session()->flash('successmessage','Product successfully duplicated');
      return redirect()->route('products');
    }

Any help will be highly appreciated

Thanks

Sammy
  • 45
  • 7
  • Maybe this'll help you: https://stackoverflow.com/questions/23895126/clone-an-eloquent-object-including-all-relationships – Sindhara Mar 26 '19 at 19:32
  • I feel sorry for the poor guy, that has to fill that form out, get one error message, fill out some more, get 1 more error message, etc. After about 3 rounds of that, I'm done with a site... just saying. It's more efficient (both code wise and for your users) to find all the errors and show them in one go. – ArtisticPhoenix Mar 26 '19 at 19:35
  • Use proper validation... You can validate every one of your inputs in a single check, and return all relevant errors in a single call, instead of returning the first error over and over again until they get it right. See https://laravel.com/docs/5.8/validation for full details. – Tim Lewis Mar 26 '19 at 19:38

1 Answers1

0

You need to replicate both your Product and ShippingOption models, so use the following logic:

$product = Product::where('uniqueid',$uniqueid)->first();
...
$newProduct = $product->replicate();
$newProduct->uniqueid = random_int(10000, 99999);
$newProduct->save();

foreach($product->shippingOptions AS $shippingOption){
  $newShippingOption = $shippingOption->replicate();
  $newShippingOption->product_id = $newProduct->id;
  $newShippingOption->save();
}

Note, you need to have a relationship between Product and ShippingOption, otherwise you will need to manually query for them:

$oldShippingOptions = ShippingOption::where("product_id", "=", $product->id)->get();
foreach($oldShippingOptions AS $shippingOption){
  ...
}

The ->replicate() method does not clone all related records, as that might not be the intended requirement, so you need to do it manually.

Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
  • This is a magical solution. Thanks very much. By the way, how do I implement this one? `$oldShippingOptions = ShippingOption::where("product_id", "=", $product->id)->get(); foreach($oldShippingOptions AS $shippingOption){ ... }` – Sammy Mar 26 '19 at 20:03
  • Same logic as the `foreach` above. Logically, `$product->shippingOptions` and `$oldShippingOptions` would contain the same `Collection` of `ShippingOption` models. – Tim Lewis Mar 26 '19 at 20:12