method setAuthorIdAttribute is not called - php

I have a Post model with a setAuthorIdAttribute method used for setting the post author id with the id of the logged user.
class Post extends Model
{
protected $fillable = ['title', 'subtitle', 'slug', 'content', 'draft', 'author_id', 'category_id'];
/**
* An post belongs to an author
*/
public function author()
{
return $this->belongsTo('App\User');
}
// Some code here...
/**
* Add the author of the post
*/
public function setAuthorIdAttribute($value)
{
return $this->attributes['author_id'] = Auth::id();
}
}
I create my Post with this :
public function store(Request $request)
{
$post = Post::create($request->all());
return redirect()->route('posts.show', ["post" => $post]);
}
When I put a dd() inside the setAuthorIdAttribute nothing happen. Why ?

You can set the attribute value in model using models boot method something like:
public function boot()
{
Model::creating(function ($model)
return $model->attributes['author_id'] = Auth::id();
});
Model::updating(function ($model)
return $model->attributes['author_id'] = Auth::id();
});
}
This will fill author_id attribute with Auth::id() on each create and update event of this model.

Related

Laravel Eloquent get all Posts stored in categories with Roles

I have four tables in a database named: Category, User, Role and then Post. In the Category table I have a column category_id which by this column i can have multiple child in category.
Every user belongsToMany roles and categories and each category belongsToMany posts, i must get all posts by role which logged into our application
As you can see in below screen shot manager 1 and manager 2 belongsToMany programings, dart, flutter and php.
you can suppose manager 1 user id is 1 and manager 2 is 2 and both of them are manager role
my question is how can i get all posts which logged user belongsToMany categories by role
logged user is manager 1 and i want to get all posts which saved into categories from parent which that's PROGRAMINGS
for example:
$categories = Category::whereNull('category_id')->whereHas('users.roles', function($q){
return $q->whereLabel('is-manager');
})->with(['posts' => function ($query) {
$query->with('language');
}])->get();
dd($categories->pluck('posts'));
NOTE:
with #Med.ZAIRI answer which posted on this thread every user in MANAGER 2 which is't synced into MANAGER 1, can see all of MANAGER 1 posts
In the Model Category add a relationship, like:
/**
* this will get the parent category
*/
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
Then, try to get Posts with their categories and their parent
Categories, and the users with their Roles, like:
$posts = Post::with( ['category.parentCategory', 'user.roles'])->get()
my used models in this senario:
class Category extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected $hidden = ['id', 'category_id'];
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
public function categories()
{
return $this->hasMany(Category::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function posts()
{
return $this->belongsToMany(Post::class);
}
public function users()
{
return $this->belongsToMany(User::class);
}
public function childrenCategories()
{
return $this->hasMany(Category::class)->with('categories');
}
}
class Role extends Model
{
protected $guarded = ['id'];
public function users()
{
return $this->belongsToMany(User::class);
}
public function permission()
{
return $this->belongsToMany(Permission::class);
}
public function hasPermission($permission)
{
return !!$permission->intersect($this->roles->permission)->count();
}
}
class User extends Authenticatable
{
use Notifiable, SoftDeletes, UsersOnlineTrait;
protected $guarded = [
'id',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'avatar_path' => 'array',
'experiences' => 'array',
];
public function group()
{
return $this->belongsToMany(UserGroup::class, 'user_user_group');
}
public function child()
{
return $this->hasMany(User::class)->with('child');
}
public function parent()
{
return $this->belongsTo(User::class, 'user_id');
}
public function properties()
{
return $this->hasOne(UsersProperty::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function hasRole($role)
{
return $this->roles->contains('id', $role);
/*if (is_string($role)) {
} else {
return !!$role->intersect($this->roles)->count();
}*/
}
public function hasRoleByName($role)
{
if ($role == null) return false;
if (is_string($role)) {
return $this->roles->contains('name', $role) || $this->roles->contains('label', $role);
} else {
return !!$role->intersect($this->roles)->count();
}
}
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
In the Model Category add a relationship, like:
/**
* this will get the parent category
*/
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
Then, try to get Posts with their categories and their parent Categories, and the users with their Roles, like:
$posts = Post::with( ['category.parentCategory', 'user.roles'])->get()
Trait with methods to get all available posts for the logged in user
based on the role
class User extends Model
{
use HasFactory, Notifiable, HasPosts;
}
<?php
namespace App\Concerns;
use App\Models\Category;
use Illuminate\Support\Str;
use Illuminate\Support\Collection;
trait HasPosts
{
/**
* Get all available posts for the currently logged in user
*
* #return void
*/
public function posts()
{
$method = 'postsFor' . Str::studly(str_replace('is-', '', $this->roles->first()->label));
return $this->{$method}()->collapse();
}
/**
* Get all posts associated with all categories including
* their subcategories for the logged in Portal Manager
*/
public function postsForPortalManager(): Collection
{
return Category::with([
'subcategories.posts.language',
'posts.language'
])
->get()
->pluck('posts');
}
/**
* Get all posts for the logged in Manager which belong to
* one of the categories associated with the Manager
*/
public function postsForManager(): Collection
{
return $this->categories()
->with('posts.language')
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
/**
* Get only the posts which belong to the categories for the Editor
* and which are authored by the logged in Editor
*/
public function postsForEditor(): Collection
{
return $this->categories()
->with([
'posts' => function ($query) {
$query->where('user_id', $this->id)->with('language');
},
'posts.language'
])
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
/**
* Get only the posts which belong to the categories for the Writer
* and which are authored by the logged in Writer
*/
public function postsForWriter(): Collection
{
return $this->categories()
->with([
'posts' => function ($query) {
$query->where('user_id', $this->id)->with('language');
},
'posts.language'
])
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
}
Then for any authenticated user we can fetch available posts with
$user->posts()
It works with the seed data you have provided.
ella is not able to see the post on Flutter and scarlett is not able to see the post on laravel
Only assumption here is that have taken the first role of the authenticated user to lookup the method used.
Add this to your roles model:
public function categories()
{
return $this->hasMany(Category::class);
}
After that you can reach posts from the user, like:
$authorizedUser->roles()->with('categories.posts')->get();
You can flatten the result to access posts directly as well
If your relationships are all many-to-many as below:
roles >-< users >-< categories >-< posts
and are all defined properly in the models, e.g.
// Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
// User.php
public function categories()
{
return $this->belongsToMany(Category::class);
}
// Category.php
public function posts()
{
return $this->belongsToMany(Post::class);
}
then I'm pretty sure you should be able to do
$role = Role::find(1);
// get all posts from all categories from all users with $role
$posts = $role->users()->categories()->posts;

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.

Laravel ORM relationship method 'BelongsToMany' throwing error

Summary
I am receiving the following error when trying to call the relationship:
Object of class Illuminate\Database\Eloquent\Relations\BelongsToMany
could not be converted to string
My setup is very basic, and consists of two models, User and Role.
User Model [User.php]
<?php
use Illuminate\Auth\UserInterface;
class User extends Eloquent implements UserInterface {
protected $table = 'users';
protected $hidden = array('password');
protected $fillable = array('id', 'username', 'password');
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
}
Role Model [Role.php]
<?php
class Role extends Eloquent {
protected $table = "roles";
protected $fillable = array(
'id',
'code',
'name'
);
public function foo() {
return $this->belongsToMany('User', 'map_role_user', 'role_id', 'user_id');
}
}
And finally I'm calling the method foo in the routes file, example:
Route::get('role', function() {
return Role::find(1)->foo();
});
From
https://laravel.com/docs/5.3/eloquent-relationships or https://laravel.com/docs/4.2/eloquent#relationships
If a collection is cast to a string, it will be returned as JSON:
<?php
$roles = (string) User::find(1)->roles;
If you dont want to add further constraints to the query then you have to use dynamic properties concept. So,
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
If you want to add more constraints then do this
App\User::find(1)->posts()->where('title', 'LIKE', '%Best%')->get()

Categories