Unifx Unifx - 7 months ago 13
PHP Question

Laravel Stuck getting last user who posted in forum

So I have a basic forum set up and I have the relationships between models completed. However I am stuck trying to get the last user who posted in the sub category. This is how its laid out.

mysql tables
forum_category (this is used for the main category and also the sub category)
forum_post (this is used for the posts)

Here is my ForumCategory.php

namespace App\Models\Forum;
use Illuminate\Database\Eloquent\Model;

class ForumCategory extends Model {

protected $table = 'forum_category';

public static function category()
{
return ForumCategory::with('ForumSubCategory')->whereNull('parent_id')->get();
}
public function User()
{
return $this->belongsTo('App\User');
}
public function ForumSubCategory()
{
return $this->hasMany('App\Models\Forum\ForumSubCategory' , 'parent_id');
}
public function ForumPost()
{
return $this->hasMany('App\Models\Forum\ForumPost' , 'parent_id');
}
}


And here is my ForumSubCategory.php the sub category model even though they are using the same table...

namespace App\Models\Forum;

use App\User;
use Illuminate\Database\Eloquent\Model;

class ForumSubCategory extends Model
{
protected $table = 'forum_category';

public function ForumCategory()
{
return $this->belongsTo('App\Models\Forum\ForumCategory');
}
public function User()
{
return $this->belongsTo('App\User');
}
public function ForumPost()
{
return $this->hasMany('App\Models\Forum\ForumPost' , 'parent_id');
}
}


And here Is my ForumPost.php model

namespace App\Models\Forum;

use Illuminate\Database\Eloquent\Model;

class ForumPost extends Model
{
protected $table = 'forum_post';

public function User()
{
return $this->belongsTo('App\User');
}
public function ForumSubCategory()
{
return $this->belongsTo('App\Models\Forum\ForumSubCategory');
}
}


The controller is pretty basic, the index is

public function index() {
return view('forum.index', ['category' => ForumCategory::category()]);
}


Now at the moment I am currently getting my last user who posted with this

public static function LastPost($value)
{
$lastPost = ForumPost::whereParentId($value)->orderBy('created_at', 'DESC')->pluck('user_id')->first();
return User::whereId($lastPost)->pluck('username')->first();
}


Which I DO NOT want to do. I want to know the correct way of doing this :(

Here is my view

<ul>
@foreach ($category as $cat)
<li>
{{$cat->category_name}} - this is main category
{{$cat->category_description}} - this is main category description

@if ($cat->ForumSubCategory)
<ul>
@foreach ($cat->ForumSubCategory as $sub)
<li>
<a href="/forum/{{$cat->slug}}/{{$sub->slug}}"> - this is the category slug with the sub category slug
{{$sub->category_name}} - this is the sub category name
</a>
{{$sub->category_description}} - this is the sub category description
{{$sub->ForumPost->count()}} - this is how many posts are in the sub category
{{$sub->LastPost($sub->id)}} - this is how i am currently getting the last user who posted
</li>
@endforeach
</ul>
@endif
</li>
@endforeach
</ul>


Thanks for taking the time to look at this!

Answer

The fastest solution:

You can filter/order relationships, hence the function below.

latest() is an eloquent shortcut for orderBy('created_at','DESC')

ForumSubCategory Model:

class ForumSubCategory extends Model
{
    ...
    public function latestPost()
    {
        return $this->hasOne('App\Models\Forum\ForumPost' , 'parent_id')->latest()->with('user');
    }
}

In your view:

From:

{{$sub->LastPost($sub->id)}} - this is how i am currently getting the last user who posted

To:

@if($sub->latestPost) 
    @if($sub->latestPost->user)
        {{$sub->latestPost->user->username or 'Username not set'}}
    @else
       {{'User Not Found'}}
    @endif
@else 
   {{'No Last Post'}}
@endif

The most stable solution should be a service class around forum sub categories to take care of edge cases such as users being deleted, posts banned and so forth.