Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mstnorris's avatar

How to go to specific ?page where Post is located (marked as answer)

Once a Post is marked as the accepted answer to a Thread, I want to display a link directly to that answer even if it is located say on page 3. Is this possible?

So far I have this bit of dirty inlining to check if has been answered

<div class="panel {{ $thread->is_question ? $thread->answer_id ? 'panel-success' : 'panel-info' : 'panel-default' }}">

I want to do something like the following:

@if ( $thread->answer_id )
    <div class="media-right">
        <a href="#link_to_answer_here"><i class="fa fa-check fa-5x text-success"></i></a>
    </div>
@endif
0 likes
35 replies
mstnorris's avatar

@JarekTkaczyk to me it is just a nested if statement. Is there a better way to do it?

I'm confused about your method here

// Post model (question)
public function markedAnswer()
{
    return $this->hasOne(Answer::class)->where('is_marked', true);
}

I'm using it like so...

public function markedAnswer()
{
    return $this->hasOne('App\Post')->whereNotNull('answer_id');
}

I have two models Thread and Post

Thread hasMany Post.

On the Thread table, there is an answer_id field which holds a Post id.

I am living proof that there is a need for your book!

JarekTkaczyk's avatar

@mstnorris Yeah, it's something like nested if statement. However it works (or at least looks) a bit unpredictably, unless you use parentheses:

echo true ? 'true' : false ? 'false and true' : 'false and false'; // prints 'false and true'
// while you would probably expect it to print 'true'

// this is because default behaviour read the statements from left to right, not nested, just like here:
echo (true ? 'true' : false) ? 'false and true' : 'false and false'; // prints 'false and true'

// so make it clear by adding parentheses
echo true ? 'true' : (false ? 'false and true' : 'false and false');
// or even
echo (true ? 'true' : (false ? 'false and true' : 'false and false'));
mstnorris's avatar

@JarekTkaczyk to me it is clear as both the first two statements are the questions

 $thread->is_question ? $thread->answer_id ? 'panel-success' : 'panel-info' : 'panel-default'

So it translates to

if ( $thread->is_question )
{
    if ( $thread->answer_id )
    {
        // Question has been answered
    } else {
        // Question hasn't been answered
    }
} else {
    // Not a question
}
JarekTkaczyk's avatar

@mstnorris Yes, this one is OK, bc you have X ? Y ? 1 : 2 : 3. It's quite different if you have X ? 1 : Y ? 2 : 3 - that's why I'm saying be careful - such things may waste your time one day, that's all ;)

mstnorris's avatar

Yes I know, the example you linked to made no sense to ever write that. I hope mine is a little clearer.

Would you please clarify what I need to do to retrieve the correct answer for my Thread?

mstnorris's avatar

I get this error:

Object of class Illuminate\Database\Eloquent\Relations\HasOne could not be converted to string (View: /home/vagrant/Code/laravel/myproject/resources/views/forum/index.blade.php)

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'll' in 'where clause' (SQL: select * from `posts` where `posts`.`thread_id` = 38 and `ll` = answer_id limit 1) (View: /home/vagrant/Code/laravel/getwhiteboard/resources/views/forum/index.blade.php)

What is confusing me is that I added the markedAnswer method to the Thread model.

Thread table

is_question -> boolean answer_id -> integer (relates to post table)

Should the markedAnswer method be on the Post model?

mstnorris's avatar
<div class="panel-footer">
    {!! link_to_action('DiscussionsController@show', $thread->posts->count() . ' replies', $thread->id) !!}
    {!! $thread->answer_id ? link_to_route('show_answer_path', 'Go to Answer', $thread->markedAnswer) : null !!}
    <span class="pull-right">
        Posted by {!! link_to_action('UsersController@show', $thread->user->name, $thread->user->id) !!} {{ $thread->created_at->diffForHumans() }}
    </span>
</div>
JarekTkaczyk's avatar

@mstnorris OK, now it's clear. I made an assumption about your setup writing my code above, and apparently I was wrong.

Since thread has foreign key referencing posts table, this is belongsTo:

// thread
public function markedAnswer()
{
    return $this->belongsTo('app\Post', 'answer_id');
}

Now, it will work without errors, just change it a bit for more reliable check:

    {!! $thread->markedAnswer ? link_to_route('show_answer_path', 'Go to Answer', $thread->markedAnswer) : null !!}

Just remember to eager load the markedAnswer relation on the threads ;)

mstnorris's avatar

Thank you. As my posts are paginated, how do I go to the specific answer?

JarekTkaczyk's avatar

@mstnorris That depends :)

You can go to the page with that answer (I prefer this one):

/threads/{id/slug/whatever}?page=2#html_anchor_for_the_answer

you can show only the answer you want

/threads/{id/slug/whatever}/{answer_id/slug/whatever}

Of course the uri can be whatever you like.

mstnorris's avatar

@JarekTkaczyk I'm not sure how to get the ?page part. I prefer your one too, I don't need to show just the answer as it most likely won't make sense outside of the discussion. And I know the $post->id, so my question is, how do I know what page the answer (post) is on?

JarekTkaczyk's avatar
Level 53

@mstnorris Where do you get $post->id from? I suppose you have it from the discussion, so the page will be accessible there as well.

Otherwise you would need a query for this. I assume you want to sort by the created_at desc timestamp:

// example controller
public function showAnswer($id)
{
    $post = Pot::find($id);
    $page = $post->thread->posts()
        ->latest()
        ->selectRaw('ceil(count(*) / ?) as page', [$perPage])
        ->where('created_at', '>=', $post->created_at)
        ->pluck('page');

    $anchor = $post->...; // get the html anchor of the answer, id or whatever you use

    return redirect("/url_to_the_current_thread?page={$page}#{$anchor}");
    // the url might be something like "/threads/{$post->thread_id}?page..."
}
mstnorris's avatar

Sorry for all the questions, where should that go? In my DiscussionsController I have created a showAnswer method so I have put it in there.

But how do I show the answer? What do I need to return from that method?

Also, if what I've done above isn't correct please tell me.

Thanks again.

mstnorris's avatar

Where do I get $thread from? - I get Undefined variable.

The $id passed to the showAnswer($id) method I assume is the id of the Post (answer)?

JarekTkaczyk's avatar

@mstnorris You tell me! :) Yeah, you said you had only post's id, so I suppose this is it. And the thread - you don't need it at all, right? Just its url. Anyway you surely have a relation between the post and thread, so use it. Thread is already there.

JarekTkaczyk's avatar

@mstnorris well.. obviously ;) Too many of these posts here already. Just get it from the relation - edited above.

mstnorris's avatar

@JarekTkaczyk I'm really sorry, I feel stupid. I have this

{!! $thread->markedAnswer ? link_to_action('DiscussionsController@showAnswer', 'Go to Answer', $thread->markedAnswer) : null !!}

Which produces a link, but it just links to /discussion/{$post->id} (it is missing the thread->id.

JarekTkaczyk's avatar

@mstnorris You don't need that, do you? Just grab the post with this id, get the thread from it, get the page and redirect to the actual show thread action - just like I showed. I'm going to sleep now :)

mstnorris's avatar

@JarekTkaczyk just to let you know, this is what I went for.

I swapped latest() to oldest() as most forums show the oldest posts first.

I also removed the where clause as (a) it didn't work with it and (b) it seems redundant even if it did... ??

public function showAnswer($thread_id, $answer_id)
    {
        $perPage = 12;
        $post = Post::find($answer_id);
        $thread = Thread::find($thread_id);
        $page = $thread->posts() //
            ->oldest()
            ->selectRaw('ceil(count(*) / ?) as page', [$perPage])
            // ->where('created_at', '>=', $post->created_at) // not necessary as we're ordering by the oldest already
            ->pluck('page');

        $anchor = $post->id; // get the html anchor of the answer, id or whatever you use

    return redirect("/discussion/$post->thread_id/?page={$page}#{$anchor}");
    // the url might be something like "/threads/{$post->thread_id}?page..."
    }

Thank you again for all your help.

mstnorris's avatar

@JarekTkaczyk sorry to bother you but it doesn't work in all cases. Sometimes it takes me to the wrong page, but I am unable to determine where.

What is your opinion on the following?

Should I try and determine what page the answer is on, or, should I always show the answer right underneath the question like they do here? That way I don't need to both with where exactly it is.

JarekTkaczyk's avatar

@mstnorris This where that you ommented out was rather crucial.. It is the one that gets the page for you, otherwsie all you're getting is the last page.

So tell me what happened there.

Next

Please or to participate in this conversation.