Undefined method 'posts' inside controller - Laravel - laravel

I am getting error for undefined method which is defined inside my User model.
My controller:
$inputs = request()->validate([
'title' => 'required|min:8|max:255',
'post_image' => 'file',
'body' => 'required'
]);
auth()->user()->posts()->create($inputs);
My Post model:
public function user() {
return $this->belongsTo('App\Models\User');
}
My User model:
public function posts() {
return $this->hasMany('App\Models\Post');
}

correct your relationship
public function posts() {
return $this->hasMany(Post::class);
}

First your posts relationship is wrong, it must be hasMany NOT belongsTo
public function posts() {
return $this->hasMany(User::class);
}
Then it should work.
You can also try to create the model in a different way:
$validated = request()->validate([
'title' => 'required|min:8|max:255',
'post_image' => 'file',
'body' => 'required'
]);
// Here you should check if $validated has all required fields
// because some could fail, in that case aren't in the array
Post::create([
'title' => $validated['title'],
'user_id' => auth()->id, // or auth()->user->id
'post_image' => $validated['post_image'],
'body' => $validated['body'],
]);
Laravel Validation Docs

Related

Laravel: "Trying to get property 'comments' of non-object"

I setup an api resource collection for the post model, called PostCollection. I have a problem with my comments query for a post. Getting non-object for $comments. The comment table currently has no records.
$author = \App\Post::find(1);
$comments = \App\Post::find(1)->comments;
return [
'id' => $this->id,
'user_id' => $this->user_id,
'description' => $this->description,
'media' => $this->media,
'media_type' => $this->media_type,
'likes' => $this->likes,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'author_avatar' => $author->setting->user_profile_photo,
'author_profile_name' => $author->name,
'author_user_name' => $author->setting->user_name,
'visible' => true,
'comments' => $comments,
];
In the post model, I have:
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
In the comment model I have:
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
You should this
public function comments()
{
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
}
in your controller
$post = \App\Post::find(1);
$comments = $post->comments;

How to handle nested relation in laravel resource - 2

So I've been trying to get a second level relation out of my "CategoryResource" but it's not working, here is some of my code :
First, My model :
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id');
}
public function sub_children()
{
return $this->hasMany(Category::class, 'parent_id');
}
and then the "CategoryResource" :
$data = [
'id' => $this->id,
'parent_id' => $this->parent_id,
'order' => $this->order,
'name' => $this->name,
'slug' => $this->slug,
'childs' => CategoryResource::collection($this->whenLoaded('children') && $this->whenLoaded('children')),
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
My Controller
return CategoryResource::collection(Category::where('parent_id',null)->with('children.sub_children')->get());
Is there anyway i can retrieve my nested relation through laravel resource ?
You could use with function in the relationship. It would be something like this:
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id')
->with('children');
}
It is going to load the children and then "subChildren" as relations of the first object.
So, you are going to load it as:
$children = $originalObject->children;
foreach ($children as $c) {
$subChildren = $c->children;
}
Check if this works for your problem.

Call to undefined method App\User::events()

I am trying to store data into the database, but the error I'm getting is:
Call to undefined method App\User::events()
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'slug' => 'required|unique:events',
'body' => 'required',
'date' => 'date_format:M-d-y H:i:s',
'time' => 'required'
]);
$request->user()->events()->create($request->all());
return redirect('/backend/blog')->with('message', 'Your event was created successfully');
}
Try this:
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'slug' => 'required|unique:events',
'body' => 'required',
'date' => 'date_format:M-d-y H:i:s',
'time' => 'required'
]);
$user = User::create($request->all()); // create the user
event(new UserRegistered($user)); // Add your own event class name.
return redirect('/backend/blog')->with('message', 'Your event was created successfully');
}
Note: Assuming that you have created the UserRegistered event. And call it by event helper method.
It seems like you do not have any events() relationship in you User model.
Assuming you have Event model, you can write like in User model:
public function events()
{
return $this->hasMany(Event::class);
}

Returning laravel realtionship within json

I am currently doing this as title says like this:
$user = User::where('username', request('username'))->first();
$posts = [];
$comments = [];
foreach($user->posts as $post){
foreach($post->comments as $comment){
array_push($comments, [
'id' => $comment->id,
'body' => $comment->body,
'user' => $comment->user->only(['name', 'id']),
]);
}
array_push($posts, [
'title' => $post->title,
'id' => $post->id,
'body' => $post->body,
'comments' => $comments,
]);
}
return response()->json([
'user' => $user->only(['name', 'avatar', 'age']),
'posts' => $posts,
]);
Is there a shorter way of doing this like:
$user->only(['name', 'avatar', 'age'])->withPostsOnly(['id', 'title', 'body'])->withCommentsOnly(['id', 'body']);
I know there is a way to make methods inside models that return these parts of data and then to use it same as above but shorter.
But is there any way to use something like getNameAttribute($value) for relations so I can say:
$user->only(['id', 'name', 'age', 'posts']);
And in posts value I need to have all posts and relationship data like comments and users that are connected to comments.
So basically in User model:
public function posts() {
return $this->hasMany('App/Post')->only('id', 'title', 'body', 'comments');
}
And inside Post model:
public function comments() {
return $this->hasMany('App/Comment')->only('id', 'body', 'user');
}
And inside Comment model:
public function comments() {
return $this->belongsTo('App/User')->only('id', 'name');
}
Thanks
You are probably overcomplicating it to be honest.
$user = User::where('username', request('username'))->first();
$user->load(['posts.comments']);
return response()->json($user);
This is a simplified version maybe but still should indicate you can just load relationships on models.

Store belongsToMany relationships w/ Conditions - Laravel

I have the following tables for my many to many relationship: soldhomestests, tasks and soldhomestest_task (as the pivot).
My soldhomestests table has already been populated with data. How do I get my soldhomestest_task pivot table to populate with data upon the creation of a new task that meets conditions in my soldhomestest table? In my example, I want to store the relationship data when the following conditions are met:
'tasks.city' = 'soldhomestests.city'
'tasks.address' = 'soldhomestests.address'
I can't seem to find any documentation on how to proceed with this?
MODELS:
class Task extends Model
{
protected $fillable = [
'address', 'city', 'state',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function soldhomestests()
{
return $this->belongsToMany('App\Soldhomestest');
}
}
class Soldhomestest extends Model
{
public function tasks()
{
return $this->belongsToMany('App\Task');
}
}
CONTROLLER:
public function store(Request $request)
{
$this->validate($request, [
'address' => 'required|max:255',
'city' => 'required|max:255',
'state' => 'required|max:255',
]);
$request->user()->tasks()->create([
'address' => $request->address,
'city' => $request->city,
'state' => $request->state,
]);
return redirect()->route('settings.index');
}
Don't believe this is the Laravel way but I modified my controller to create an array of IDs using the where condition:
public function store(Request $request)
{
$this->validate($request, [
'address' => 'required|max:255',
'city' => 'required|max:255',
'state' => 'required|max:255',
]);
$newtask = $request->user()->tasks()->create([
'address' => $request->address,
'city' => $request->city,
'state' => $request->state,
]);
$condition = DB::table('soldhomestests')->where([
['soldhomestests.address', '=', $request->address],
['soldhomestests.city', '=', $request->city],
])->pluck('id');
$lastid = $newtask->id;
$tasksoldhome = Task::find($lastid);
$tasksoldhome->soldhomestests()->sync($condition);
return redirect()->route('settings.index');
}
Using eloquent, you can do this way.
$task=new Task();
$task->city=$request->city;
$task->address=$request->address;
$task->save();
$soldhometests=Soldhometest::all();
foreach($soldhometests as $soldhometest)
{
if($task->city==$soldhometest->city && $task->address==$soldhometest->address)
{
$soldhometest_task=new SoldhometestTask(); // pivot model
$soldhometest_task->task_id=$task->id;
$soldhometest_task->soldhometest_id=$soldhometest->id;
$soldhometest_task->save();
}
}

Resources