query(" SELECT m.*, c.place, c.name as cinema_name, c.address as cinema_address, c.color as cinema_color FROM movies m LEFT JOIN cinemas c ON m.cinema_id = c.id ORDER BY m.watch_date DESC, m.created_at DESC "); $movies = $stmt->fetchAll(); attachViewersToMovies($movies); return $movies; } function getMovie($id) { $db = getDB(); $stmt = $db->prepare(" SELECT m.*, c.place, c.name as cinema_name, c.address as cinema_address, c.color as cinema_color FROM movies m LEFT JOIN cinemas c ON m.cinema_id = c.id WHERE m.id = ? "); $stmt->execute([$id]); $movie = $stmt->fetch(); if ($movie) { $stmt2 = $db->prepare(" SELECT v.id, v.movie_id, v.person_id, COALESCE(p.name, v.name) as name, p.color as person_color, p.avatar as person_avatar FROM viewers v LEFT JOIN persons p ON v.person_id = p.id WHERE v.movie_id = ? ORDER BY v.id "); $stmt2->execute([$id]); $movie['viewers'] = $stmt2->fetchAll(); $stmt3 = $db->prepare("SELECT * FROM movie_photos WHERE movie_id = ? ORDER BY id"); $stmt3->execute([$id]); $movie['photos'] = $stmt3->fetchAll(); } return $movie; } function attachViewersToMovies(&$movies) { if (empty($movies)) return; $db = getDB(); $movie_ids = array_column($movies, 'id'); if (empty($movie_ids)) return; $placeholders = implode(',', array_fill(0, count($movie_ids), '?')); $stmt = $db->prepare(" SELECT v.movie_id, p.id as person_id, p.name, p.color, p.avatar FROM viewers v LEFT JOIN persons p ON v.person_id = p.id WHERE v.movie_id IN ($placeholders) ORDER BY v.id "); $stmt->execute($movie_ids); $rows = $stmt->fetchAll(); $viewers_map = []; foreach ($rows as $row) { $movie_id = $row['movie_id']; if (!isset($viewers_map[$movie_id])) $viewers_map[$movie_id] = []; $viewers_map[$movie_id][] = [ 'person_id' => $row['person_id'], 'name' => $row['name'] ?? '未知', 'color' => $row['color'] ?? '#888888', 'avatar' => $row['avatar'] ]; } foreach ($movies as &$movie) { $movie['viewers'] = $viewers_map[$movie['id']] ?? []; } } // ===== 影院 ===== function getCinemas() { $db = getDB(); $stmt = $db->query("SELECT * FROM cinemas ORDER BY place, name"); return $stmt->fetchAll(); } // ===== 搜索 ===== function searchMovies($keyword) { return advancedSearch(['title' => $keyword]); } function advancedSearch($params) { $db = getDB(); $sql = " SELECT DISTINCT m.*, c.place, c.name as cinema_name, c.address as cinema_address, c.color as cinema_color FROM movies m LEFT JOIN cinemas c ON m.cinema_id = c.id LEFT JOIN viewers v ON m.id = v.movie_id LEFT JOIN persons p ON v.person_id = p.id WHERE 1=1 "; $bind = []; if (!empty($params['title'])) { $sql .= " AND m.title LIKE :title"; $bind[':title'] = '%' . $params['title'] . '%'; } if (!empty($params['cinema_id']) && is_numeric($params['cinema_id'])) { $sql .= " AND m.cinema_id = :cinema_id"; $bind[':cinema_id'] = (int)$params['cinema_id']; } if (!empty($params['person_id']) && is_numeric($params['person_id'])) { $sql .= " AND v.person_id = :person_id"; $bind[':person_id'] = (int)$params['person_id']; } if (!empty($params['date_from'])) { $sql .= " AND m.watch_date >= :date_from"; $bind[':date_from'] = $params['date_from']; } if (!empty($params['date_to'])) { $sql .= " AND m.watch_date <= :date_to"; $bind[':date_to'] = $params['date_to']; } $sql .= " ORDER BY m.watch_date DESC, m.created_at DESC"; $stmt = $db->prepare($sql); $stmt->execute($bind); $movies = $stmt->fetchAll(); attachViewersToMovies($movies); return $movies; } // ===== 表单提交时的关联数据处理 ===== /** * 解析表单提交的电影院选择。 * 选择「新建」且填了名称时创建影院并返回新 id;未选择或信息不足时返回 null。 */ function resolveCinemaId($cinema_id, $new_place, $new_name, $new_address) { $db = getDB(); if ($cinema_id === 'new' && !empty($new_name)) { $stmt = $db->prepare("INSERT INTO cinemas (place, name, address) VALUES (?, ?, ?)"); $stmt->execute([$new_place, $new_name, $new_address]); $cinema_id = $db->lastInsertId(); } elseif ($cinema_id === 'new') { $cinema_id = null; } elseif (!empty($cinema_id) && is_numeric($cinema_id)) { $cinema_id = (int)$cinema_id; } else { $cinema_id = null; } return $cinema_id; } /** * 解析「一起看的人」表单行:已有观影人取 id,选择「新增」则按姓名建库或复用。 * 返回去重后的观影人 id 列表。 */ function resolvePersonIds($viewer_selects, $viewer_news) { $db = getDB(); $person_ids = []; foreach ($viewer_selects as $idx => $val) { if ($val === 'new') { $new_name = trim($viewer_news[$idx] ?? ''); if (!empty($new_name)) { $chk = $db->prepare("SELECT id FROM persons WHERE name = ?"); $chk->execute([$new_name]); $existing = $chk->fetch(); if ($existing) { $person_ids[] = $existing['id']; } else { $ins = $db->prepare("INSERT INTO persons (name) VALUES (?)"); $ins->execute([$new_name]); $person_ids[] = $db->lastInsertId(); } } } elseif (is_numeric($val) && $val > 0) { $person_ids[] = (int)$val; } } return array_unique($person_ids); } // 把观影人写入电影关联表 function linkViewers($movie_id, $person_ids) { if (empty($person_ids)) return; $db = getDB(); $stmt = $db->prepare("INSERT INTO viewers (movie_id, person_id, name) VALUES (?, ?, ?)"); foreach ($person_ids as $pid) { $stmt->execute([$movie_id, $pid, '']); } }