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
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.
Related
Hi i'm using a form to create a new product and send the info to the controller and save it into the database, the form does send the data because I can see it when I do a Log inside the controller and the info is there, I don't understand why it's not being saved into the database?
In this example the data I've added to the product is minimal but there could be more like prices and countries, along with the stuff inside the store function like tags and sizes.
This is the complete store function in the controller
public function store(ProductSaveRequest $request)
{
DB::beginTransaction();
$product = new Product;
$product->fill($request->all());
$file = $request->file('image');
if ($file) {
$file = $request->file('image');
$filename = Uuid::uuid() . '.' . $file->getClientOriginalExtension();
$file->move('img/products', $filename);
$product->image = 'img/products/' . $filename;
}
$product->save();
Log::info($product);
if (!empty($request->get('prices'))) {
$prices = array_map(function ($item) use ($product) {
$item['product_id'] = $product->id;
return $item;
}, $request->get('prices'));
CountryProduct::insert($prices);
}
if ($request->has('tags')) {
$product->tags()->sync($request->get('tags'));
}
if ($request->has('sizes')) {
$product->sizes()->sync($request->get('sizes'));
}
if ($request->has('categories')) {
$productCategories = [];
foreach ($request->get('categories') as $item) {
if (key_exists('category_name', $item)) {
$category = Category::where('name', $item['category_name'])
->first();
} else if (key_exists('category_id', $item)) {
$category = Category::findOrFail($item['category_id']);
}
if (empty($category)) {
$category = new Category;
$category->name = $item['category_name'];
}
$category->type = $item['type'];
$category->save();
if (!empty($item['fields'])) {
foreach ($item['fields'] as $fieldItem) {
if (key_exists('field_name', $fieldItem)) {
$field = Field::where('name', $fieldItem['field_name'])
->first();
} else if (key_exists('field_id', $fieldItem)) {
$field = Field::findOrFail($fieldItem['field_id']);
}
if (empty($field)) {
$field = new Field;
$field->name = $fieldItem['field_name'];
$field->category_id = $category->id;
}
$field->save();
$productCategories[] = [
"field_id" => $field->id,
"category_id" => $category->id,
"product_id" => $product->id,
"value" => $fieldItem['value']
];
}
}
if (count($productCategories) > 0) {
ProductField::insert($productCategories);
}
ExportationFactor::insert($product);
}
$product->save();
DB::commit();
return $product;
}
}
This is the Log.info
local.INFO: {"discount":"1","code":"123","sku":"123","description_spanish":"123","description_english":"123","brand_id":"2","id":591}
The current output is that I get a success action and it says it has been successfully added but when I go look it's not there.
Put your commit method outside the last if condition.
public function store(ProductSaveRequest $request)
{
DB::beginTransaction();
$product = new Product;
$product->fill($request->all());
$file = $request->file('image');
if ($file) {
$file = $request->file('image');
$filename = Uuid::uuid() . '.' . $file->getClientOriginalExtension();
$file->move('img/products', $filename);
$product->image = 'img/products/' . $filename;
}
$product->save();
Log::info($product);
if (!empty($request->get('prices'))) {
$prices = array_map(function ($item) use ($product) {
$item['product_id'] = $product->id;
return $item;
}, $request->get('prices'));
CountryProduct::insert($prices);
}
if ($request->has('tags')) {
$product->tags()->sync($request->get('tags'));
}
if ($request->has('sizes')) {
$product->sizes()->sync($request->get('sizes'));
}
if ($request->has('categories')) {
$productCategories = [];
foreach ($request->get('categories') as $item) {
if (key_exists('category_name', $item)) {
$category = Category::where('name', $item['category_name'])
->first();
} else if (key_exists('category_id', $item)) {
$category = Category::findOrFail($item['category_id']);
}
if (empty($category)) {
$category = new Category;
$category->name = $item['category_name'];
}
$category->type = $item['type'];
$category->save();
if (!empty($item['fields'])) {
foreach ($item['fields'] as $fieldItem) {
if (key_exists('field_name', $fieldItem)) {
$field = Field::where('name', $fieldItem['field_name'])
->first();
} else if (key_exists('field_id', $fieldItem)) {
$field = Field::findOrFail($fieldItem['field_id']);
}
if (empty($field)) {
$field = new Field;
$field->name = $fieldItem['field_name'];
$field->category_id = $category->id;
}
$field->save();
$productCategories[] = [
"field_id" => $field->id,
"category_id" => $category->id,
"product_id" => $product->id,
"value" => $fieldItem['value']
];
}
}
if (count($productCategories) > 0) {
ProductField::insert($productCategories);
}
ExportationFactor::insert($product);
}
}
DB::commit();
return $product;
}
In the first line of the method, you begin a database transaction.
But you only commit the database transaction
if ($request->has('categories')) {
I want to save the same data with 365 records within one table. I'm new to Laravel.
I've tried with replicate() but was unsuccessful. I tried this on the Apache server and used Laravel5.7.
my controller
public function price_save(Request $request) {
$price=new Price();
$price->price=$request->price;
$price->extra_bed=$request->extra_bed;
$price->room_id=$request->room;
$id=$request->room;
$price = Price::find($id);
if(null !== $price){
$new = $price->replicate();
if(null !== $new){
$new->push();
// $price->save();
}
I am NOT sure about your code, But you can customize it as per your needs, To just get idea :
$model = User::find($id);
$model->load('invoices');
$newModel = $model->replicate();
$newModel->push();
foreach($model->getRelations() as $relation => $items){
foreach($items as $item){
unset($item->id);
$newModel->{$relation}()->create($item->toArray());
}
}
Credits
public function price_save(Request $request, int $id)
{
if ($id > 365) {
return;
}
$price = new Price();
$price->price = $request->price;
$price->extra_bed = $request->extra_bed;
$price->room_id = $request->room;
$price->save();
$existing = Price::find($request->room);
if ($existing) {
$request = $request->replace([
'price' => $price->price,
'extra_bed' => $price->extra_bed,
'room_id' => $price->room,
]);
}
return price_save($request, $id++);
}
From the model TagModel i can filter the value which i want it, but value is stored in the form of object variable. To play with those data in controller i am not able to pluck the particular id.
This is my model
public static function getLatestTag($name){
return $tagIds =DB::table('tags')
->where ('is_deleted',0)
->where('name',$name)
->get();
}
This is my controller code:
foreach ($newTags as $newTag) {
$productTagIds[] = TagModel::getLatestTag($newTag);
dd($id);
}
$productId = (int)ProductManagementModel::getMaxId();
foreach ($productTagIds as $productTagId) {
$productTag = new ProductTagModel;
$productTag ->product_id = $productId;
$productTag ->tag_id = $productTagId;
$productTag->save();
}
the value which i want is stored in the variable $productTagIds which is object variable. How can I pluck just id from this?
public function addProduct()
{
foreach(Input::get('tagName') as $checkTag){
$newTags[]=$checkTag;
}
foreach ($newTags as $newTag) {
if(TagModel::checkExist($newTag)){
$tagExist[] = TagModel::checkExist($newTag);
$message = 'The tag <b>'.$checkTag.'</b> already exist';
Session::flash('class', 'alert alert-error');
Session::flash('message', $message);
return View::make('admin.product_management.add');
}
else {
$objectTagProduct = new TagModel;
$objectTagProduct ->name = $newTag;
$objectTagProduct->save();
$productTagIds[]=$objectTagProduct->id;
}
}
$objectProduct = new ProductManagementModel;
$objectProduct->product_name = Input::get('product_name');
$objectProduct->product_url = $productUrl;
$objectProduct->category_id = Input::get('category_id');
$objectProduct->product_cost = Input::get('product_cost');
$objectProduct->product_short_description = Input::get('product_short_description');
$objectProduct->product_description = Input::get('product_description');
$objectProduct->is_active = Input::get('is_active');
$objectProduct->created_at = Auth::user()->id;
$objectProduct->updated_at = Auth::user()->id;
if($logo != '')
{
$objectProduct->product_attachment = $logo;
}
$objectProduct->save();
$productId = (int)ProductManagementModel::getMaxId();
//dd($productId);
foreach ($productTagIds as $productTagId) {
//dd($productTagIds);
$productTag = new ProductTagModel;
$productTag ->product_id = $productId;
$productTag ->tag_id = $productTagId;
$productTag->save();
}
if($objectProduct->id) {
Session::flash('class', 'alert alert-success');
Session::flash('message', 'Product successfully added');
return View::make('admin.product_management.add');
} else {
Session::flash('class', 'alert alert-error');
Session::flash('message', 'Something error');
return View::make('admin.product_management.add');
}
}
The code might flash a certain error that have to troubleshoot by yourself. I have kept
$productTagIds[]=$objectTagProduct->id;
after $objectTagProduct->save(); please try it
public static function getLatestTag($name){
return $tagIds = DB::table('tags')
->where ('is_deleted',0)
->where('name',$name)
->pluck(id);
}
public static function getLatestTag($name){
return App\TagModel::where('is_deleted',0)->where('name',$name)->first()->id;
}
$ids = [];
foreach ($newTags as $newTag) {
$productTagId = TagModel::getLatestTag($newTag);
array_push($ids,$productTagId);
}
$productId = (int)ProductManagementModel::getMaxId();
foreach ($ids as $productTagId) {
$productTag = new ProductTagModel;
$productTag ->product_id = $productId;
$productTag ->tag_id = $productTagId;
$productTag->save();
}
try to use eloquent like this
to get the particular value from the object class variable
$productTagIds[]=$objectTagProduct->id;`
public function addProduct()
{
foreach(Input::get('tagName') as $checkTag){
$newTags[]=$checkTag;
}
foreach ($newTags as $newTag) {
if(TagModel::checkExist($newTag)){
$tagExist[] = TagModel::checkExist($newTag);
$message = 'The tag <b>'.$checkTag.'</b> already exist';
Session::flash('class', 'alert alert-error');
Session::flash('message', $message);
return View::make('admin.product_management.add');
}
else {
$objectTagProduct = new TagModel;
$objectTagProduct ->name = $newTag;
$objectTagProduct->save();
}
}
$objectProduct = new ProductManagementModel;
$objectProduct->product_name = Input::get('product_name');
$objectProduct->product_url = $productUrl;
$objectProduct->category_id = Input::get('category_id');
$objectProduct->product_cost = Input::get('product_cost');
$objectProduct->product_short_description = Input::get('product_short_description');
$objectProduct->product_description = Input::get('product_description');
$objectProduct->is_active = Input::get('is_active');
$objectProduct->created_at = Auth::user()->id;
$objectProduct->updated_at = Auth::user()->id;
if($logo != '')
{
$objectProduct->product_attachment = $logo;
}
$objectProduct->save();
$productId = (int)ProductManagementModel::getMaxId();
//dd($productId);
foreach ($productTagIds as $productTagId) {
//dd($productTagIds);
$productTag = new ProductTagModel;
$productTag ->product_id = $productId;
$productTag ->tag_id = $productTagId;
$productTagIds[]=$objectTagProduct->id;
$productTag->save();
}
if($objectProduct->id) {
Session::flash('class', 'alert alert-success');
Session::flash('message', 'Product successfully added');
return View::make('admin.product_management.add');
} else {
Session::flash('class', 'alert alert-error');
Session::flash('message', 'Something error');
return View::make('admin.product_management.add');
}
}
I came to knew that to get the data from object class variable $productTagIds[]=$objectTagProduct->id;
But i am confused with its flow and where to execute this code.
I want to minimize this by removing if else statement using simple code in laravel 5.5 can someone help me with it?
public function shirts($type='')
{
if($type == 'glass') {
$shirt = Product::where('category_id','1')->get();
$products = Category::find(1);
} elseif ($type == 'ic') {
$shirt = Product::where('category_id','2')->get();
$products = Category::find(2);
} elseif ($type == 'cover') {
$shirt = Product::where('category_id','3')->get();
$products = Category::findOrFail(3);
} else {
$shirt = Product::all();
}
return view('front.shirt',compact('products','shirt'));
}
One way would be to create a mappings for your type and comparing the type with the mappings.
public function shirts($type = '')
{
$type_mappings = [
'glass' => 1,
'ic' => 2,
'cover' => 3
];
if(array_key_exists($type, $type_mappings)) {
$shirt = Product::where('category_id', $type_mappings[$type])->get();
$products = Category::find($type_mappings[$type]);
} else {
$shirt = Product::all();
$products = null;
}
return view('front.shirt', compact('products', 'shirt'));
}
Edit : i assumed you want to avoid if else not as what the title of question says if still i am unclear please add comment so i can update the answer Thanks!
Lets handle it somewhere else as i guess your function only has the responsibility to find product based on id it get not mapping part so we can have something like :
// Your function with single responsibility to return product.
public function shirts($category = '')
{
$type = $this->CategoryIdMapper($category);
if($type == 0) {
$shirt = Product::all();
$products = null;
} else{
$shirt = Product::where('category_id',$type_id)->get();
$products = Category::findOrFail($type_id);
}
return view('front.shirt',compact('products','shirt'));
}
//let the mapping part be done by some independent function which you can later modify accordingly and independently.
public function CategoryIdMapper($category)
{
$categories = ['glass'=>1, 'ic'=> 2, 'cover' => 3 ];
if(array_key_exist($category,$categories))
{
return $categories[$category];
}
return 0;
}
I have some sample code within a controller method that looks up a cookie and manipulates the model if it exists, or creates a new model and returns a new cookie if it doesn't.
Is it possible to add the cookie before I return the view such that the duplicated code can be written only once?
I'm just looking for efficiency and tidiness.
$cat = Cat::find($request->cookie('cat_id'));
if (null !== $cat) {
if ($cat->name === 'Felix') {
$cat->age = 10;
} else {
$cat->age = 8;
}
//duplicated code
$cat->fur = 'soft';
$cat->tail = 'wavy';
$cat->save();
return redirect('/');
} else {
$cat = new Cat;
$cat->name = 'Ralf';
$cat->age = 12;
//duplicated code
$cat->fur = 'soft';
$cat->tail = 'wavy';
$cat->save();
return redirect('/')->withCookie(cookie('cat_id', $cat->id,10000));
}
The redirect() method returns a Illuminate\Http\RedirectResponse when a string is passed to it, which the Laravel routing stack interprets as a direction to send out a particular response header. So instead of returning twice, you can just do this:
$cat = Cat::find($request->cookie('cat_id'));
$redirect = redirect('/');
if (null !== $cat) {
if ($cat->name === 'Felix') {
$cat->age = 10;
} else {
$cat->age = 8;
}
//duplicated code
$cat->fur = 'soft';
$cat->tail = 'wavy';
$cat->save();
} else {
$cat = new Cat;
$cat->name = 'Ralf';
$cat->age = 12;
//duplicated code
$cat->fur = 'soft';
$cat->tail = 'wavy';
$cat->save();
$redirect->withCookie(cookie('cat_id', $cat->id,10000));
}
return $redirect;