Files
gtsit/app/Repositories/PostRepository.php
2026-08-10 21:19:10 +09:00

82 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Repositories;
use App\Database;
use PDO;
final class PostRepository
{
private PDO $db;
public function __construct()
{
$this->db = Database::connection();
}
public function latest(int $limit = 3): array
{
$statement = $this->db->prepare(
"SELECT posts.id, posts.title, posts.slug, posts.category, posts.excerpt, posts.published_at,
(SELECT file_path FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_path,
(SELECT alt_text FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_alt
FROM posts
WHERE posts.status = 'published' AND posts.deleted_at IS NULL AND posts.published_at <= NOW()
ORDER BY published_at DESC, id DESC
LIMIT :limit"
);
$statement->bindValue(':limit', $limit, PDO::PARAM_INT);
$statement->execute();
return $statement->fetchAll();
}
public function paginate(int $page, int $perPage, ?string $category = null): array
{
$where = "posts.status = 'published' AND posts.deleted_at IS NULL AND posts.published_at <= NOW()";
$params = [];
if ($category !== null && $category !== '') {
$where .= ' AND posts.category = :category';
$params['category'] = $category;
}
$count = $this->db->prepare("SELECT COUNT(*) FROM posts WHERE {$where}");
$count->execute($params);
$total = (int) $count->fetchColumn();
$offset = max(0, ($page - 1) * $perPage);
$query = $this->db->prepare(
"SELECT posts.id, posts.title, posts.slug, posts.category, posts.excerpt, posts.published_at,
(SELECT file_path FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_path,
(SELECT alt_text FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_alt
FROM posts WHERE {$where}
ORDER BY published_at DESC, id DESC
LIMIT :limit OFFSET :offset"
);
foreach ($params as $key => $value) {
$query->bindValue(':' . $key, $value);
}
$query->bindValue(':limit', $perPage, PDO::PARAM_INT);
$query->bindValue(':offset', $offset, PDO::PARAM_INT);
$query->execute();
return ['items' => $query->fetchAll(), 'total' => $total];
}
public function findPublishedBySlug(string $slug): ?array
{
$statement = $this->db->prepare(
"SELECT posts.id, posts.title, posts.slug, posts.category, posts.excerpt, posts.body, posts.author, posts.published_at,
(SELECT file_path FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_path,
(SELECT alt_text FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_alt
FROM posts
WHERE posts.slug = :slug AND posts.status = 'published' AND posts.deleted_at IS NULL AND posts.published_at <= NOW()
LIMIT 1"
);
$statement->execute(['slug' => $slug]);
$post = $statement->fetch();
return $post ?: null;
}
}