Counting data before sending to view in Laravel - laravel

I have two tables, products and product_images, now I want to show product which has at least one image.
In controller I have a simple function in ProductController to fetch all the products:
public function products(){
$allProducts = $this->product->paginate(15);
return view('frontend.pages.products',compact('allProducts'));
}
But, I want to send the products which has at least one image of each product.
What should I do to achieve that?
Edit:
I have created relationship between tables, now how can I get my desired answer?
I have written this in the Controller:
$allProducts = $this->product->whereHas('product_images', function ($query){
$query->where();
})->get();

Assuming table schema
product
-id
-name
product_image
-id
-product_id
-url //any columns you needed
$product_ids = DB::table('product')
->join('product_image','product_image.product_id','=','product.id')
->select('product.id','roduct.name')
->groupBy('product.id')
->get();
$product_count = count($product_ids);

Eloquent has this built in.
Example
// Retrieve all posts that have three or more comments...
$posts = App\Post::has('comments', '>=', 3)->get();
In your case
In your case you could change the $allProducts line to be
$allProducts = $this->product()->has('product_image', '>=', 1)->paginate(15);
I didn't test the code above.
See documentation for more information on this topic.
https://laravel.com/docs/6.x/eloquent-relationships#querying-relationship-existence

You can use selectRaw:
$products = Product::leftJoin('product_images',function ($join){
$join->on('products.product_id','=','product_images.product_id');
})->selectRaw("products.product_id i, count(product_images.id) c")
->groupBy('products.product_id')
->where('c','>=',3)
->get();

Getting answer querying realtionship:
The query will look like following:
$allProducts = $this->product->has('Images')->paginate(15);
But, make you sure you have created relation in Model like the following:
public function Images(){
return $this->hasMany('\App\Models\ProductImages');
}
I have used hasMany relationship because one product can have multiple images.

Related

Join tables in Laravel Eloquent method

How to write this code in eloquent method ?
$product = DB::table('products')
->join('purchase', 'products.id', '=', 'purchase.id')
->join('sales', 'purchase.id', '=', 'sales.id')
->select('sales.*', 'purchase.*','products.*')
->get();
Create model Product and add one to many relationship with Purchase in Product model.
public function purchases()
{
return $this->hasMany('App\Models\Purchase');
}
Create model Purchase and add one to many relationship with Sale in Purchase model.
public function sales()
{
return $this->hasMany('App\Models\Sale');
}
Create model Sale.
You can retrieve data using following statement.
$products = Product::with('purchases.sales')->get();
Note: I am assuming the relationship as one to many you can also declare as per your data, also you can define one to many inverse relationship, please refer to laravel docs https://laravel.com/docs/8.x/eloquent-relationships#one-to-many.
You will get purchases and sales data in different key so you can use below syntax to loop over it.
foreach ($products as $product) {
foreach ($product->purchases as $purchase) {
//Purchase data for current product
foreach($purchase->sales as $sale){
//Sale data for current purchase
}
}
}

Looking up model in Laravel after returning array of objects in Controller

I am trying to do something I've never done before in Laravel and cannot figure out how to do it.
I have the following code in my Controller:
public function show($id)
{
//Get application for drug
$application = PharmaApplication::where('ApplNo', $id)->first();
//Get all products for given application (i.e. the different quantities and forms drug comes in)
$product = PharmaProduct::where('ApplNo', $id)->get();
foreach($product as $product){
$product->ProductNo;
}
//Get Marketing Status for drug
$marketingStatus = DB::table('pharma_marketing_statuses')
->where('ApplNo', $id)
->where('ProductNo', $product->ProductNo)
->get();
//Lookup marketing status Description
$marketingStatusDescription = PharmaMarketingSatusLookup::where('MarketingStatusID', $marketingStatus->MarketingStatusID);
return view('profiles.drug', compact('application', 'product', 'marketingStatus', 'marketingStatusDescription'));
}
I am trying to accomplish the following:
Get the application for a drug - this part of my code works
Return an array of objects for the products (i.e. 7 products that belong to one application). I can do this but get stuck going to the next part.
Next, I have to use the array of objects and search a table with the following columns: MarketingStatusID, ApplNo, ProductNo. I know how to query this table and get one row, but the problem is I have an array that I need to search. I imagine I have to use a loop but don't know where.
Finally, I use the MarketingStatusID to retrieve the MarketingStatusDescription which I will know how to do.
I am also getting an error message that says:
Class 'App\Http\Controllers\profiles\PharmaMarketingSatusLookup' not found
In my Controller, I have use App\PharmaMarketingStatusLookup; so I am not sure why it is searching the Controllers folder
You have a typo in your class
From PharmaMarketingSatusLookup change to PharmaMarketingStatusLookup
App\Http\Controllers\profiles\PharmaMarketingStatusLookup
USE whereIn
use App\PharmaApplication;
use App\PharmaProduct;
use App\PharmaMarketingSatusLookup;
public function show($id)
{
$application = PharmaApplication::where('ApplNo', $id)->first();
$products = PharmaProduct::where('ApplNo', $id)->get();
$productid = array();
foreach($products as $product){
$productid[] = $product->ProductNo;
}
$marketingStatus = DB::table('pharma_marketing_statuses')
->where('ApplNo', $id)
->whereIn('ProductNo', $productid)
->get();
$marketingStatusDescription = PharmaMarketingSatusLookup::where('MarketingStatusID', $marketingStatus->MarketingStatusID);
return view('profiles.drug', compact('application', 'product', 'marketingStatus', 'marketingStatusDescription'));
}

Laravel eloquent get data from two tables

Laravel Eloquent Query builder problem
Hello I have a problem when I am trying to get all the rows where slug = $slug.
I will explain in more details:
I have two tables, cards and card_categories.
cards has category_id.
card_categories has slug.
What I need is a query which returns all the cards which contents the slugs.
For example I made this:
$cards = Card::leftJoin('card_categories', 'cards.id', '=', 'card_categories.id')
->select('cards.*', 'card_categories.*')
->where('card_categories.slug', $slug)
->paginate(5);
But what happens is that just return 1 row per category.
I don't know what is wrong.
Many thanks.
I think I understand what you mean, from your explanation I would imagine your card model is as follows.
class Card extends Model {
protected $table = 'cards';
public function category()
{
return $this->belongsTo(Category::class)
}
}
In which case, you should just be able to do this:
$cards = Card::whereHas('category', function ($query) use ($slug) {
$query->where('slug', $slug);
})->paginate(5);
That will select all of the cards that has the category id of the given slug.

Use Eloquent to attach array to query

I have a USER table, an ITEMS table, and a LIKES table. I'm randomly taking 9 items from the Items table (which is named 'categories') and I want to get an array of users which liked that item. I'm returning a JSON response so I can't use laravel's ORM relationships as far as I know. I want to be able to look through the results (with javascript) like so:
foreach item
item->price
....
foreach user
(this is how i wish to look through the users with js)
endforeach
endforeach
{{--Im trying to get an output that looks like so--}}
0: {
cost: 409
views: 0
...
user_like_id: {1,5,2,4,5}
}
EDIT: This is what I would like to attach the array to...
$likes = Category::orderByRaw("RAND()")
->leftJoin('likes', 'likes.item_id', '=', 'categories.id')
->take(9)
->get();
I'm relatively new to programming so please dont downnrate this question
Laravel provides in ways to make json from objects. The first and simplest is the eloquent toJson() method:
$likes = Category::orderByRaw("RAND()")
->leftJoin('likes', 'likes.item_id', '=', 'categories.id')
->take(9)
->get()
->toJson();
$likes is now json.
Second method:
If you return a model from a controller or a routecallback function, laravel returns it as json. So:
class MyController extends Controller{
public function getIndex(){
return Category::orderByRaw("RAND()")
->leftJoin('likes', 'likes.item_id', '=', 'categories.id')
->take(9)
->get();
}
}
This example returns a json response which is quite usefull!
I actually got exactly what I wanted with this:
$likes = Category::orderByRaw("RAND()")
->take(9)
->with(array('getLikes' => function($query)
{
$query->with('getUser');
}))
->get();
Works exactly how I want ito :) thanks for the suggestion tho

laravel search many to many Relashionship

I am testing eloquent for the first time and I want to see if it suit my application.
I have Product table:
id, name
and model:
class Produit extends Eloquent {
public function eavs()
{
return $this->belongsToMany('Eav')
->withPivot('value_int', 'value_varchar', 'value_date');
}
}
and eav table:
id, name, code, field_type
and pivot table:
product_id, eav_id, value_int, value_varchar, value_date
class Eav extends Eloquent {
public function produitTypes()
{
return $this->belongsToMany(
'ProduitType'
->withPivot('cs_attributs_produits_types_required');
}
All this is working.
But I want to search in that relashionship:
e.g: all product that have eav_id=3 and value_int=3
I have tested this:
$produits = Produit::with( array('eavs' => function($query)
{
$query->where('id', '3')->where('value_int', '3');
}))->get();
But I get all the product, and eav data only for these who have id=3 and value_int=3.
I want to get only the product that match this search...
Thank you
I know the question is very old. But added the answer that works in the latest versions of Laravel.
In Laravel 6.x+ versions you can use whereHas method.
So your query will look like this:
Produit::whereHas('eavs', function (Builder $query) {
// Query the pivot table
$query->where('eav_id', 3);
})->get()
My suggestion and something I like to follow is to start with what you know. In this case, we know the eav_id, so let's go from there.
$produits = Eav::find(3)->produits()->where('value_int', '3')->get();
Eager loading in this case isn't going to save you any performance because we are cutting down the 1+n query problem as described in the documentation because we are starting off with using find(). It's also going to be a lot easier to read and understand.
Using query builder for checking multiple eavs
$produits = DB::table('produits')
->join('eav_produit', 'eav_produit.produit_id', '=', 'produits.id')
->join('eavs', 'eavs.id', '=', 'eav_produit.eav_id')
->where(function($query)
{
$query->where('eav_produit.value_int','=','3');
$query->where('eavs.id', '=', '3');
})
->orWhere(function($query)
{
$query->where('eav_produit.value_int','=','1');
$query->where('eavs.id', '=', '1');
})
->select('produits.*')
->get();
Making it work with what you already have...
$produits = Produit::with( array('eavs' => function($query)
{
$query->where('id', '3')->where('value_int', '3');
$query->orWhere('id', '1')->where('value_int', '1');
}))->get();
foreach($produits as $produit)
{
if(!produit->eavs)
continue;
// Do stuff
}
From http://four.laravel.com/docs/eloquent:
When accessing the records for a model, you may wish to limit your results based on the existence of a relationship. For example, you wish to pull all blog posts that have at least one comment. To do so, you may use the has method
$posts = Post::has('comments')->get();
Using the "has()" method should give you an array with only products that have EAV that match your criteria.
$produits = Produit::with( array('eavs' => function($query)
{
$query->where('id', '3')->where('value_int', '3');
}))->has('eavs')->get();

Resources