SS54's avatar
Level 1

Why I am getting the error: Trying to get property 'id' of non-object (View: C:\xampp\htdocs\cms\resources\views\posts\edit.blade.php)

When I went to create the edit functionality with (Laravel 8) I faced the the above said error for the first time. It seems from googling that I am not the only one to have been facing this error, and it was not a straight forward problem to solve. Each case has it is own individual case and so it required its own relevant solution. I would extremely thankful for assistances from more experienced users and I would appreciate it so much.

show.blade.php

@extends('layouts.app')

@section('content')
<a href="/posts" class="btn btn-danger">Go Back</a>
<h3>{{$post->title}}</h3>

<div>

  {!! $post->content !!}

</div>
<hr>
<small>written on {{$post->created_at}}</small>
<hr>
 <a href="/posts/{{$post->id}}/edit" class="btn btn-primary">Edit</a>
@endsection

Edit.blade.php

@extends('layouts.app')

@section('content')

    {!! Form::open(['action' => ['PostsController@update', $post->id], 'method'=>'POST']) !!}

    <div class="form-group">
      {{Form::label('title', 'Title')}}
      {{Form::text('title', $post->title, ['class'=>'form-control', 'placeholder'=>'title'])}}
  </div>

  {!! '<br>' !!}

  <div class="form-group">
    {{Form::label('body', 'Body')}}
    {{Form::textarea('body', $post->content, ['class'=>'form-control ckeditor', 'placeholder'=>'content'])}}
</div>

{{Form::hidden('_method', 'PUT')}}
{!! Form::submit('Submit', ['class'=>'btn btn-primary']) !!}
{!! Form::close() !!}

   @endsection	

PostsController.php

public function show($id)
    {
       $post = Post::find($id);
       return view('posts.show')->with('post', $post);
    }

 public function edit($id)
    {

        $post = Post::find($id);
        return view('posts.edit')->with('post', '$post');
    } 

public function update(Request $request, $id)
    {
        Return "Update";
    }

Post.php Model

<?php

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
}
0 likes
11 replies
mabdullahsari's avatar

Post::find($id) cannot find a model most probably. You need to bail out if no model can be found.

Post::findOrFail($id)

Use implicit route model binding and you don't have to worry about it:

 public function edit(Post $post)
    {
        return view('posts.edit')->with('post', '$post');
    } 
1 like
tykus's avatar

@SS54 if you use Route Model binding as described above; then your route definition wildcard {post} must match the method parameter $post; and you do not need an id:

Route::get('posts/{post}/edit', [PostController::class, 'edit']);

As you see from @mabdullahsari suggestion, there is no explicit Eloquent query because this is handled by the Route-Model binding.

 public function edit(Post $post)
{
    return view('posts.edit')->with('post', '$post');
} 
1 like
SS54's avatar
Level 1

@tykus In the edit.blade file I replaced the action with Route as

 {{-- {!! Form::open(['action' => ['PostsController@update', $post->id], 'method'=>'POST']) !!} --}}
    {!! Form::open(['route' => 'posts.update', $post->id]) !!}

and changed the PostsController to

public function edit(Post $post)
    {

        $post = Post::find($id);
        return view('posts.edit')->with('post', '$post');
    }

and added to the web.php the following route get statement

Route::get('posts/{posts}/edit', [App\Http\Controllers\PostsController::class, 'edit']);

But it did not work. Am I missing something?

tykus's avatar

@ss54 what did not work; are you not seeing the edit page?

What is $post->id; is it a valid (a record existing in the database) Post?

SS54's avatar
Level 1

@tykus It is giving the same error Trying to get property 'id' of non-object Yes the $post->id is a record existing in the database Yes I am not seeing the editing page

tykus's avatar

@SS54 did you read my post earlier about the edit action? You **do not ** need an explicit Eloquent query:

public function edit(Post $post)
{
    // $post = Post::find($id);
    return view('posts.edit')->with('post', $post);
}

Also, note that '$post' is not the variable; it is a String!!! If you send a String to the view, then $post will be the literal string "$post" and therefore not an Object

mabdullahsari's avatar

@tykus The string is my bad, lol. Seems like I derped.

@ss54 The route still doesn't have a 'post' defined as a route parameter, you're using posts as plural.

tykus's avatar

@mabdullahsari good catch... @ss54 I did mention this already...

if you use Route Model binding as described above; then your route definition wildcard {post} must match the method parameter $post

SS54's avatar
Level 1

@tykus inspired by your reply and also by @mabdullahsari I was able to solve it by replacing

{!! Form::open(['route' => 'posts.update', $post->id]) !!} 

with

    <form action="/posts/{{$post->id}}" method="post">
        @csrf
        @method('PUT')

and also I replaced:

 public function edit(Post $post)
 {
$post = Post::find($id);
return view('posts.edit')->with('post', $post);
}

with

public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }

But I really could not understand why we are using edit(Post $post) and not edit($id) in in the PostsController, how we could find the id without using the find() function Now I can see the edit page perfectly with recod populated

tykus's avatar
tykus
Best Answer
Level 104

@SS54 I mentioned Route Model Binding a number of times already... I thought it might prompt you to read the relevant docs.

TLDR; It is such a common pattern to fetch a model using the URL's wildcard segment, that the framework can handle this for you. It saves you one line of code (the find operation), but also throws the appropriate exception for an invalid id. Altogether, this makes you application code more readable; and your application more tolerant to exceptional behaviour.

Otherwise, if you're all set, please mark the thread closed

1 like

Please or to participate in this conversation.