Displaying posts with users in laravel - php

I m new to laravel i want to display all the posts on a view with the name of the user who created the post.. I m trying to do that but I m getting the error of "Trying to get property 'name' of non-object " ..
Any kind of help will be appreciated Thank you
User.php
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
public function Posts(){
return $this->hasMany('\App\Post');
}
protected $fillable = [
'name', 'email', 'password','verifyToken','dob',
];
Post.php
class Post extends Model
{
public function Users(){
return $this->belongsTo('\App\User');
}
protected $fillable = [
'title','body','thumbnail','user_id',
];
PostController.php
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$posts=Post::paginate(5);
return view('\home2',compact('posts'));
}
web.php
Route::get('/home2', 'PostController#index')->name('home');
Home2.blade.php
#foreach($posts as $post)
<div class="text-center">
<h1 align="center">{{$post->title }}</h1>
<h4 align="center">{{$post->body}}</h4>
<p>{{ $post->created_at->diffForHumans() }}</p>
<p> {{$post->Users->name}}</p>

Eager load the users:
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$posts=Post::with('users')->paginate(5);
return view('\home2',compact('posts'));
}
Then on the blade:
<p> {{$post->user->name}}</p>
Update your relationship classes
from:
public function Posts(){
return $this->hasMany('\App\Post');
}
to
public function posts(){
return $this->hasMany(Post::class);
}
Import at the top use App\Post;
and
public function user(){
return $this->belongsTo(User::class);
}
Import at the top use App\User;

Your models should look like this.
User.php
public function posts(){
return $this->hasMany('App\Post');
}
Post.php
public function user(){
return $this->belongsTo('App\User','user_id');
}
then your blade code should be like this,
<p> {{$post->user->name}}</p>

Related

Can't get detailed deleted with soft delete feature in Laravel 5.7

I'm using soft delete feature in laravel, it is ok when I load all data with Post::withTrashed()->get() method. But when I want to get the detailed information of the data using this query Post::withTrashed()->find($post)->get(), it throws me to 404 page. Please help.
I tried Post::onlyTrashed()->find($post)->get() too, but still the same.
I checked the routes file by directly echoing a Hello world string on it and does work normally.
UPDATE
Controller script.
public function fetchDeletedPosts()
{
return Post::onlyTrashed()->paginate(10);
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Post $post
* #return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
$posts = Post::withTrashed()->find($post)->first();
return view('post.edit', compact('posts'));
}
web.php script
Route::get('posts/deleted', 'PostController#fetchDeletedPosts')->name('posts.removed');
Route::get('posts/deleted/{post}/edit', 'PostController#edit');
Post.php script
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['deleted_at'];
protected $fillable = [
'category_id', 'status', 'slug', 'title', 'content-preview', 'content'
];
public function getRouteKeyName() {
return 'slug';
}
public function author() {
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function tags() {
return $this->belongsToMany(Tag::class);
}
}
Laravel dependency injection container will already fetch the data for you. But you have a deleted post. That's why you got a 404.
So change your route to:
Route::get('posts/deleted/{id}/edit', 'PostController#edit');
And your controller to
public function edit($id)
{
$posts = Post::withTrashed()->find($id);
return view('post.edit', compact('posts'));
}

How to get the name of user that belongs to foreign key using Laravel?

I want to get the name of User where belongs the foreign key using Laravel Eloquent.
I have posts Model:
Class Posts Extends Eloquent{
protected $table = 'posts';
protected $fillable = array('title, image, text, user_id');
public $timestamps = false;
}
and
User Model:
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
I want to send to controller the value of user name, title, text, image to view.
public function index(){
// get all the bears
$posts = Posts::all();
return View::make('welcome', compact('posts'));
}
Define the one to many relationship between the models as,
class Posts extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
// Whatever your code in Post model
}
class User extends Model
{
public function posts(){
return $this->hasMany('App\Post');
}
// Whatever your code in User model
}
as explained in the documentation here. Now you can get the name of the user that the post is belonged to each post.
Define the route as
Route::get('/all-posts','PostController#getAllPosts')->name('get_all_posts');
Write the controller class to get the posts
class PostController extends Controller
{
public function getAllPosts() {
$posts = Posts::all();
foreach ($posts as $post){
$username = $post->user->name;
//do something with $username
}
return view('all_posts')->with('detailed_posts');
//here the $detailed_posts can be defined in the 'do something' above
}
}
Here at do something you can create a new array of username and pass it to the view,
or
set the PostController as,
class PostController extends Controller
{
public function getAllPosts() {
return view(all_posts);
}
}
and then set the all_posts.blade.php to directly access the username in the view using blade syntax as follow ,
<html>
<div>
<h1>All Posts</h1>
#foreach (App\Post::all() as $post)
<span> Title : {{ $post->title}}</span>
<span> Username: {{$post->user->name}}</span>
.......
#endforeach
</div>
</html>
To set up the relationship for the Users -> Posts, then you can use hasMany
public function posts(){
return $this->hasMany('App\Post');
}
This will look for any user_id on the posts table. If it's named differently, then you can pass it in as the second parameter.
public function posts(){
return $this->hasMany('App\Post', name_of_column_in_post_table, name_of_column_in_user_table);
}
In the posts table, you want either hasOne or belongsTo. Both work the same way:
public function users() {
return $this->belongsTo('App\User', name_of_column_in_user_table, name_of_column_in_post_table);
}
You can then get the user information by doing $post->user->name
In the Model Class add the Relation like
Class Posts Extends Eloquent{
protected $table = 'posts';
protected $fillable = array('title, image, text, user_id');
public $timestamps = false;
public function user()
{
return $this->belongsTo('App\User','user_id);
}
}
Now in the controller or view in every instance of Post you can use:
By Example
$post->user
Read the documentation about many to one relationship and even eager loading.

Send user id and post id with comment

I am following a laravel tutorial and created a form to create a comment on a post with the user_id. I can't seem to understand how I pass the user_id.
Post Model
class Post extends Model
{
protected $guarded = [];
public function comments()
{
return $this->hasMany(Comment::class);
}
public function addComment($body)
{
$this->comments()->create(compact('body'));
}
public function user()
{
return $this->belongsTo(User::class);
}
}
CommentModel
class Comment extends Model
{
protected $guarded = [];
public function post()
{
$this->belongsTo(Post::class);
}
public function user()
{
$this->belongsTo(User::class);
}
}
User Model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function posts()
{
return $this->hasMany(Post::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function publish(Post $post)
{
$this->posts()->save($post);
}
}
CommentsController.php
class CommentsController extends Controller
{
public function store(Post $post)
{
$this->validate(request(), ['body' => 'required|min:2']);
$post->addComment(request('body'));
return back();
}
}
As you can see I call ->addComment in the Post Model to add the comment. It worked fine untill I added user_id to the Comments table. What is the best way to store the user id? I can't get it to work.
Update your addComment method :
public function addComment($body)
{
$user_id = Auth::user()->id;
$this->comments()->create(compact('body', 'user_id'));
}
PS : Assuming that the user is authenticated.
UPDATE
public function addComment($body)
{
$comment = new Comment;
$comment->fill(compact('body'));
$this->comments()->save($comment);
}
Create a new instance of the comment without savingit and you only need to save a comment in the post because a post already belongs to a user
There is no need to handle ids manually, let eloquent handle it for you:
$user = Auth::user(); // or $request->user()
$user->comments()->save(new Comment());
more information about saving eloquent models.

Dynamic Allow access to different permission rules - ACL LARAVEL

The admin user can view all posts on the homepage and access the update page for each post
$gate->before(function(User $user, $ability)
{
if ($user->hasAnyRoles('adm') )
return true;
});
This is ok
But I do not know what I am doing wrong in the policies because other users can see all posts at home page but can not access the post update page that they have created, access is denied.
The permissions are dynamic, I have the tables in the DB:
permissions
permission_role
posts
roles
role_user
users
Home Controller
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Post;
use Gate;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index(Post $post)
{
$posts = $post->all();
return view('home', compact('posts'));
}
public function update($idPost)
{
$post = Post::find($idPost);
if(Gate::denies('update-post', $post))
abort(403);
return view('update-post', compact('post'));
}
}
class AuthServiceProvider
<?php
namespace App\Providers;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Post;
use App\User;
use App\Permission;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
];
/**
* Register any application authentication / authorization services.
*
* #param \Illuminate\Contracts\Auth\Access\Gate $gate
* #return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
$permissions = Permission::with('roles')->get();
foreach( $permissions as $permission)
{
$gate->define($permission->name, function(User $user) use ($permission){
return $user->hasPermission($permission);
});
}
$gate->before(function(User $user, $ability)
{
if ($user->hasAnyRoles('adm') )
return true;
});
}
}
model User
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Permission;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function roles()
{
return $this->belongsToMany(\App\Role::class);
}
public function hasPermission(Permission $permission)
{
return $this->hasAnyRoles($permission->roles);
}
public function hasAnyRoles($roles)
{
if(is_array($roles) || is_object($roles)){
foreach($roles as $role){
return $roles->intersect($this->roles)->count();
}
}
return $this->roles->contains('name', $roles);
}
}
model Role
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function permissions()
{
return $this->belongsToMany(\App\Permission::class);
}
}
model Permission
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
public function roles()
{
return $this->belongsToMany(\App\Role::class);
}
}
view home.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
#forelse($posts as $post)
#can('view_post', $post)
<h2>{{$post->title}}</h2>
<p>{{$post->description}}</p><br>
<p>Autor: {{$post->user->name}}</p>
Editar
#endcan
<hr>
#empty
<p>No posts registered</p>
#endforelse
</div>
#endsection
view update-post.blade.php
#extends('layouts.app')
#section('content')
#can('edit_post', $post)
<div class="container">
<h2>{{$post->title}}</h2>
<p>{{$post->description}}</p><br>
<p>Autor: {{$post->user->name}}</p>
#endcan
#endsection
create a policy class:
php artisan make:policy PostPolicy --model=Post
than in your AuthServiceProvider register the policy:
protected $policies = [
Post::class => PostPolicy::class,
];
than in PostPolicy update method do this:
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
you made a mistake in your home controller.
if(Gate::denies('update-post', $post))
{
abort(403);
}
or you can do the same in a single line:
$this->authorize('update-post', $post);
or using can middleware:
if ($user->can('update-post', $post)) {
return view('update-post', compact('post'));
}

how to join two models in laravel 5.2

I have two models as Project and Collaborator this is My tables
Project column
id
project_name
project_note
user_id
Collaborator Model
id
project_id
collaborator_id
I need join this models to get project_name instead project_id of Collaborator Model.
how can I do this. I read www.laravel.com documents but difficult to understand. help me in code...
project Model
<?php
namespace App;
use Auth;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
/*
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['project_name', 'project_notes', 'project_status', 'due_date'];
public function scopePersonal($query)
{
return $query->where('user_id', Auth::user()->id);
}
//
}
collaborator Model
<?php
namespace App;
use Auth;
use Illuminate\Database\Eloquent\Model;
class Collaboration extends Model
{
protected $table = 'project_collaborator';
/*
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['project_id', 'collaborator_id'];
/*
* Get the user that is a collaborator on another project
* #return collection
*/
public function user()
{
return $this->belongsTo(User::class, 'collaborator_id');
}
/*
* Query scope to return information about the current project
* #param $query
* #param int $id
* #return query
*/
public function scopeProject($query, $id)
{
return $query->where('project_id', $id);
}
public function scopeColabo($query)
{
return $query->where('collaborator_id',Auth::user()->id);
}
}
Based on your comment, you need to add a relationship hasOne to your collaboration model:
class Collaboration extends Model
{
.....
public function project()
{
return $this->hasOne('App\Project');
}
.....
}
The method project() will define your relationship with your project model. And then you'll be able to get the collaboration project name like this:
$collaborations = Collaboration::with('project')->get();
foreach ( $collaborations as $collaboration ) {
echo $collaboration->project->project_name;
}
You can read more in the documentation.
In your Collaboration class add the followoing relation:
public function project()
{
return $this->belongsTo('App\Project');
}
And in your User class define a relation as:
public function collaborations()
{
return $this->hasMany('App\Collaboration', 'collaborator_id');
}
Then you can get all the collaborations of logged in user by:
$collaborations = auth()->user()->collaborations()->with('project')->get()
or
To get all collaborations you can so as:
$collaborations = Collaboration::with('project')->get();
In your view file:
#foreach ($collaborations as $collaboration)
{{ $collaboration->project->project_name }}
#endforeach

Categories