/* ============================================================ app/controllers/GameController.php ============================================================ */ class GameController { private PDO $db; public function __construct() { $this->db = DB::get(); } // GET /games/ and GET /games/{slug}/ public function index(?string $slug = null): void { if ($slug) { $this->show($slug); return; } $games = $this->db->query(" SELECT g.id, g.title, g.slug, g.game_type, g.difficulty, g.play_count, g.thumbnail, s.name AS subject_name, s.color_hex, s.icon, cl.name AS class_name FROM games g JOIN topics t ON t.id = g.topic_id JOIN subjects s ON s.id = t.subject_id JOIN class_levels cl ON cl.id = t.class_id WHERE g.is_active = 1 ORDER BY g.is_featured DESC, g.play_count DESC ")->fetchAll(); $subjects = $this->db->query(" SELECT s.id, s.name, s.slug, s.icon, s.color_hex, COUNT(g.id) AS game_count FROM subjects s JOIN topics t ON t.subject_id = s.id JOIN games g ON g.topic_id = t.id AND g.is_active = 1 GROUP BY s.id ORDER BY s.sort_order ")->fetchAll(); Seo::set( 'Free Educational Games for Nigerian Students — Play Online', 'Free mathematics, English, science and history games for Nigerian primary and secondary school students. No sign-up required.' ); Seo::addCrumb('Home', '/'); Seo::addCrumb('Games', '/games/'); Seo::breadcrumbSchema(); $pageTitle = 'Games'; $templatePath = ROOT . '/views/games/index.php'; require ROOT . '/views/layouts/main.php'; } private function show(string $slug): void { // Word scramble has its own controller — delegate if (str_starts_with($slug, 'english-word-scramble')) { (new WordScrambleController())->show($slug); return; } $stmt = $this->db->prepare(" SELECT g.*, gd.data AS game_data, s.name AS subject_name, s.slug AS subject_slug, s.color_hex, cl.name AS class_name, cl.slug AS class_slug, t.name AS topic_name FROM games g LEFT JOIN game_data gd ON gd.game_id = g.id JOIN topics t ON t.id = g.topic_id JOIN subjects s ON s.id = t.subject_id JOIN class_levels cl ON cl.id = t.class_id WHERE g.slug = ? AND g.is_active = 1 "); $stmt->execute([$slug]); $game = $stmt->fetch(); if (!$game) { http_response_code(404); $templatePath = ROOT . '/views/errors/404.php'; require ROOT . '/views/layouts/main.php'; return; } $this->db->prepare("UPDATE games SET play_count = play_count + 1 WHERE id = ?") ->execute([$game['id']]); if ($game['game_data']) { $game['game_data'] = json_decode($game['game_data'], true); } $related = $this->db->prepare(" SELECT id, title, slug, game_type, play_count FROM games WHERE topic_id = ? AND id != ? AND is_active = 1 LIMIT 4 "); $related->execute([$game['topic_id'], $game['id']]); $related = $related->fetchAll(); Seo::set( $game['meta_title'] ?: $game['title'] . ' | Educational Games Nigeria', $game['meta_desc'] ?: $game['description'] ); Seo::addCrumb('Home', '/'); Seo::addCrumb('Games', '/games/'); Seo::addCrumb($game['subject_name'], '/subjects/' . $game['subject_slug'] . '/'); Seo::addCrumb($game['title']); Seo::breadcrumbSchema(); Seo::gameSchema($game); $pageTitle = $game['title']; $templatePath = ROOT . '/views/games/show.php'; require ROOT . '/views/layouts/main.php'; } } Educational Games Nigeria
Primary P1 P2 P3 P4 P5 P6 JSS JSS1 JSS2 JSS3 SSS SS1 SS2 SS3