Search code examples
phplaravellaravel-5

How do i fix this error i'm getting "Sorry, the page you are looking for could not be found."


I have this application where I am trying to get the the author of a question to be able to mark an answer as the best answer.

I have an AcceptAnswerController created which has been registered in the routes/web.php file as below:

AcceptAnswerController.php

class AcceptAnswerController extends Controller
{
    public function __invoke(Answer $answer) 
    {
        $this->authorize('accept', $answer);

        $answer->question->acceptBestAnswer($answer);
        return back();
    }
}

web.php

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::resource('questions', 'QuestionsController')->except('show');

Route::resource('questions.answers', 'AnswersController')->only(['store', 'edit', 'update', 'destroy']);

Route::get('questions/{slug}', 'QuestionsController@show')->name('questions.show');

Route::post('answers/{answer}/accept', 'AcceptAnswerController')->name('answers.accept');

In my Answers view, i have the following:

<div class="row mt-4">
    <div class="col-md-12">
        <div class="card">
            <div class="card-body">
                <div class="card-title">
                    <h2>{{ $answersCount . " " . str_plural('Answer', $answersCount) }}</h2>
                </div>
                <hr>
                @include ('layouts._messages')

                @foreach ($answers as $answer)
                    <div class="media">
                        <div class="d-fex flex-column vote-controls">
                            <a title="This answer is useful" class="vote-up">
                                <i class="fas fa-caret-up fa-3x"></i>
                            </a>
                            <span class="votes-count">1230</span>
                            <a title="This answer is not useful" class="vote-down off">
                                <i class="fas fa-caret-down fa-3x"></i>
                            </a>
                            @can ('accept', $answer)
                                <a title="Mark this answer as best answer" 
                                    class="{{ $answer->status }} mt-2"
                                    onclick="event.preventDefault(); document.getElementById('answer-{{ $answer->id }}').submit();"
                                    >
                                    <i class="fas fa-check fa-2x"></i>                                    
                                </a>
                                <form id="answer-{{ $answer->id }}" action="{{ route('answers.accept', ['answer' => $answer->id]) }}" method="POST" style="display:none;">
                                    @csrf
                                </form>
                            @else
                                @if ($answer->is_best)
                                    <a title="The question owner accepted this answer as best answer" 
                                        class="{{ $answer->status }} mt-2"                                        
                                        >
                                        <i class="fas fa-check fa-2x"></i>                                    
                                    </a>
                                @endif
                            @endcan
                        </div>
                        <div class="media-body">
                            {!! $answer->body_html !!}
                            <div class="row">
                                <div class="col-4">
                                    <div class="ml-auto">
                                        @can ('update', $answer)
                                            <a href="{{ route('questions.answers.edit', ['question' => $question->id, 'answer' => $answer->id]) }}" class="btn btn-sm btn-outline-info">Edit</a>
                                        @endcan
                                        @can ('delete', $answer)
                                            <form class="form-delete" method="post" action="{{ route('questions.answers.destroy', [$question->id, $answer->id]) }}">
                                                @method('DELETE')
                                                @csrf
                                                <button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure?')">Delete</button>
                                            </form>
                                        @endcan
                                    </div>
                                </div>
                                <div class="col-4"></div>
                                <div class="col-4">
                                    <span class="text-muted">Answered {{ $answer->created_date }}</span>
                                    <div class="media mt-2">
                                        <a href="{{ $answer->user->url }}" class="pr-2">
                                            <img src="{{ $answer->user->avatar }}">
                                        </a>
                                        <div class="media-body mt-1">
                                            <a href="{{ $answer->user->url }}">{{ $answer->user->name }}</a>
                                        </div>
                                    </div>
                                </div>
                            </div>                            
                        </div>
                    </div>
                    <hr>
                @endforeach
            </div>
        </div>
    </div>
</div>

Once the author of the question clicks on the check icon, it should mark the answer as the best answer but i get the following error:

Sorry, the page you are looking for could not be found

I see that the answer id is missing in the url as follows:

http://localhost:8000/answers//accept

when it should actually be something like this:

http://localhost:8000/answers/1/accept

I can't seem to figure out why as i passed it as a route parameter in the form action. Same thing happens if a user is trying to edit his answer.


Solution

  • So, after scrutinizing my code a bit more carefully everything else seemed okay the controller, routes, views. I was able to isolate the problem down to this region

    @can ('accept', $answer)
     <a title="Mark this answer as best answer" 
       class="{{ $answer->status }} mt-2"
      onclick="event.preventDefault(); document.getElementById('answer-{{ $answer->id }}').submit();"
                                       >
        <i class="fas fa-check fa-2x"></i>                                    
     </a>
     <form id="answer-{{ $answer->id }}" action="{{ route('answers.accept', ['answer' => $answer->id]) }}" method="POST" style="display:none;">
         @csrf
     </form>
    @endcan
    

    I was certian the $answer->id was supposed to return the correct id but i wasn't too sure about the $answer->status so I decided to check its accessor defined in the Answer model.

    public function getStatusAttribute()
    {
       return $this->isBest() ? 'vote-accepted' : '';
    }
    
    public function isBest()
    {
       return $this->id = $this->question->best_answer_id; /** here is the problem **/
    }
    

    There the problem was staring right back at me. The isBest method above was supposed to return a boolean value but i was mistakingly assigning. This was the simple fix.

    public function isBest()
    {
       return $this->id === $this->question->best_answer_id; /** here is the problem **/
    }