Suppose I have a User model and a Post model.
class Post extends Eloquent
{
}
There are many users, and each User has many Post. All Post belongs to a User.
class User extends Eloquent
{
public function posts()
{
return $this->hasMany('Post');
}
}
I know that I can get a single User with find().
$user = User::find(1);
I know that from a single User, I can get all their posts().
$posts = User::find(1)->posts;
However, suppose now I have multiple users.
$users = User::all();
I wish to access all the posts that this collection of users have. Something along the lines of
$posts = User::all()->posts;
This, of course, doesn't work. However, in theory, it should be functionally equivalent to
$posts = Post::all()
Is there a way to do something similar to the above in Laravel 4.2?
I do not want to use Post::all(). Reason being that it would not be what I want in a more complicated example that involves constraints on User.
$postsByMaleUsers = User::where('gender', '=', 'male')->posts;
Should get all the posts made by male users.
I am also aware that I could simply use a foreach loop.
foreach($users->posts as $post)
{
// Process result here.
}
However, suppose I am trying to return the results instead of processing the results. For example, I could have a public static function postsByMaleUsers() in the User model, and calling User::postsByMaleUsers() should return a collection of posts by male users only. In which case, the foreach loop would not suit me.
Eager load the posts, then use pluck and collapse to get a flat collection of posts:
$users = User::with('posts')->where('gender', 'male')->get();
$posts = $users->pluck('posts')->collapse();
Related
I have two tables named posts and categories. these two tables have one-to-many relationship and I wrote them in models like this:
class Post extends Model
{
...
public function category()
{
return $this->belongsTo(Category::class, 'category_id', 'id');
}
...
}
class Category extends Model
{
...
public function posts()
{
return $this->hasMany(Post::class, 'category_id', 'id');
}
...
}
This is work fine when I use $post = Post::find($id) in controller and retrieve one post and use $post->category to get category of this post. but what if I want to retrieve all posts and their categories together?
I mean, let's assume that I have 10 posts in DataBase and I have $posts = Post::get(); to get all posts. now, how I can get categories of each post?
One way is loop! for example:
foreach($posts as $post) {
$post['category'] = $post->category;
}
return response()->json($posts);
Yeah! I want to response in Json and I forgot to say earlier, sorry.
Is there better way to do this? I searched and I got nothing by my search. I'll be appreciated if anyone response to my problem. :)
The easiest way to include categories in each post model with json, is simply including it using with() and it will automatically transform it.
return Post::with('category')->get();
In Laravel you do not have to wrap models or collections in response->json(); it will automatically do that.
I am creating a comment table in my Laravel project so that users can comment on products. I want to make a table which can integrate with my user table (like a one-to-many relationship) in Laravel.
Here is my code:
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
$comments =comments::orderBy('id','desc')->get();
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Here I send my data to the view in my project. I don't understand how to access the data which is in my user table along with the data in the comment table.
First comments::orderBy... should be Comments::orderBy... ,
But you don't need that,
It's so simple to get user comments :
First Method: Using with()
Once the relationship has been defined, we can access the collection of comments by accessing the comments property. Remember, since Eloquent provides "dynamic properties", we can access relationship methods as if they were defined as properties on the model:
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
Second Method : Direct
Thankfully, we can use eager loading to reduce this operation to just 2 queries. When querying, you may specify which relationships should be eager loaded using the with method:
$comments = App\Post::find(1)->comments;
foreach ($comments as $comment) {
//
}
In your case :
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
//blow line changed
$comments =$users_comment->comments;
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Hope it helps;)
For example I have:
// Returns all projects
$projects = Projects::all();
To return categories, belonging to project, I use relationships and can do something like:
foreach($projects as $project) { ...show $project->categories... }
I need only specific projects, which are followed by specific user. On my projects_followers table I have user_id and project_id.
To retrieve projects which were followed I have this peace of code:
$projects = Project::rightJoin(DB::raw('(select * from projects_followers group by project_id) projects_followers'),'projects_followers.project_id','=','projects.id')->get();
// Note: This code doesn't include specifuc user_id.
It does retrieve specific rows, but the problem with this code is that laravel relationhips dont work on them. For example $project->categories return empty.
// Relationship
public function categories()
{
return $this->belongsToMany('App\Category');
}
How do I retrieve my model specific rows and make relationships to work?
Actually your question is:
How do I get projects liked/followed by Auth/Logged in User ?
Unfortunately you described it in such a way that it looks something else, anyways. Lets try to find the solution and for this I would like to use something like this:
$projects = Auth::user()->favorite_projects;
So how we can implement this to work, first of all the User Model should contain the method favoriteProjects so lets create it:
public function favoriteProjects()
{
return $this->belongsToMany(
'App\Project',
'projects_followers', // This table already exists as you mentioned
'user_id',
'project_id'
);
}
That's it. You will be able to load the projects followed by the current user and other relationship methods will work on every single project as well.
My workaround:
// I don't know how to create empty collection, so impossible conditions here.
$projects = Project::where('id', 0)->get();
$follows = DB::table('projects_followers')->where('follower_id', Auth::user()->id)->get();
foreach($follows as $follow) {
$project = Project::where('id', $follow->project_id)->first();
$projects = $projects->add($project);
}
For a school project, I'm creating a website in the Laravel framework.
I can't work with the data from a many-to-many table in my controller.
Here are my models:
class Item extends Eloquent {
public function Tags()
{
return $this->belongsToMany('Tag', 'items_has_tags', 'items_id', 'tags_id');
}
}
class Tag extends Eloquent {
public function LearningMaterials()
{
return $this->belongsToMany('LearningMaterial', 'learning_materials_has_tags', 'tags_id', 'learning_materials_id');
}
}
I want to iterate all tags from my items in my controller:
//get all items
$all = Item::where('public', '1')->get();
foreach($allLm as $item){
$tags = $item->Tags();
var_dump('will iterate');
foreach($tags as $t){
var_dump('will not iterate');
}
}
What is wrong with my code? How can I handle the tags from my items?
FYI: I'm creating a search engine. If the user inserts an input value like "mana", all items with tag "management" should be shown.
Laravel's belongsToMany method queries related models and doesn't get them. That's because you might want to have some additional constraints in your query. What you need to do is:
$tags = $item->Tags()->get();
Or simply:
$tags = $item->Tags;
Calling the relationship function will return a relation object (in this case an instance of BelongsToMany). You can use this to run add further components to your query before running it.
For example:
$only4Tags = $item->Tags()->take(4)->get();
If you want the result of your relation, call get() or simpler, just use the magic property:
$tags = $item->Tags()->get();
$tags = $item->Tags;
In normal many2many tutorials, we're taught how to get all B's from a single specific A by doing A->B(). What if you want to get all B's from multiple A's? The first thing that come to mind is using for loop but what if we don't want to use for loop?
This is my situation :
I have two models, ConversationsUser and Events. Now I would like to get all Events from multiple ConversationsUser model without using for loops.
This is my initial take on the problem :
$loginuser = Auth::user();
ConversationsUser::where('user_id','LIKE',$loginuser->id)->events();
but it wouldn't work because the events method isn't found.
These are my models and their relationships
ConversationsUser
public function events(){
return $this->belongsToMany('Events');
}
Events
public function conversations(){
return $this->belongsToMany('ConversationsUser');
}
$conversations = ConversationsUser::with('events')->whereUserId($loginuser->id)->get();
$events = $conversations->lists('events')->collapse()->unique();
UPDATE
Actually there is a trick to achieve that easier:
$events = null;
ConversationsUser::where('user_id','LIKE',$loginuser->id)
// note the reference
->with(['events' => function ($q) use (&$events) {
$events = $q->get();
}])->get();
$events; // all related models with `->pivot` attached (possible dups)
$events->unique(); // unique related events
con: it will run additional query
pro: it's pretty easy to use
The best and easiest thing to do is simple whereIn.
Depending on the relation type you might need a join, like in this case (for brevity I use short variable names):
$convUsers = ConversationsUser::where('user_id','like',$loginuser->id)->get();
$convUsersIds = $convUsers->modelKeys();
// or if you don't need those models but only their ids:
$convUsersIds = ConversationsUser::where('user_id','like',$loginuser->id)->lists('id');
$events = Events::join('PIVOT_TABLE as ce', 'ce.event_id', '=', 'events.id')
->whereIn('ce.conversation_id', $convUsersIds)
->get(['events.*']);
This will return exactly what you needed.