Get value with max amount in Laravel - php

I'm using laravel-page-view-counter to count visits of my products and it's working just fine, what i need to do is to get list of top 10 products by their visits (get 10 products which has largest number of visits).
Here is what I have:
$visits = Product::join('page-visits', function ($join) {
$join->on('products.id', '=', 'page-visits.visitable_id');
})->get();
$sorted = $visits->sortBy(function ($product, $key) {
return count($product['visits']);
});
But It return from lowest product visits to highest one (it shows product with 0 visit till product with 100 visits) I need reverse method of that to show (product with 100 visits first).

You can do it easily with query builder and some raw queries like this:
$visits = DB::table('products')
->join('page-visits','products.id','=','page-visits.visitable_id')
->select(DB::raw('count(visitable_id) as count'),'products.*')
->groupBy('id')
->orderBy('count','desc')
->take(10)
->get();
I hope you will understand.

Related

Trying to related tables columns and sums with Laravel eloquent

Ok.
I have three tables
products
--product_id
--product_name
--product_type_id
--price15
--price23
--description
--bonus_points
--image
productTypes
--product_type_id
--product_type_name
productQuantities
--id
--product_id
--warehouse_id
--quantity
Products are placed in different warehouses so I have to keep tracks of its numbers
And has relationships are like this
class Product extends Model
{
public function productType() {
return $this->belongsTo('App\Models\ProductType','product_type_id','product_type_id');
}
public function productQuantities() {
return $this->hasMany('App\Models\ProductQuantity','product_id','product_id');
}
}
What I want to get is all columns from products and product type name from productType, sum of quantity from productQuantities, so I can perform search on those column values later on with where().
How can I get these columns with Eloquent?
I know I could get them with raw SQL commands but I need to do this way for compatibility reasons.
I tried this way before I ask the question.
But model relations just stopped working with no errors. Values just got emptied out from the other parts of the page.
$products = Product::selectRaw('products.*, productTypes.product_type_name, sum(product_quantities.quantity) as quantitySum')
->leftjoin('productTypes','products.product_type_id','=','productTypes.product_type_id')
->leftjoin('productQuantities','products.product_id','=','productQuantities.product_id')
->where('products.product_id','like','%'.$searchID.'%')
->where('product_name', 'like', '%'.$searchName.'%')
->where('product_type_name', 'like', '%'.$searchType.'%')
->where(function($q) use ($searchPrice) {
$q->where('price15','like','%'.$searchPrice.'%')
->orwhere('price23','like','%'.$searchPrice.'%');
})
->where('points', 'like', '%'.$searchPoints.'%')
->groupBy('products.product_id')
->orderByRaw($query)
->paginate($paginateBy);
Working version before this was simple.
Product::leftjoin('productTypes','products.product_type_id','=','productTypes.product_type_id')
->select('products.*','productTypes.product_type_name')
->where('products.product_id','like','%'.$searchID.'%')
->where('product_name', 'like', '%'.$searchName.'%')
->where('product_type_name', 'like', '%'.$searchType.'%')
->where(function($q) use ($searchPrice) {
$q->where('price15','like','%'.$searchPrice.'%')
->orwhere('price23','like','%'.$searchPrice.'%');
})
->where('points', 'like', '%'.$searchPoints.'%')
->orderByRaw($query)
->paginate($paginateBy);
And I thought any kind of join methods doesn't seem to be working well with Eloquent relationship? But older one has leftjoin method as well.
I have not tested this (and am assuming you want to group on product_type_name but you should be able to do something along the lines of:
$results = Product::with(['productType','productQuantities'])
->select(DB::raw('products.*,
productType.product_type_name,
sum(productQuantities.quantity) as "QuantitySum"'))
->groupBy('productType.product_type_name')
->get();
OR
$results = DB::table('products')
->join('productType', 'productType.product_type_id', '=', 'products.product_type_id')
->join('productQuantities', 'productQuantities.product_id', '=', 'products.product_id')
->select(DB::raw('products.*,
productType.product_type_name,
productType.product_type_name,
sum(productQuantities.quantity) as "QuantitySum"'))
->groupBy('productType.product_type_name')
->get();
Then you should be able to access the aggregated quantities using (in a loop if you wanted) $results->QuantitySum.
you can get it with eager loading and aggregating. For example, you need to query products has product type name like "new product" and quantity greater than 1000:
Product::with("productType")
->whereHas("productType", function ($query) {
$query->where("product_type_name", "like", "new product");
})
->withCount(["productQuantities as quantity_count" => function ($query) {
$query->selectRaw("sum(quantity)");
}])
->having("quantity_count", ">", 1000)
->get();
you can get through relationship
$product->productType->product_type_name
and attribute:
$product->quantity_count
$products = Product::withsum('productQuantities','quantity')
->leftjoin('product_types','products.product_type_id','=','product_types.product_type_id')
Gives me the result that I wanted. And didn't break the other parts.
But I'm still confused why with() and withSum() didn't work together.
Is it because products belongs to productTypes maybe

Laravel advanced query

Affiliate has many affiliatesHistory, affiliatesHistory belongs to affiliate, how to make the following query?
Take affiliates, where has affiliatesHistory, if affiliatesHistory records count is equal to 1, then do not take affiliatesHistory, which has status of uninstalled.
$affiliates = $user->affiliates()
->whereDoesntHave('affiliatesHistory', function ($q) {
$q->where('affiliates_histories.status', 'Installed earlier')
->orWhere('affiliates_histories.status', 'Uninstalled / Installed earlier');
The following query works, but I need to not take those affiliates, where affiliatesHistory count is equal to 1 and the status is uninstalled.
Any help will be appriaciated.
So, for what I understand you want to get the affiliates which affiliatesHistory status is Installed earlier. If this is the case then try this:
$user_affiliates = $user->affiliates();
$affiliates = $user_affiliates->whereHas('affiliatesHistory', function($q){
$q->where('status', 'Installed earlier');
})->get();
dd($affiliates);
For your case if there are more than one affiliatesHistory items then return else if there is only one affiliatesHistory then it should not contain Uninstalled status, I guess you can use conditional count to get desired results as
$affiliates = Affiliate::withCount([
'affiliatesHistory',
'affiliatesHistory as affiliatesHistoryUninstalled_count' => function ($query) {
$query->where('status', 'Uninstalled');
}
])->where('user_id', $user->id)
->havingRaw('affiliatesHistory_count > 1 OR (affiliatesHistory_count = 1 AND affiliatesHistoryUninstalled_count = 0)')
->get();

Laravel OrderBy relationship count without loading models (count)

I have an episodes table and an episode_Listen table, which is a One episode to Many listens
I want to get the 6 episodes with highest listens. I've tried every single solution like the following:
$trending = Episode::where('active', true)
->get()->sortBy(function($podcast) {
return $podcast->latestListens;
});
Or
$trending = Episode::where('active', true)
->withCount('listens')
->orderBy('listens_count', 'desc')
->get();
Or
$trending = Episode::join('episode_listens', function ($join) {
$join->on('episode_listens.episode_id', '=', 'episodes.id');
})
->groupBy('episodes.id')
->orderBy('count', 'desc')
->select((['episodes.*', DB::raw('COUNT(episode_listens.podcast_id) as count')]))->paginate(6);
But the execution time always exceeds 6 seconds, because I've around 500k listens records in the database, and they'll go millions in a very short period of time.
Any thoughts?
Thanks in advance

Random result except self in laravel

I have this code:
$product = Product::where('slug', $slug)->firstOrFail();
$random = Product::inRandomOrder()->limit(10)->get();
Where by $random I'm getting related result of my products.
The issue is:
If I'm visiting product two page in my random section I see 9 other products + product two
What I want is
To see totally 10 different products and not see product two in my random section while I'm visiting product two page
How can I do that?
Have you tried [WHERE NOT IN] in SQL?
$random = Product::whereNotIn('id', [$product->id])
->inRandomOrder()
->limit(10)
->get();
You can use where to filter
$product = Product::where('slug', $slug)->firstOrFail();
$random = Product::where('id', '!=', $product->id)
->inRandomOrder()
->limit(10)
->get();

Laravel paginator display more pages

what i am trying to do is to get distinct values (date) of my Model and for each date the display the corresponding data. When i make pagination of the distinct dates, it works fine, but in the pagination pages i see all the results instead of the distinct. Here is my function:
public function showdaily($id) {
$capacities = array();
// DB::enableQueryLog();
$capacity_daily = CapacityDaily::select('for_date')->where('capacity_id', '=', $id)->orderBy('for_date', 'asc')->distinct()->paginate(2);
// dd(DB::getQueryLog());
foreach($capacity_daily as $cap) {
$get_capacity = CapacityDaily::where('capacity_id', '=', $id)->where('for_date', '=', $cap->for_date)->orderBy('for_date', 'asc')->distinct()->get();
$capacities[] = array('for_date' => $cap->for_date, 'values' => $get_capacity, 'capacity' => Capacity::find($id)->first());
}
return view('admin.capacity.daily', compact('capacities', 'capacity_daily', 'id'));
}
I have totally 4 distinct dates and 96 rows in that table. As i want to display only 2 dates per page it should show me only one additional page available, but instead of that i have from 1-47.
What i make wrong ?
The toSql() method will show the query it is running, but I suspect you need to group on for_date rather than use distinct
$capacity_daily = CapacityDaily::select('for_date')->where('capacity_id', '=', $id)->orderBy('for_date', 'asc')->groupBy('for_date')->paginate(2);

Categories