Get count of votes with Eloquent in Laravel 4.2 - laravel-4

i'm trying to get count of likes for each picture. Here is my code
$user = User::with(['pictures' => function($q){
$q->with('likes')->count();
}])
This code returns all likes as separately for each picture.
I think this count() is not working for me.
Thanks for help.

$user = User::with(['pictures' => function($q){
$q->where('likes',1)->count();
}]);
Remember to specify a relationship in User Model like so:
class Country extends \Eloquent {
public function pictures(){
return $this->hasMany('App\Models\Picture');
}
}
NB: I assumed App\Models\Picture is your pictures Model and also that 'likes' is Boolean datatype column in pictures table

Related

Laravel Eloquent is there a better way to write this query?

I have a typical pivot table structure like this:
Users
id [...]
Locations
id [...]
User_Location
id | user_id | location_id
I need to get the locations the current authorized user has access to, and then I need to get all the users who also have access to all of those locations.
I tried to figure out an "eloquent" way to do this, but I'm not familiar enough with it. This works, but I'm wondering if it's the best way to do it?
$locations = auth()->user()->locations(); //returns the user_location records
$locationIds = $locations->pluck('location_id');
$locationUsers = new UserLocation();
$userIds = $locationUsers->whereIn('location_id', $locationIds)->groupBy('user_id')->pluck('user_id');
$users = User::withTrashed()
->whereIn('id', $userIds)
->get();
return view('users.index')->with('users', $users);
here's the locations() relationship referenced in the code:
public function locations()
{
return $this->belongsToMany(Location::class, 'user_location')->withPivot('primary');
}
You must create a new method in the Locations model.
public function users()
{
return $this->belongsToMany(User::class, 'user_location');
}
Then your query could look like this.
$locations = auth()->user()->locations()->with('users')->get();
$users = $locations->pluck('users');
If you need to get all users withTrashed then you should modify the first line for this.
$locations = auth()->user()->locations()->with(['users' => function ($user) {
$user->withTrashed();
}])->get();

How to filter Eloquent collection with data from pivot table

I'm searching for a fine and neat solution to filter my Eloquent collection with the data in the related pivot table. I actually found a solution to my problem already though it feels like my solution is somehow bad. Here is, what I got:
Two models Video and User where every user can track separately the progress on a video. For this I need to save the progress for every video in the ratings table related to the user. When you want to search for just the progress you can do that besides some other filters (category, full text search). What I find a bit quirky is that I have to double "where()" the part where I'm checking the video progress for the logged in user.
Video.php
class Video extends Model
{
use SearchableTrait;
use Taggable;
[...]
public function videocreator(){
return $this->belongsTo('App\User', 'create_user_id');
}
public function users(){
return $this->belongsToMany('App\User', 'progress', 'video_id', 'user_id')
->withPivot('progress_index')
->withTimestamps();
}
[...]
}
User.php
class User extends Authenticatable
{
use Notifiable;
[...]
public function videoscreated(){
return $this->hasMany('App\Video');
}
public function videos(){
return $this->belongsToMany('App\Video', 'progress', 'user_id', 'video_id')
->withPivot('progress_index')
->withTimestamps();;
}
}
VideoController.php
class VideoController extends Controller
{
public function index(Request $request)
{
[...]
$videos = Video::with('videocreator')->with(['users' => function ($query) {
$query->where('users.id', '=', auth()->user()->id);
}])->latest();
if($request->filled('progress') && $request['progress'] !== 'all'){
$videos = $videos->whereHas('users', function($query) use($selectedProgress) {
$query->where('progress_index', $selectedProgress)->where('users.id', '=', auth()->user()->id);
});
}
$videos = $videos->get();
[...]
}
As you can see this part where('users.id', '=', auth()->user()->id) is duplicated. A friend of mine from the Ruby on Rails Faction proposed to come from the User Model first and then fetch the Videos (that's how you would do it there). Though this way you would limit the videos to the user from the progress table. This is not what you want. The App shall track only the per user progress per video, meaning, all the users can see all the videos (just not the progress which is not their own.
Another approach would be to put the part where you filter for the user into the relationship. A method like: myProgress() or something similar.
What is your opinion to that? Is there a more 'eloquent' way to solve that?
Thanks in advance for reading this post!
I would do something like this :
// Get an instance of the videos relationship of the current authenticated user
// Eager load the videocreator relationship
$videoQuery = request()->user()->videos()->with('videocreator');
if ($request->filled('progress') && $request->input('progress') !== "all") {
// Constrain the query : only get the videos with rated_index equal to $selectedProgress
$videoQuery = $videoQuery->wherePivot('rated_index', $selectedProgress);
}
// Finally, run the query against the database
$videos = $videoQuery->latest()->get();

How to retrieve multiple relations with multiple tables in laravel eloquent

I'm using Laravel 5.8 to build a babysitting site. I have 4 tables with different relationships as below:
please see this image
The relationships are:
Babysitter->hasMany(session)
Sessions->hasOne(Review)
Sessions->hasOne(Kids)
Sessions->hasOne(Babysitter)
Sessions->hasOne(Parent)
I want to achieve 2 things:
First one
I want to show this result when listing all babysitters. I'm showing this information for each babysitter:
plsease see this image
See here what I couldn't achieve
plsease see this image
This is my code
Sitters::where('Status', 'active')->where('Verified', 1)->get();
Second one
Also, I've tried to show kids name with parent review as shown here:
plsease see this image
This is what i'm using
Sessions::select('Reviews.*', 'Sessions.Parent_id')->join('Reviews', 'Reviews.Session_id', '=', 'Sessions.id')->with('owner')->where('Trainer_id', session('user')->Id)->where('Status', '=', 'complete')->with('owner')->orderBy('Sessions.id', 'DESC')->get();
Here is Session.php Model
public function owner(){
return $this->belongsTo('App\Models\Parents', 'Parent_id');
}
As discussed change the relations:
Babysitter->hasMany(sesstion)
Sessions->hasOne(Review)
Sessions->belongsTo(Kids)
Sessions->belongsTo(Babysitter)
Sessions->belongsTo(Parent)
First one
in Babysitter.php declare the following attributes
class Babysitter extends Model
{
public function reviews()
{
$this->hasManyThrough(Review::class, Session::class);
}
public function getAverageReviewAttribute()
{
return $this->reviews()->avg('Rating');
}
}
Then you just need to call it on the model instance.
$babysitter = Babysitter::first();
return $babysitter->average_review;
Second one
Just use the relation
$babysitter = BabySitter::with(['sessions' => public function ($session) {
$session->with(['review','parent','kids']);
})->where('trainer_id', '=', session('user')->Id) //did not understand this condition
->first();
This assumes you have parent, kids and review relation declared on Session::class. (change the names if needed)
After a few days of searching & testing, this is what worked for me:
Inside (Sitters) Model, put this relation
public function sessions()
{
return $this->hasMany(Sessions::class, 'sitter_id')
->withCount('reviews')
->withCount(['reviews as review_avg' => function($query){
$query->select(DB::raw('AVG(Rating)'));
}]);
}
Also, inside (Sessions) Model, put this relation
public function reviews()
{
return $this->hasOne(Reviews::class, 'Session_id');
}
Now you query like this
return $sitters = Sitters::with('sessions')->get();
I hope this can help someone :)

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.

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