Querying other database using whererIn() and leftJoin() in the same query - laravel

To get the posts from another database corresponding to the id of the $ids array I use, for example, the following query (it works fine):
$ids = [1, 2, 4, 7];
$data = DB::connection('mysqlDatabase2')
->table('posts')
->whereIn('id_post', $ids)
->get();
Post has many comments.
The problem to solve is to also get the comments related to each post.
I tried with the following query, which returns two problems:
1- posts are returned duplicated;
2- return just one comment per post instead of an array with all related comments
$ids = [1, 2, 4, 7];
$data = DB::connection('mysqlDatabase2')
->table('posts')
->whereIn('posts.id_post', $ids)
->leftJoin('comments', 'post.id_post', '=', 'comments.id_post')
->get();
Edited:
The following is happening: if a post has three related comments, it returns the same post three times, each with one of the comments.

Dont Use Joins. You can use the Eloquent ORM
In Your Model Post.php file:
//If you want All comments related to posts
public function comments(){
return $this->hasMany(Comment::class, 'id_post')->orderBy('created_at', 'desc');
}
//If you want Single latest comment related to posts
public function latestComment(){
return $this->hasOne(Comment::class, 'id_post')->latest('created_at');
}
Now, in your controller you can use this like:
$data = Post::with('latestComment')->get();
Or
$data = Post::with('comments')->get();

Related

Laravel ORM query where with two columns and differents tables

I'm new in Laravel and maybe could be silly
1.- Query with two tables and using two columns in each table
class Post extends Model {
public function Comment()
{
return $this->hasMany('App\Comment');
}
}
Figure out the Post model has the column type. I want to consult where type = 1 and title = foo(comment model).The below example only has the title.
$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();
2.- My second question, Is there a way to run the orm queries without running or render the application. I mean like sqlplus or mysql terminal.
Q1: I want to consult where type = 1 and title = foo(comment model).
A1: Constraining Eager Loads
// From the docs
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
// So in your case -
$comments = App\Comment::with(['posts' => function ($query) {
$query->where('type', '=', 1); // Constraints on the Post model
})->where('title', '=', 'foo')->first(); // Constraints on the Comment model
Q2: Is there a way to run the orm queries without running or render the application.
A2: - Use the Artisan Console
Read up on using the php artisan tinker with the link to the docs above.
Answering with your question
// Answer 1
Post::with('comments')->where([
['type', 1],
['comments.title', '=', 'foo']
])->get();
// Answer 2
// you can use tinker: https://laravel.com/docs/7.x/artisan#tinker

Laravel Eloquent subquery and count subquery results

Let's say there's a Post model. It has a hasMany relationship called comments() defined in its model.
I'm trying to:
Get the count of comments
That belongs to a specific set of Posts, defined by an array of ids
Where the comments are posted in a certain date range
I thought the following would work:
$ids = [1, 2, 3, 4];
$results = Post::whereIn('id', $ids)
->with(['comments'])
->whereHas('comments', function($q) {
$q->whereMonth('created_at', Carbon::now()->month);
})
->withCount('comments')
->get();
And then do
$count = array_sum($results->pluck('comments_count')->toArray());
The result of the query does include comments_count so that's working, and $count works as well.
But the date range in the subquery is not applied, it counts all comments. What am I missing?
You will need to pass the same condition/subquery to the withCount method:
->withCount(['comments' => function($q) {
$q->whereMonth('created_at', Carbon::now()->month);
}])
https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.html#method_withCount

Laravel eloquent: group the related models (e.g. all the comments for collection of posts)

To get the comments for a single Post: Post::find(1)->comments()
To get multiple Posts: Post::whereBetween('id',[1,10])
How to get all the combined comments for multiple Posts?
A la Post::whereBetween('id',[1,10])->comments()
Use pluck():
$posts = Post::whereBetween('id', [1, 10])->with('comments')->get();
$comments = $posts->pluck('comments')->flatten();
You can use this
$posts = Post::whereBetween('id',[1,10])->with('comments')->get();
Or if you wont to get only comments
$comments = App\Comment::whereHas('post', function ($query) {
$query->whereBetween('id', [1, 10]);
})->get();
Or if related primary key post_id
$comments = App\Comment::whereBetween('post_id', [1, 10])->get();
If you just want the comments, and assuming you have a post_id field in your Comment model, and you have the ids of the posts as you've indicated:
$comments = Comment::whereIn('post_id', [1,2,3,4,5,6,7,8,9,10])->get();

How to get last value for each foreign key in laravel?

I have two tables - posts and comments. Each post has a lot of comments. I need to retrieve last comments of a user all posts where he has ever replied. Like if he commented to a post multiple times I need only the last comment to that post.
So if he commented to 10 posts 43 times, I need only 10 comments (those that were last to each post).
I tried:
Comment::where('user_id', $user_id)
->orderBy('created_at','DESC')
->distinct('post_id')
->get();
But it returns all his comments.
I have made a sample comments table and tried with following DB query it return the desired result.
Here is the code.
$data = DB::table('comments as c1')
->select('c1.col_2', 'c1.col_2')
->leftJoin('comments as c2', function($join) {
$join->on('c1.post_id', '=', 'c2.post_id');
$join->on('c1.id', '<', 'c2.id');
})
->whereNull('c2.id')
->limit(10)
->get();
put relation in your 'post' model ('post.php').
public function comments(){
return $this->hasMany('App\Comments','id_post','id');
}
public function last10comment (){
return $this->comments()->orderBy('created_at','DESC')->take(10)->get();
}
try in your controller :
call on each post $post->last10comment()` //return array/collection

Laravel 4.2 - Use where clause on related tables

I am working with two models, UserType and User - UserType hasMany User.
I am trying to retrieve a list of Users associated with a UserType that has the property receive_email set to 1 (true).
I have tried:
$userGroups = UserType::with(['Users' => function($query) {
$query->whereReceiveEmail(1)->whereNotNull('email')->whereNull('status');
}])->whereIn('id', [10, 1])->get();
and the Where clause seems to be totally ignored. From the Laravel 4.2 docs -
$users = User::with(array('posts' => function($query)
{
$query->where('title', 'like', '%first%');
}))->get();
I have seen many people say that this is not the correct way to use eager loading constraints but I really do not know what that would be, they do not seem to do anything. So, the short question, how can I retrieve a listing of Users with receive_email set to 1 through the UserType relation?
UPDATE
Can someone explain to me what the example code from the docs above is supposed to do? I'm assuming that it is supposed to return Posts associated with Users that match the constraint of having a title LIKE "first." In my case, I'm trying to find Users associated with UserTypes where each User has receive_email set to 1. The only significant differences between my code and the example code is that I am applying whereIn() and the model names are different.
So, with the results from the example, would the following be true?
foreach ($users as $user) {
foreach ($user->posts as $post) {
// matching posts with titles LIKE "first"
}
}
If you're after a list of users, then I suggest you actually start with that model and make use of whereHas to filter by user type:
$users = User::where('receive_email', 1)
->whereNotNull('email')
->whereNull('status')
->whereHas('UserType', function($q){
$q->whereIn('id', [1, 10]);
})
->get();
And actually, since the user type id should exist as foreign key in the users table, you don't even need whereHas:
$users = User::where('receive_email', 1)
->whereNotNull('email')
->whereNull('status')
->whereIn('user_type_id', [1, 10]);
->get();
For RosterMember it's basically the same. Although now you have to use whereHas since it's a many-to-many relation:
$rosterMembers = RosterMember::where('receive_email', 1)
->whereNotNull('email')
->whereHas('UserType', function($q){
$q->whereIn('user_type_id', [1, 10]);
})
->get();
I'm not 100% familiar with relationships, they've always been a bit tricky. But from what I understand, you want all the Users in UserType 1 and 10 that have receive_emails set to 1. So, this should work:
$result =
UserType::whereIn("id", array(1, 10))
->first()
->users()
->where("receive_email", "=", 1)
->whereNotNull("emails")
->whereNull("status")
->get()
;
What this should do is return all the accessible fields from both id 1 and 10 of UserType as well as all fields from the User table. If you run a dd($result) on this query, you should see an entry for UserType id 1 connected to all the Users that have receive_email set to 1, and another set for UserType id 10.
I can't guarantee that this will work without seeing your UserType.php and User.php classes, as the relationships might not be set, but if you followed Laravel convention:
public function users(){
return $this->hasMany("User");
}
and the inverse
public function userType(){
return $this->belongsTo("UserType");
}
then it should work. Hope this helps! Also, I'm sure there are better ways to accomplish this, but this is what I came up with, and it seems to work on some of my existing projects with relationships.
Cheers!

Resources