Multiple relations (pivot) in Laravel - php

I have a problem with related models.
There are three models. User, PostType (music, animals) and Post.
A user can select the posttypes he wants to see. So I created a pivot-table posttype_user.
Now I can save the selected postTypes binded to a user.
// User model
public function postTypes()
{
return $this->belongsToMany(PostType::class);
}
// PostType model
public function users()
{
return $this->belongsToMany(User::class);
}
The Post model has a foreign key with postType_id. And this relationships in the models:
// Post model
public function postType()
{
return $this->belongsTo(PostType::class);
}
// PostType model
public function post()
{
return $this->hasMany(Post::class);
}
Now I want to receive all Posts (of the selected posTypes) from the current user (Auth::user()).
But I don't know how. Does anyone have an idea?

You can use nested whereHas():
Post::whereHas('postType', function($q) {
$q->whereHas('users', function($q) {
$q->where('id', auth()->id());
});
})->get();
Or you can do this:
$postTypeIds = auth()->user()->postTypes()->pluck('id');
$posts = Post::whereIn('post_type_id', $postTypeIds)->get();

Related

How to filter entries via hasMany relationship in Laravel

I'm trying write an website with Laravel (current version is 5.7) and I have 3 models as: Post, User and Fav. I'm using a simple form to add posts to "favs" table which has 3 columns as; id, user_id and post_id. And I want to list posts that user added favorites bu I can't use "hasMany" method properly.
I can use variables like; $post->user->name but I can't figure it out how to use relationship with "favs" table.
Post Model
public function user() {
return $this->belongsTo('App\User');
}
public function favs() {
return $this->hasMany('App\Fav');
}
Fav Model
public function users() {
return $this->hasMany('App\User');
}
public function posts() {
return $this->hasMany('App\Post', 'post_id', 'id');
}
User Model
public function posts() {
return $this->hasMany('App\Post');
}
public function favs() {
return $this->hasMany('App\Fav');
}
Controller
public function user($id){
$favs = Fav::orderBy('post_id', 'desc')->get();
$user = User::find($id);
$posts = Post::orderBy('id', 'desc')->where('user_id', $id)->where('status', '4')->paginate(10);
return view('front.user')->with('user', $user)->with('posts', $posts)->with('favs', $favs);
}
The Fav model only has one User and Post each, so you need to use belongsTo() instead of hasMany and change the method names to singular. You can also remove the additional parameters in post() since they're the default values.
public function user() {
return $this->belongsTo('App\User');
}
public function post() {
return $this->belongsTo('App\Post');
}
Loading all Posts that a user has favorited:
$user->favs()->with('post')->get();
The with() method is used to eager load the relationship.
Now you can loop through the Favs:
#foreach($favs as $fav)
{{ $fav->post->name }}
#endforeach
I think you can change these two lines of your code to
$posts = Post::orderBy('id', 'desc')->where('user_id', $id)->where('status', '4')->paginate(10);
return view('front.user')->with('user', $user)->with('posts', $posts)->with('favs', $favs);
to
$posts = Post::where('user_id', $id)->where('status', '4')->latest()->paginate(10);
return view('front.user', compact('user', 'posts', 'favs'));
And for retrieving favorite posts of an user,
if you will change the fav table to make it a pivot table only to handle a many to many relationships between Post and User, you can get it as $user->posts, for a separate model, I think you can consider something like $user->favs and in view
In Fav model
public function user() {
return $this->belongsTo('App\User');
}
public function post() {
return $this->belongsTo('App\Post');
}
and in view
#foreach ( $user->favs as $fav )
{{ $fav->post->id }}
#endforeach
If an User, per example, have many Favs you need to use a Iteration Block, like foreach.
Example:
foreach($user->favs as $fav) {
dd($fav) // do something
}
Ps.: Be careful not to confuse hasMany and belongsToMany.

Select specific column in laravel eloquent's with method

I am using laravel 5.6 and i want to get user posts with comments (only id field)
User Model
public function posts()
{
return $this->hasMany('App\Post');
}
Post Model
public function user()
{
return $this->belongsTo('App\User');
}
public function comments()
{
return $this->hasMany('App\Comment');
}
Comment Model
public function post()
{
return $this->belongsTo('App\Post');
}
In my controller i am using this code to get user posts with their comments
$posts = $request->user()->posts()->with(['comments' => function($query) {
$query->select(['id']);
}]);
But its not working...
When i comment $query->select(['id']); it works fine but returns Comment model all fields. I want to only select id field.
What i am missing here?
You also have to select the foreign key column (required for matching the results):
$posts = $request->user()->posts()->with('comments:id,post_id');
If you want to only one column, you can use ->pluck('id')
https://laravel.com/docs/5.6/collections#method-pluck

Laravel - Eloquent: get posts from user with users post table

I searched a lot but could not find any answer about it, so I hope you could help me!
I have three tables: posts, users and post_users.
Post_users contains two columns: user_id and post_id.
I need to get all posts by an user with Eloquent. Any ideas?
Model User:
public function posts()
{
return $this->belongsToMany('App\Post', 'post_users', 'user_id', 'post_id');
}
Model Post:
public function users()
{
return $this->belongsToMany('App\User', 'post_users', 'post_id', 'user_id');
}
Try:
$user = User::find($id);
$allpost = $user->posts()->get();
var_dump($allpost);
The Laravel docs cover this pretty well but I had an issue with it when I first started as well. Check out Laravel Relationships for the fully write up.
// Inside your Post model
public function user() {
return $this->belongsTo('App\User');
}
// Inside your User model
public function posts() {
return $this->hasMany('App\Posts');
}
You can then create a query:
$posts = User::find(1)->posts;
Or you can filter it further..
$posts = User::find(1)->posts()->where('active', 1)->get();
You may need to change your paths for the hasMany() and belongsTo() if your model location and names are different.
As you wish. Relation between User and Post is many-to-many
- Defined relation
// In User model
public function posts(){
return $this->belongsToMany(Post::class);
}
// In Post model
public function users(){
return $this->belongsToMany(User::class);
}
- Table structure
- users
id
- posts
id
- post_user
user_id
post_id
- Get all post by a user
$posts = User::find($user_id)->posts
If you donot have relationship built, try this. However building relationships is preferred. PostUsers and Posts are assumed models of post-users and posts tables, and post as column of the posts table. this gives the posts of logged in user, but not tested.
$postusers=PostUsers::where(['user_id'=>Auth::user()->id])->get();
foreach($postusers as $postuser)
{
$posts=Posts::where(['post_id'=>$postuser->post_id)]->get();
foreach($posts as $post)
{
print_r($post->post);
}
}
Try this
From Controller :
dd(Auth::user()->posts);
App/User
public function posts()
{
return $this->belongsToMany('App\Entities\posts', 'post_users', 'user_id', 'post_id');
}
make relationship with post model on the user model:
public function posts()
{
return $this->hasMany(Post::class);
}
make relationship with user model on the post model:
public function User()
{
return $this->belongsTo(User::class);
}
in controller or Wherever you use:
$userPosts = User::find($user->id)->posts->where('status', 1);

Laravel 5.2 polymorphic model return all where relationship has value

I have a polymorphic model, named FeedItem which is has polymorphic relationships to an Alert and Publication model.
There is also another model, named Category, which the Alert and Publication models have a hasMany relationship to.
FeedItem
public function feedable()
{
return $this->morphTo();
}
Publication
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
Alert
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
I want to be able to get all FeedItems where the feedable models have a given category.
I've tried:
$items = FeedItem::with(['feedable.categories' => function($item) {
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
However, the issue is that the feedable relation never gets eager loaded, which prevents the categories relationship scoping from being performed.
For example, if I do this:
$items = FeedItem::with(['feedable.categories' => function($item) {
dd('This should be displayed');
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
The dd() statement is never called.
Can anyone provide a way of doing this sort of query?

Laravel 5.1 eloquent query syntax

I have the following model relationships. If a user logs in as an employee, I want them to be able to get a list of employees for a their company and the roles they have been assigned:
class User {
// A user can be of an employee user type
public function employee()
{
return $this->hasOne('App\Employee');
}
//
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
class Employee {
// employee profile belong to a user
public function user()
{
return $this->belongsTo('App\User');
}
// employee belongs to a company
public function company()
{
return $this->belongsTo('App\Company');
}
}
class Company {
public function employees()
{
return $this->hasMany('App\Employee');
}
}
But the following query doesnt work. I get error Column not found: 1054 Unknown column companies.id in WHERE clause:
$employee = Auth::user()->employee;
$companyEmployees = Company::with(['employees.user.roles' => function ($query) use ($employee) {
$query->where('companies.id', '=', $employee->company_id)
->orderBy('users.created_at', 'desc');
}])->get();
The users and the employees table have a one to one relationship.
All employees have a base role type of employee in addition they may also have other roles such as manager, supervisor etc.
How do I write a query that gives me a company with all its employees and their roles?
I've tried to add a hasManyThrough relation to the Company model but that doesn't work either?
public function users()
{
return $this->hasManyThrough('App\User', 'App\Employee');
}
I think you're ring to get a list of coworkers for the current user and eager load the user and role?
$employee = Auth::user()->employee;
$companyEmployees = Company::with(['employees.user.roles')->find($employee->company_id);
Or perhaps:
$companyEmployees = Company::find($employee->company_id)->employees()->with('user.roles')->get();
$sorted = $companyEmployees->sortBy(function($employee){ return $employee->user->created_at; });
That might be a more direct route. Is your employee id in the user table or vice versa? The eloquent relationships are easy to set backwards.
Users::select('table_users.id')->with('roles')->join('table_employes', function($join) use ($employee) {
$join->on('table_employes.user_id','=','table_users.id')->where('table_employes.company_id', '=', $employee->company_id);
})->orderBy('tables_users.created_at')->get();
1. Create relationship for database table columns in migrtaion :
User Role
$table->foreign('user_id')->references('id')->on('users');
Users
$table->increments('id');
2. Create a model for each database table to define relationship
User.php (model)
public function userRoles()
{
return $this->hasOne('App\UserRoles', 'user_id', 'id');
}
Userroles.php (model)
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
3. Let controller handle database calls recommended to use REST api
Controller
use App\User;
use App\UserRoles;
class UserController extends Controller
{
public function index()
{
return User::with('userRoles')->orderBy('users.created_at', 'desc')->paginate(50);
}
}

Categories