@tykus
model
<?php
/*
* Copyright (c) DeveloperZONE 2022.
*/
namespace App\Models;
use App\Filters\ForumFilters;
use Auth;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
class Discussion extends Model
{
protected $fillable = [
'title',
'content',
'user_id',
'channel_id',
'slug',
'count_replies',
];
protected $appends = ['short_content'];
public function channel(): BelongsTo
{
return $this->belongsTo(Channel::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function replies(): HasMany
{
return $this->hasMany(Reply::class);
}
public function watchers(): HasMany
{
return $this->hasMany(Watcher::class);
}
public function isBeingWatchedByAuthUser(): bool
{
$id = Auth::id();
$watchers_ids = [];
foreach ($this->watchers as $watcher) {
$watchers_ids[] = $watcher->user_id;
}
if (in_array($id, $watchers_ids, true)) {
return true;
}
return false;
}
public function scopeFilter($query, ForumFilters $filters)
{
return $filters->apply($query);
}
public function getShortContentAttribute(): string
{
return Str::limit(strip_tags($this->content), 100);
}
public function attachFiles($files): Model
{
return $this->files()->create($files);
}
public function files(): HasMany
{
return $this->hasMany(ForumFile::class, 'discussion_id', 'id');
}
public function scopeClosed(Builder $query): Builder
{
return $query->where('is_closed', true);
}
public function createdAt(): Attribute
{
return Attribute::make(
get: static fn ($value) => Carbon::parse($value)->diffForHumans(),
);
}
}
Contoller
public function index(Channel $channel, ForumFilters $filters)
{
$discussions = Discussion::withCount('replies')->with('channel')->filter($filters);
if ($channel->exists) {
$discussions->where('channel_id', $channel->id);
}
return Inertia::render('Forum/Index', [
'threads' => ThreadResource::collection($discussions->paginate(10)),
]);
}
Wich return collection
"data": [
{
"id": 1,
"title": "Whats Your Goto Solid Surface?",
"slug": "whats-your-goto-solid-surface-147970",
"content": "<p>My goto is Mirostone. It's softer than Mistral. Great fitting kit.<br>I've fitted Pietra / Pietra Gold, Mirostone, Mistral and various chipboard core resin worktops in the past.<br>What's your goto and why?</p>",
"created_at": "1 year ago",
"views": 552,
"short_content": "My goto is Mirostone. It's softer than Mistral. Great fitting kit.I've fitted Pietra / Pietra Gold,...",
"replies_count": 1,
"channel": {
"title": "Kitchen Fitters Chat",
"slug": "kitchen-fitters-chat"
}
}```
and show method
public function show(Channel $channel, Discussion $discussion)
{
$discussion->increment('views');
return Inertia::render('Forum/Show', [
'discussion' => new ThreadResource($discussion->loadCount('replies')->load('channel')->load('replies')->load('user')),
'replies' => fn () => RepliesResource::collection($discussion->replies()->with('user')->withCount('likes')->paginate(config('custom.comments.paginate'))),
]);
}```
return
{
"data":{"id":1,"title":"Whats Your Goto Solid Surface?","slug":"whats-your-goto-solid-surface-1","content":"
My goto is Mirostone. It's softer than Mistral. Great fitting kit.
I've fitted Pietra / Pietra Gold, Mirostone, Mistral and various chipboard core resin worktops in the past.
What's your goto and why?