Laravel - Eloquent sync() insertting same value to every row - laravel

So I just learned how to utilize nested iterations to load data from a pivot table. Now I am trying to save the data but I am not able to .
I have a 'new' blade which the customer can create a new 'Order' with many 'products'.
The blade basically just iterates through all available Products. (As far as I can tell, this is how the blade needs to be setup)
new.blade.php
{!! Form::open(['url' => '/orders/store']) !!}
#foreach ($products as $product)
<h1>{{ $product->name }}</h1>
<p>{{ $product->description }}</p>
{{ Form::text('qty', null }}
#endforeach
So this is my attempt at utilizing a nested iteration in order to pass the 'qty' data to the pivot table.
OrderController.php
public function store(Request $request)
{
$user = Auth::user();
$user->load("orders.products"); //eager load pivot table
/*NEW ORDER*/
$order = new Order;
$order->user_id = Auth::user()->id;
$order->save();
$product_id_array = [];
/*PIVOT*/
$products_to_sync_ids = [ 1,2,3,4,5,6,7,8,9 ];
$sync_data = [];
for ($i = 0; $i < count($products_to_sync_ids); $i++) {
$qty = $request->input('qty');
$sync_data[$products_to_sync_ids[$i]] = ['qty' => $qty];
}
$order->products()->sync($sync_data);
The 'Order' saves, but the qty always defaults to the last Products inputted qty.

You are defining text input with same name 'qty' multiple times that's why when you submit the form, it will give you the value of last text field with name 'qty'.
In this case you should define the qty field as an array of like:
{{ Form::text('qty[]', null }}
And while fetching its value you need to iterate it:
$qty = $request->input('qty');
for ($i = 0; $i < count($products_to_sync_ids); $i++) {
$sync_data[$products_to_sync_ids[$i]] = ['qty' => $qty[$i]];
}
This may help you to achieve what you want.

Related

Trying to get property 'name' of non-object

In code Controller recieving data from model but failed to show in blade view file.
This is blade view code.
#for($id = 0;$id < 59;$id++)
#foreach($data[$id] as $data)
{{$data->name}}
#endforeach
#endfor
Here is the controller
public function cart(){
$data = array();
$data['flashSale'] = Product::flashSale();
$cartProdId = Session::get('prodId');
for ($id = 0;$id<sizeof($cartProdId);$id++){
$data[$id] = Product::getCartProduct($cartProdId[$id]);
}
return view('user.cart')->with('data',$data);
}
you are using two loops unnecessarily..you can achieve this by using only one loop if it is for or foreach loop...
You can do it by single foreach loop. It will save execution/loading time.
#foreach($data as $key => $value)
{{$value->name}}
#endforeach
Do smart work!! .

Laravel 5.7 - Pivot table attach()

I cannot get attach() to work in my setup.
Each User can have many Orders which can have many Products.
User.php
public function orders()
{
return $this->hasMany(Order::class);
}
Order.php
public function users()
{
return $this->belongsTo(User::class);
}
public function products()
{
return $this->belongsToMany(Product::class)
->withTimestamps()
->withPivot('qty');
}
Product.php
public function orders()
{
return $this->belongsToMany(Order::class)
->withTimestamps()
->withPivot('qty');
}
I have a create.blade.php which is meant to show all available products and the quantity for each can be chosen, this is to be saved on the pivot table.
create.blade.php
{{ Form::open(array('url' => '/orders/store')) }}
#foreach ($products as $product)
<div>
<span class="mealname">{{ $product->name }}</span>
<hr>
<p>{{ $product->description }}</p>
</div>
<div class="qty">
{{ Form::text( 'qty', 0, [ 'type' => 'tel' ]) }}
</div>
#endforeach
{{ Form::select('delivery_day', ['M' => 'Monday', 'W' => 'Wednesday'],
null, ['placeholder' => 'Delivery Day'])
}}
{{ Form::submit('Place Order') }}
{{ Form::close() }}
When I submit the request only the fields to the Order table are saved,
public function store(Request $request)
{
// Validate
$request->validate([
'qty'=> 'integer',
]);
# Create New Order
$order = new Order;
$id = Auth::user()->id;
$order->user_id = $id;
// passed in parameters of form (not qty)
auth()->user()->orders()->save($order); // save order
# Pivot attach()
HERE I AM LOST
return redirect('complete')->with('success', 'Order has been created');
}
I believe it is the fact that I am trying to pass multiple products in one form, (which I believe i should be able to just pass as an arry while I use attach().
I have tried various solutions and I am still unable to ever get the pivot table to populate.
My last attempt was to pass the product_id through a hidden field and then running this.
$attach_data = [];
for ($i = 0; $i < count($product_ids); $i++);
$attach_data[$product_ids[$i]] = ['qty' => $qtys[$i]];
$order->product_ids()->attach($attach_data);
However, this did not work.
According to the docs (https://laravel.com/docs/5.7/eloquent-relationships#updating-many-to-many-relationships) this is one way to attach multiple items:
$user->roles()->attach([
1 => ['expires' => $expires],
2 => ['expires' => $expires]
]);
So you have to modify this:
# Create New Order
$order = new Order;
$id = Auth::user()->id;
$order->user_id = $id;
$order->save();
// change this for your array of ids
$products_to_sync_ids = [1,3,23];
$sync_data = [];
$qty = 1; <----- I dont know if you are inserting them with the same qty
for($i = 0; $i < count($products_to_sync_ids); $i++))
$sync_data[$products_to_sync_ids[$i]] = ['qty' => $qty];
$order->products()->sync($sync_data);
Try and check if the products are inserting correctly on the pivot table and then modify the code to insert every code with his quantity.

How to convert MySqli Loop Code Laravel controller

I want to work on a while loop in a foreach loop but I can't convert it to Laravel controller system. Please help.
foreach (range('a', 'z') as $i)
{
echo $i = strtolower($i);
$sql = "SELECT * FROM `list` Where name like '$i%' Limit 30";
$result = mysqli_query($con, $sql);
echo"<hr><h3>Name Starting with ".strtoupper($i)."</h3>";
while($row=mysqli_fetch_array($result,MYSQLI_ASSOC))
{
$id = $row['id'];
$name = $row['name'];
echo "<li>".$row['name']."</li>";
}
echo "<li>More</li>";
echo "</ul>";
}
The code in Laravel that I have is
foreach (range('a', 'z') as $i)
{
$list = DB::table('list')->where('name', 'LIKE', $i.'%')->limit(30)->get();
return view('pages.all', ['list' => $list]);
}
This code only gives data for names starting with alphabet "a" but won't proceed with the rest of the characters.
Store it on the array based on your search.
$list = array();
foreach (range('a', 'z') as $i) {
$list[$i] = DB::table('list')->where('name', 'LIKE', $i.'%')->limit(30)->get();
}
return view('pages.all', ['list' => $list]);
Customize your view, to showing the list against each character (a-z).
[Edit]
View file can be changed like below,
#foreach ($list as $keyI => $moredata)
<hr>
<h3>Author's Name Starting with "{{strtoupper($keyI)}}"</h3>
<ul class="tags-list">
#foreach ($moredata as $data)
<li>{{$data->name}}</li>
#endforeach
</ul>
#endforeach

Passing variables,arrays and objects to view with compact

I have a method in laravel that aims to pass data to views. I have data in variables, arrays and objects.
This is the method
public function view($id){
$id = request()->segment(2);
$items = Role::all(['name', 'display_name']);
return view('text.ServicesEditUser',compact('items',$items));
}
I also have this code
$uid = Auth::id();
$settings = Settings::where('user_id','=',Auth::id())->first();
return view('text.settings',compact('settings'));
that i want to incorporate to the code above. Once i pass the settings to the view, i can access data like $settings->language for instance. I also want to pass a variable which is
$title = 'degrees of tilt';
to the first code snippet's compact method.
This is the method now with all the data i want to pass to the view
public function view($id){
$id = request()->segment(2);
$title = 'Tilt in degrees';
$settings = Settings::where('user_id','=',Auth::id())->first();
$users = User::where('id','=',$id)->get();
$items = Role::all(['name', 'display_name']);
return view('text.ServicesEditUser',compact('items',$items));
}
How do i pass $settings ,$title,$users , $items to the view and how do i access each in view?
When returning a view you can pass multiple variables like this.
return view('text.ServicesEditUser')
->with(compact('items',$items))
->with('variable2', $variable2);
See here the documentation about this - Laravel Views.
In controller:
$variable = "Var";
$array = ["first" => "a", "second" => "b"];
$object = (object) $array;
return view('view',compact(['variable', 'array', 'object']));
In view:
{{$variable}}
{{$array['first']}}
{{$object->first}}
compact() doesn't need dollar at start.
You can just add your code to view by:
$title = 'My title';
$settings = ['my', 'settings',];
return view('text.settings', compact('title', 'settings'));
Anyway you can pass your variables by array:
$settings = ['my', 'settings',];
return view('text.settings', [
'title' => 'Title',
'settings' => $settings,
]);
The last option is with() method:
return view('text.settings')
->with('settings', $settings)
->with('title', 'My title');
Get access to variables in the view by {{ $title }} and
#foreach ($settings as $sett)
{{ $sett }}
#endforeach
This did also work
public function view($id){
$id = request()->segment(2);
$title = 'Degrees of tilt';
$settings = Settings::where('user_id','=',Auth::id())->first();
$users = User::where('id','=',$id)->get();
$items = Role::all(['name', 'display_name']);
return view('text.ServicesEditUser', compact('title', 'settings','users','items'));
}
in the blade view
<p>{{$title}}</p>
{{$settings->language}}
#foreach($items as $item)
<option value="{{$item->name}}">{{$item->display_name}}</option>
#endforeach
#foreach($users as $user)
<option value="{{$user->id}}">{{$user->email}}</option>
#endforeach
In settings
#if($settings)
$settings->language
#endif

How to optimize code in Laravel?

I use the following code to get data from two related tables:
$arr = [];
$objectModel = new ProductCategory();
$objectModel::$language = 2;
$subcategories = $objectModel::with("translate", "parent")->get();
foreach($subcategories as $key => $item) {
$arr[$item->translate()->first()->objectId] = $item->translate()->first()->name;
}
array_unshift($arr, 'Select category');
return $arr;
In result this part of code I get array with key => value to insert this in select list in Blade template.
But I desire to escape a loop:
foreach($subcategories as $key => $item) {
$arr[$item->translate()->first()->objectId] = $item->translate()->first()->name;
}
And get clear collection from request. How can I do it?
You can use Laravel Collections https://laravel.com/docs/5.3/collections
$arr = ProductCategory::with("translate", "parent")->get()
->mapWithKeys(function ($item, $key) {
return [$item->translate()->first()->objectId => $item->translate()->first()->name];
})
->all();

Resources