Hope you're all having a good day. I'm working on a blogs page and reached a part where I want to display the certain blogs a user has posted. I added relations to the Post model and User model but i can't seem to get the specific posts of the logged in user and it gives me the error above in the title. Here are my models and Profile controller.
The users schemaThe posts schema
Post model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
}
Posts function in User model
public function posts(){
return $this->hasMany(Post::class);
}
The ProfileController
<?php
namespace App\Http\Controllers;
use App\Reviews;
use Illuminate\Foundation\Auth\User;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$user_id=auth()->user()->id;
$user = User::where('id', $user_id)->get();
$posts= $user->posts;//Gets all details of the user with id 123
return view('profile')->with(['users' => $user ],['posts', $posts]);
}
}
$user = User::where('id', $user_id)->get(); // return a collection so it is multiple items and would have to be accessed as so
This should be
$user = User::where('id', $user_id)->first();
Or rather
$user = User::find($user_id);
But better
$user = auth()->user()
Be mindful that you are doing some unnecessary work, auth()->user() is the user instance there is no need to use that to then get it from the database. As it stands you would have access to the User in the blade template for profile using Auth::user() So there may be no reason just yet to even do any database queries in the controller. This may change as you build out the page of course
Related
I have a pivot table post_profile that contains the hearts (likes) of each post.
Post.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
public function profilesHearted()
{
return $this->belongsToMany(Profile::class);
}
}
Profile.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $guarded = [];
public function profileImage()
{
$imagePath = ($this->image) ? $this->image : 'profile/czyhBQu2YWX6gvBivZrnEs2ORoBwr3d9mzkwxk8k.png';
return $imagePath;
}
public function followers()
{
return $this->belongsToMany(User::class);
}
public function heartedPosts()
{
return $this->belongsToMany(Post::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
The main view which shows all posts of followed users is working along with the heart button but underneath I want to show liked by <x> and 30 others, where x is first follower of the user if any of the user's follower hearted the post. I tried many ways to get x but I am a bit lost.
This is PostsController.php index function which leads to the view:
public function index()
{
$users = auth()->user()->following()->pluck('profiles.user_id');
$posts = Post::whereIn('user_id', $users)->with('user')->latest()->paginate(5);
return view('posts.index', compact('posts', 'users' ));
}
What I tried to do but deleted eventually after failing is get each post in foreach loop and check if each $post->heartedProfiles(contains($users)), but this doesn't work this way. So another way I tried is in my view ie, index.blade.php
#foreach($users as $userid)
User::select('id')->where('profile_id', $userid)->first()
->profile->profilesHearted->find($post->id)
#endforeach
Which doesn't work because User class cannot be used directly in view without passing.
I'm sure there is a simple and cleaner way to do this in Laravel. This is my first time using Laravel and ORM programming so really felt lost. Took the FreeCodeCamp Instagram clone tutorial and understood the basics. All I need is to give me some idea to get started.
When dealing with many to many you need to use the pivot functions, so you would do like so
Post::profilesHearted()->wherePivotIn('profile_id', $users)->first()
Not checked the code but hopefully it will give you the idea.
Let say i have the following;
User Model;
class User extends Authenticatable
{
public function posts()
{
return $this->hasMany('App\Models\Socials\Post');
}
}
Post Model;
class Post extends Model
{
public function comments()
{
return $this->morphMany('App\Models\Socials\Comment', 'commentable');
}
Comment model;
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
When i used $user = User::find($id); and $user->posts(), it returns all the post of the user, but if i used this method $user->posts()->comments() It return this message Method Illuminate\Database\Query\Builder::comments does not exist.
The question is how can i get all the comments of the user on the said post?
Change:
$user->posts()->comments();
to:
$user->posts->pluck('comments')->collapse();
The method itself returns an instance of Eloquent's query builder allowing you to add to or edit the query if you want. However, if you don't want to edit the query you can access the relationships as properties and Laravel will handle to execution of the query.
Essentially, $user->posts is actually turning into $user->posts()->get() in the background.
Credit to #JonasStaudenmeir.
Apologies if the title doesn't completely make sense... I wasn't sure if the exact terminology for the linking of models are the associated data in their controllers.
I'm trying to paginate a table with the posts created by a user.
I managed to paginate it previously, without the user_id in the posts table. But I've added the user_id to the posts table, and run the migration which works fine.
The following is my Post model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
}
And this is my User model:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = ['name', 'email', 'password',];
protected $hidden = ['password', 'remember_token',];
public function posts() {
return $this->hasMany('App\Post');
}
}
And this is the relevant section of the post controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use App\User;
use Session;
use Carbon\Carbon;
class PostController extends Controller
{
public function index()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('posts.index')->with('posts', $user->posts);
}
I thought that it would simply be a case of appending ->paginate(5) to the $user in the PostController, but that doesn't appear to work.
I get the following:
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$posts
I've tried including the {!! $posts->links() !!} in the posts.index view before the #foreach but that gives:
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$posts
I'm trying to learn Laravel basics by creating this crud application, and have tried combining two tutorials together, but I'm clearly missing something.
You can call ->paginate() on the relationship like this (also I've removed the unnecessary user query, since auth()->user() will execute it already):
public function index()
{
$user = auth()->user();
$posts = $user->posts()->paginate();
// Or with 1 line: $posts = auth()->user()->posts()->paginate();
return view('posts.index')->with('posts', $posts);
}
TLDR: When the SoftDeletes trait is included in my parent model, I no longer get soft deleted instances of the parent model as a dynamic property of the child. How can this be done?
I have defined a couple of basic models, like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;
class User extends Model
{
use SoftDeletes;
public function posts()
{
return $this->hasMany("App\Post");
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo("App\User");
}
public function scopePending(Builder $query)
{
return $query->whereNull("pending");
}
}
In my controller, I want to list pending posts, so I do this:
<?php
namespace App\Controllers;
use App\Post;
class PostController extends Controller
{
public function index()
{
$posts = Post::pending()->get();
return view("post.index", ["pending"=>$posts]);
}
}
And finally, in my view:
#foreach($pending as $post)
{{ $post->title }}<br/>
{{ $post->user->name }}<br/>
#endforeach
This results in an exception being thrown, "Trying to get property of non-object" with the line number corresponding to where I try to output $post->user->name for users which have been soft deleted.
How can I have these dynamic properties include soft deleted items?
Apparently the related user model has been soft-deleted, that's why the related user is not loaded.
Define the relation like in the code below and you'll be always able to fetch a user regardless if they have been soft-deleted or not:
public function user()
{
return $this->belongsTo("App\User")->withTrashed();
}
Unfortunately if you do so
public function user()
{
return $this->belongsTo("App\User")->withTrashed();
}
you will no longer available to use dynamic access to user relation, because dynamic access expects that relation method returns BelongsTo instance, which returns by belongsTo method of Eloquent class. But withTrashed returns Builder instance.
EDIT
I was wrong, thanks #patricius for being guided on the right path (in comments).
I'm making a small work with Laravel and using Zizaco Entrust.
While logged in as Administrator I want to see all Roles of a specific user.
I'v searched for a while but didn't find any clue...
How can I do it using Entrust or shall I use SQL queries?
In your User class add
public function roles()
{
return $this->belongsToMany('Role','assigned_roles');
}
Then you can get all roles for a specific user
$user = User::with('roles')->find(1);
$roles = $user->roles;
If you are using Zizaco\Entrust you don't need new roles method in User model. Roles method already exist in EntrustUserTrait class. You only need this line inside User class:
use EntrustUserTrait;
like this:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;
class User extends Authenticatable
{
use EntrustUserTrait; // add this trait to your user model
.....
}
In your UsersController you can select users with their roles (index method):
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use App\Http\Requests;
class UsersController extends Controller
{
protected $users;
public function __construct(User $users)
{
$this->users = $users;
parent::__construct();
}
public function index()
{
$users = $this->users->with('roles')->paginate(25);
return view('users.index', compact('users'));
}
In your blade loop $user->roles inside $users loop because $user->roles are collection even if user have only one role.
#foreach($users as $user)
#foreach($user->roles as $role)
{{ $role->display_name }}
#endforeach
#endforeach