Having difficulties displaying all content on my wishlist table - php

I am trying to retrieve the data on my wishlist table, for a particular user, so far it only retrieves the first data on the table, just returning one array instead of the three in the table with same user id
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
foreach($wishlists as $wishlist){
$products = Product::where('id', $wishlist->productId)->get();
return $products;
}
}

It happens because the foreach loop returns a value during the first iteration. Place your return statement outside the loop. Also you could improve your performence by making use of relationships.
An example could be:
// Product.php
public function wishlists()
{
return $this->hasMany(Wishlist::class);
}
// Your method
public function getWishlistByUserId($id)
{
return Product::whereHas('wishlists', function ($query) use ($id) {
$query->where('userId', $id);
});
}

Ideally this is n+1 situation
So i will suggest to use laravel relationship like:
in your whishlist model
public function product(){
return $this->hasMany(Product::class,'productId','id');
}
get data with relationship
public function getWishlistByUserId($id){
$wishlists = Wishlist::with('product')->where('userId', $id)->get();
}

I was finally able to get it working this way, i just pushed the result into an array, and then returned it outside the loop, thanks everyone for your help
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
$wishlist = [];
foreach($wishlists as $wish){
$product = Product::where('id', $wish->productId)->get();
array_push($wishlist, $product);
}
return $wishlist;
}

Related

laravel dynamic scope not working

I try to get my categories base on their status and i have scope below in my category model:
public function scopeOfStatus($query, $status)
{
return $query->where('status_id', $status);
}
And my controller is like:
public function finder() {
$findercategories = Category::OfStatus('Active')->get();
return response()->json($findercategories);
}
My route is like:
Route::get('/finder','frontend\SearchController#finder');
But i get blank page as result. Any idea?
update
if i use $findercategories = Category::ofStatus(1)->get(); i get the result that i want but it's static not dynamic :\
Get the Id's from the statuses table with respect to the searched value and use the Id's to get the Category
public function scopeOfStatus($query, $status)
{
$statuses = Status::where('title', $status)->pluck('id'); // Or relevant column name
return $query->whereIn('status_id', $statuses);
}
and in your Controller you could do so
public function finder() {
$findercategories = Category::ofStatus('Active')->get();
return response()->json($findercategories);
}

Laravel relationships belongsToMany

I want to fetch all orders and connect them with their statuses, but I want only the last status for each. I was trying to do it like this, but I only get the status for the first order the rest doesn't have any. How can I fix it?
static function actualKioskOrders()
{
$orders = Order::query();
return $orders->with([
'statuses' => function ($query) {
$query->orderBy('created_at', 'desc')->first();
}
]);
}
In order model add this method, I suggest doing query on model class.
public function status(){
return $this-> belongsToMany(Status::class);
}
public function latestStatus()
return $this->status()->latest()->first();
}
.
I believe the easier way to do it would be
$orders = Order::with('status')->orderBy('created_at', 'desc');
Then if you dd($orders); you will have all the orders with their corresponded status.

Laravel: Ordering data at a query level when using pivot tables?

In my routes/web.php I have a route like this...
Route::get('/tags/{tag}', 'TagsController#show');
Then, inside TagsController because I have a post_tag pivot table that has been defined as a many-to-many relationship.
Tag.php...
public function posts(){
return $this->belongsToMany(Post::class);
}
public function getRouteKeyName(){
return 'name';
}
Post.php...
public function tags(){
return $this->belongsToMany(Tag::class);
}
I get the posts for a certain tag like this...
public function show(Tag $tag){
$posts = $tag->posts;
return view('posts.index', compact('posts','tag'));
}
Then, to sort the posts into newest first I can do this in index.blade.php...
#foreach ($posts->sortByDesc('created_at') as $post)
#include('posts.post')
#endforeach
This works fine, but I'm doing the re-ordering at collection level when I'd prefer to do it at query level.
From Eloquent: Relationships I can see that I can do something like this, which also works...
$user = App\User::find(1);
foreach ($user->roles as $role) {
//
}
But, something like this does not seem to work...
public function show($tag){
$posts = \App\Tag::find($tag);
return view('posts.index', compact('posts'));
}
My question is, how can I filter/order the data at a query level when using pivot tables?
To order your collection you must change
public function tags(){
return $this->belongsToMany(Tag::class);
}
to
public function tags(){
return $this->belongsToMany(Tag::class)->orderBy('created_at');
}
Extending #leli. 1337 answer
To order content without changing the relation created.
First, keep the original relation
class User
{
public function tags
{
return $this->belongsToMany(Tag::class);
}
}
Second, during query building do the following
//say you are doing query building
$users = User::with([
'tags' => function($query) {
$query->orderBy('tags.created_at','desc');
}
])->get();
With this, you can order the content of tags data and in query level also if needed you can add more where clauses to the tags table query builder.

Laravel findOrFail with related data?

In my Menu controller I have a method which should display the specified record and all its children.
I have two models: MenuItem and MenuVariation, My items will have many variations as outlined in my methods:
MenuItem model
public function variant()
{
return $this->hasMany('App\MenuVariation');
}
MenuVariation model
public function item()
{
return $this->belongsTo('App\MenuItem', 'menu_item_id');
}
Now in my controller I have the following method:
public function show($id)
{
$item = MenuItem::findOrFail($id);
return $item;
}
...which currently only shows the item record but not its variations, so I have changed the code like this...
public function show($id)
{
$item = MenuItem::findOrFail($id)->with('variant')->get();
return $item;
}
but this oddly return ALL items and their variations.
Could someone help me get this working as desired? I would like to still utilise FindOrFail on the Item record, but it should also retrieve any variants (if found).
findOrFail will initiate the query, so you want to switch the order and put with in-front of it. Then use findOrFail. See Below:
public function show($id)
{
$item = MenuItem::with('variant')->findOrFail($id);
return $item;
}
There is also no need for get when you do that.

Unable to assign variable value in model constructor

I am playing with Laravel models and I need one to return a value that is not in the db table but it comes by running a model method. This method runs a query that groups and count grouped results.
The model method works just fine but I don't seem to be able to pre-fill the $quantity variable within the constructor with something different than 0.
So this is an excerpt of the model:
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity()
{
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id',$this->cart_id)
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
While this is how I am trying to retrieve the results from controller:
$cartitems = Auth::user()->cartshopping;
foreach ($cartitems as $cartitem)
{
echo $cartitem->name;
echo $cartitem->quantity;
}
As you may guess 'cartshopping' comes from the user model being related with the model excerpt I pasted.
I also noticed that quantity() method gets called and it returns 0 all the time as if $this->cart_id was empty and, changing $this-cart_id with a real value the query itself doesn't even get executed.
Thanks a lot for any suggestion you guys can share.
Have you tried accessing the properties using $this->attributes?
public $quantity;
function __construct($attributes = array(), $exists = false) {
parent::__construct($attributes, $exists);
$this->quantity = $this->quantity();
}
public function quantity() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
Failing that, you could try using the Eloquent accessors, which would be the best way to do it. This would make it dynamic as well, which could be useful.
class YourModel {
// Normal model data here
public function getQuantityAttribute() {
$query = DB::table('carts_shopping')
->select('cart_id', DB::raw('COUNT(*) AS quantity'))
->where('cart_id', $this->attributes['cart_id'])
->groupBy('cart_id')
->first();
return ($query) ? $query->quantity : 0;
}
}

Categories