How to get all data except last query? - laravel

I have this foreach I need to get all data except last one that I current add it
my foreach :
#foreach ($user->projects->sortByDesc('id')->except() as $porject)
// my data
#endforeach
projects is relation between user and projects table

You can use pop() collection method that removes the last item. I would do it in the controller and share the projects with the view.
$projects = $user->projects()->orderBy('id')->get();
$projects->pop();
return view('view', compact('user', 'projects'))

Going from your code you could use take(n):
#foreach ($user->projects->sortByDesc('id')->take($user->projects->count() - 1) as $porject)
// my data
#endforeach
or you could use $loop->last and just render when it's not the last item:
#foreach ($user->projects->sortByDesc('id') as $porject)
#if (! $loop->last)
// my data
#endif
#endforeach
or you could use pop() (as #mrhnn suggested) with tap():
#foreach (tap($user->projects->sortByDesc('id'))->pop() as $porject)
// my data
#endforeach

Related

Only return one row in foreach

I'm starting with Laravel and I'm having trouble getting the results of a query on the laravel blade.
From a list obtained through a query to MySQL 'mysql', I want to check the name it has in another table of another 'tienda' database.
Everything is fine, but it only returns the last value of the second query, it does not return all the values ​​of the $ products query with its corresponding name obtained in $ products_name.
Controller
$productos = [
'id' => $id
];
$products = DB::connection('mysql')
->SELECT("SELECT * FROM promociones_product WHERE id_promo = $id", $productos);
foreach ($products as $product)
{
$products_name = collect(DB::connection('tienda')
->table('ps_product_lang')
->where('id_product', $product->id_product)
->get(['name', 'id_product']));
}
return view('promociones-products')->with('promo', $products_name);
Blade
#foreach($promo as $product)
<tr>
<td>{{ $product->id_product }}</td>
<td>{{ $product->name }}</td>
</tr>
#endforeach
I need to make a query against the 'mysql' database and, with those results, consult its name in another database, and all the values ​​are printed on the screen.
So there are a couple of issues with the code you provided.
To start with, in your loop you are creating a new collection called 'products_name' on each loop which keeps overwriting itself.
There are lots of ways of approaching this however how I would do it is below:
$promo = []; // Initialise a new array called promo
foreach ($products as $product)
{
// Append the collection to the new array
$promo[] = collect(DB::connection('tienda')
->table('ps_product_lang')
->where('id_product', $product->id_product)
->get(['name', 'id_product']));
}
Now you have an array with all of the products in collections.
Now the loop to get that data should work.
You can then return the data to the view using a couple of methods, my preferred method is indeed compact() seen below:
return view('promociones-products', compact('promo'));
What compact() will do is grab any variable names mentioned in the view and pass it through to the view. This compact will pass the $promo variable to the view.

Laravel - Populating view with info from single row (with pivot data)

I currently have a form/view that allows a User to save an Order. This also updates a pivot table with the respective Products and qtys. What I am trying to do, is after this information is inputted and saved into the database, I want to send the user to a checkout page that shows all the information they inputted for that Order.
Relationships
User hasMany Order
Order belongsToMany Product
Product belongsToMany Order
checkout.blade.php
#foreach ($orders as $order)
#foreach ($order->products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->pivot->qty }}</td>
</tr>
#endforeach
#endforeach
OrderController.php
public function checkout($id)
{
$user = Auth::user();
$user->load("orders.products"); //eager load pivot table
$orders = $user->orders->where('order_id', $id);
return view('orders.checkout', compact('orders', 'user'));
}
I know I am calling the order incorrectly, because if I change
$orders = $user->orders->where('order_id', $id);
to
$orders = $user->orders;
It displays correctly, except of course, it populates with every Order's detail.
Or is there some elegant way for me to pass the data from the checkout function without this additional query? (I understand about moving data in Sessions, but I am working with a pivot table, and that complicates things.
If on the checkout page, you want to use just the latest order that the user has made, then you can just load that order using route model binding
Route::get('checkout/{order}', 'OrdersController#checkout');
Then in your controller:
public function checkout(Order $order)
so from here, you can pass this order to the view, and list all the products from this order, and also in your Order model you should have a reference to the user that this order belongs to:
public function user()
{
return $this->belongsTo(User::class);
}
Accessing columns from the pivot table will be:
#foreach($order->products as $product)
<div> {{ $product->pivot->column }} </div>
#endforeach

Laravel array shows as null before data array

I have a user that has many properties. This is user should also be able tp view the offers bet on his properties.
So have the relationship set.
User.php
public function properties(){
return $this->hasMany('App\Property');
}
Property.php
public function offers(){
return $this->hasMany('App\Offer');
}
Then in my controller this is what I have:
public function my_offers(){
$properties = Property::whereUserId(Auth::id())->get();
return view('pages.seller.offers.index', compact('properties'));
}
Then I go to my views like this:
#if($properties)
<ul>
#foreach($properties as $property)
<li>{{$property->offers->offer_message}}</li>
#endforeach
</ul>
#endif
When I view the page I see the below error:
Property [offer_message] does not exist on this collection instance.
But this property exists in my table.
If I change my list item to the one below I can see the array:
<li>{{$property->offers}}</li>
I also see that before and after the array with the data, there are two empty arrays as the image shows below:
Is there anything that I didn't correctly?
If not all the properties have offers, then you should check that before the <li>, besides that, offers is a collection, you need to loop through it, that's why you get the error.
#if($properties)
#php ($i = 1)
<ul>
#foreach($properties as $property)
#if ($property->offers)
#foreach ($property->offers as $offer)
<li>Offer {{ $i++ }}: {{$offer->offer_message}}</li>
#endforeach
#endif
#endforeach
</ul>
#endif
If you want to get only de properties that have offers (Querying Relationship Existence):
$properties = Property::whereUserId(Auth::id())->has('offers')->get();
And you should probably eager load that relationship:
$properties = Property::whereUserId(Auth::id())->has('offers')->with('offers')->get();

Display Fields of Relationship Query in Blade

After binding tables in a model and writing a query, fetched data in a Blade shows error.
Trying to get property of non-object
Model
<?php
public function unit()
{
return $this->belongsTo('TEST\Units');
}
Query
$inst = Instructions::with('unit')
->where('id',$inst_id)
->first()
->get();
Model
#foreach ($inst as $item)
<pre>{{$item->units->name}}</pre>
#endforeach
However, when using this code and I delete a name or other field, no error displays...
#foreach ($inst as $item)
<pre>{{$item->units}}</pre>
#endforeach
output:
{"id":1,"name":"UNIT 101","description":null,"created_at":"2017-03-06 13:30:18","updated_at":"2017-03-06 13:30:18"}
Solved
#foreach ($inst as $item)
#if (!empty($item->unit->id))
<pre>{{$item->unit->name}}</pre>
#endif
#endforeach

Pagination in laravel 5 with realtion on where condition

Model smsHeader
protected $fillable = [
'type',
'imei',
'login',
'ver'
];
public function detail()
{
return $this->hasMany('App\Model\smsDetail', 'id_header');
}
Controller
$smsheader = smsHeader::orderBy('id', 'desc')->where('login', $user->email)->paginate(20);
return view('app.inbox')->with('smsheader', $smsheader);
Views
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1') as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach
but the result of pagination it was error, how i can set paginition in where smsdetail condition....??
sorry for my bad english
The error is showing for this line $header->detail->where('type', '1')
you can access $header->detail within foreach if you want to use where condition then you need to use get() at the end,like below
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1')->get() as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach
Laravel Queries within Blade views do not automatically execute. They simply prepare another QueryBuilder instance. You still need to run one of the "execute" methods (that will run PDOStatement::execute() underneath). These methods are:
first() (returns first result from result set as single object)
get() (which returns a Collection (ArrayObject with some added extra functionality))
paginate($numberPerPage) (which returns a Collection with extra meta information to pass to a $links property accessible via $collection->links())
In your example:
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1')->get() as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach

Resources