Files
fitness/app/Models/Post.php
T
rootandClaude Sonnet 5 4686dea609 Add blog feature and fix broken test/build infra
BlogController was an empty stub with no view, so /blog 500'd on every
visit. Adds a real Post model, public listing/detail pages, and an admin
CRUD screen mirroring the existing Exercise admin pattern (image upload
or URL, auto-slug, publish toggle). Seeds 5 real posts so it's not empty
on launch.

Also fixes two things that were silently broken: phpunit.xml pointed
DB_DATABASE at a non-existent "testing" file with no DB_CONNECTION set,
and the stock ExampleTest had RefreshDatabase commented out - both meant
the test suite never actually ran successfully.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 11:36:31 +03:00

58 lines
1.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Storage;
class Post extends Model
{
protected $fillable = [
'title',
'slug',
'excerpt',
'body',
'cover_image',
'author_id',
'published_at',
];
protected $casts = [
'published_at' => 'datetime',
];
public function getRouteKeyName(): string
{
return 'slug';
}
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id');
}
public function scopePublished(Builder $query): Builder
{
return $query->whereNotNull('published_at')->where('published_at', '<=', now());
}
public function getIsPublishedAttribute(): bool
{
return $this->published_at !== null && $this->published_at->lte(now());
}
public function getCoverUrlAttribute(): ?string
{
$cover = (string) ($this->attributes['cover_image'] ?? '');
if ($cover === '') {
return null;
}
if (preg_match('/^https?:\/\//i', $cover)) {
return $cover;
}
return Storage::url($cover);
}
}