当前位置:首页 > 云服务器 > 正文

PHP音乐网站开发教程,如何用PHP开发在线音乐播放网站?

PHP音乐网站开发方案

我将设计一个功能丰富的音乐网站,使用PHP作为后端语言,结合MySQL数据库实现核心功能,下面是我的实现思路和完整代码。

设计思路

这个音乐网站将包含以下核心功能:

  • 用户注册登录系统
  • 音乐搜索与播放
  • 个性化播放列表
  • 艺术家和专辑浏览
  • 响应式布局适配所有设备

数据库设计(MySQL)

CREATE DATABASE music_db; USE music_db; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE artists ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, bio TEXT, image_path VARCHAR(255) ); CREATE TABLE albums ( id INT AUTO_INCREMENT PRIMARY KEY,VARCHAR(100) NOT NULL, artist_id INT, release_year YEAR, cover_path VARCHAR(255), FOREIGN KEY (artist_id) REFERENCES artists(id) ); CREATE TABLE songs ( id INT AUTO_INCREMENT PRIMARY KEY,VARCHAR(100) NOT NULL, artist_id INT, album_id INT, duration TIME, file_path VARCHAR(255) NOT NULL, plays INT DEFAULT 0, FOREIGN KEY (artist_id) REFERENCES artists(id), FOREIGN KEY (album_id) REFERENCES albums(id) ); CREATE TABLE playlists ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, name VARCHAR(100) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); CREATE TABLE playlist_songs ( playlist_id INT, song_id INT, added_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (playlist_id, song_id), FOREIGN KEY (playlist_id) REFERENCES playlists(id), FOREIGN KEY (song_id) REFERENCES songs(id) );

PHP实现 – 完整音乐网站代码

<?php // 数据库连接 $host = 'localhost'; $dbname = 'music_db'; $username = 'root'; $password = ''; try { $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 启动会话 session_start(); // 用户认证函数 function registerUser($username, $email, $password) { global $pdo; $hashedPassword = password_hash($password, PASSWORD_DEFAULT); $stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)"); return $stmt->execute([$username, $email, $hashedPassword]); } function loginUser($username, $password) { global $pdo; $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password'])) { $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; return true; } return false; } // 获取音乐数据 function getFeaturedSongs() { global $pdo; $stmt = $pdo->query("SELECT songs.*, artists.name AS artist_name FROM songs JOIN artists ON songs.artist_id = artists.id ORDER BY plays DESC LIMIT 10"); return $stmt->fetchAll(); } function getNewReleases() { global $pdo; $stmt = $pdo->query("SELECT songs.*, artists.name AS artist_name, albums.title AS album_title, albums.cover_path FROM songs JOIN artists ON songs.artist_id = artists.id JOIN albums ON songs.album_id = albums.id ORDER BY albums.release_year DESC LIMIT 8"); return $stmt->fetchAll(); } function searchSongs($query) { global $pdo; $stmt = $pdo->prepare("SELECT songs.*, artists.name AS artist_name FROM songs JOIN artists ON songs.artist_id = artists.id WHERE songs.title LIKE ? OR artists.name LIKE ?"); $searchTerm = "%$query%"; $stmt->execute([$searchTerm, $searchTerm]); return $stmt->fetchAll(); } // 处理表单提交 if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['action'])) { switch ($_POST['action']) { case 'register': if (registerUser($_POST['username'], $_POST['email'], $_POST['password'])) { loginUser($_POST['username'], $_POST['password']); header("Location: index.php"); exit; } break; case 'login': if (loginUser($_POST['username'], $_POST['password'])) { header("Location: index.php"); exit; } break; case 'search': $searchResults = searchSongs($_POST['search_query']); break; } } } // 获取页面数据 $featuredSongs = getFeaturedSongs(); $newReleases = getNewReleases(); ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">Harmony音乐 - 发现好音乐</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> :root { --primary: #1DB954; --dark: #121212; --gray: #282828; --light-gray: #b3b3b3; --white: #ffffff; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--dark); color: var(--white); display: flex; min-height: 100vh; } /* 侧边栏样式 */ .sidebar { width: 230px; background-color: #000; padding: 24px; position: fixed; height: 100vh; overflow-y: auto; } .logo { margin-bottom: 30px; font-size: 24px; font-weight: bold; color: var(--white); } .logo i { color: var(--primary); margin-right: 10px; } .nav-links { list-style: none; } .nav-links li { margin-bottom: 12px; } .nav-links a { color: var(--light-gray); text-decoration: none; font-size: 16px; font-weight: 600; display: flex; align-items: center; padding: 8px 0; transition: color 0.3s; } .nav-links a:hover, .nav-links a.active { color: var(--white); } .nav-links i { margin-right: 16px; font-size: 20px; } .playlists-section { margin-top: 30px; border-top: 1px solid var(--gray); padding-top: 20px; } .playlists-section h3 { color: var(--light-gray); font-size: 14px; text-transform: uppercase; margin-bottom: 15px; } /* 主内容区样式 */ .main-content { flex: 1; margin-left: 230px; padding: 20px 40px; background: linear-gradient(to bottom, #404040, var(--dark) 400px); } .top-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; padding: 10px 0; } .search-bar { background-color: var(--white); border-radius: 30px; display: flex; align-items: center; padding: 8px 15px; width: 350px; } .search-bar input { border: none; background: none; outline: none; flex: 1; padding: 5px 10px; font-size: 16px; } .search-bar button { background: none; border: none; color: var(--dark); cursor: pointer; font-size: 18px; } .user-actions { display: flex; align-items: center; } .user-actions a { color: var(--white); text-decoration: none; margin-left: 20px; font-weight: 600; font-size: 14px; padding: 8px 15px; border-radius: 20px; } .signup-btn { background-color: var(--white); color: var(--dark) !important; } .login-btn { background-color: transparent; border: 1px solid var(--white); } .user-profile { display: flex; align-items: center; background-color: rgba(0,0,0,0.7); border-radius: 30px; padding: 5px; } .user-profile img { width: 30px; height: 30px; border-radius: 50%; margin-right: 10px; } /* 内容区块样式 */ .section-title { font-size: 24px; margin: 30px 0 20px; } .cards-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 20px; } .card { background-color: var(--gray); border-radius: 6px; padding: 16px; transition: background-color 0.3s; cursor: pointer; } .card:hover { background-color: #3a3a3a; } .card-img { position: relative; margin-bottom: 16px; } .card-img img { width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: 4px; box-shadow: 0 8px 16px rgba(0,0,0,0.3); } .play-btn { position: absolute; bottom: 10px; right: 10px; background-color: var(--primary); width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; opacity: 0; transform: translateY(10px); transition: all 0.3s; box-shadow: 0 4px 8px rgba(0,0,0,0.4); } .card:hover .play-btn { opacity: 1; transform: translateY(0); } .play-btn i { color: var(--dark); font-size: 16px; } .card-title { font-size: 16px; font-weight: 600; margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .card-subtitle { color: var(--light-gray); font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* 音乐播放器样式 */ .player-bar { position: fixed; bottom: 0; left: 0; right: 0; background-color: var(--gray); height: 90px; display: flex; align-items: center; padding: 0 20px; border-top: 1px solid #404040; } .now-playing { width: 30%; display: flex; align-items: center; } .now-playing img { width: 56px; height: 56px; margin-right: 15px; } .track-info h4 { font-size: 14px; margin-bottom: 5px; } .track-info p { color: var(--light-gray); font-size: 12px; } .player-controls { width: 40%; display: flex; flex-direction: column; align-items: center; } .control-buttons { display: flex; align-items: center; margin-bottom: 10px; } .control-buttons button { background: none; border: none; color: var(--light-gray); font-size: 16px; margin: 0 10px; cursor: pointer; transition: color 0.3s; } .control-buttons button:hover { color: var(--white); } .control-buttons .play-pause { background-color: var(--white); color: var(--dark); width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; } .progress-container { width: 100%; display: flex; align-items: center; } .progress-time { font-size: 12px; color: var(--light-gray); min-width: 40px; } .progress-bar { flex: 1; height: 4px; background-color: #5e5e5e; border-radius: 2px; position: relative; cursor: pointer; } .progress { height: 100%; background-color: var(--light-gray); border-radius: 2px; width: 30%; } .progress-handle { position: absolute; top: 50%; right: 0; width: 12px; height: 12px; background-color: var(--white); border-radius: 50%; transform: translate(50%, -50%); opacity: 0; transition: opacity 0.3s; } .progress-bar:hover .progress-handle { opacity: 1; } .volume-controls { width: 30%; display: flex; justify-content: flex-end; align-items: center; } .volume-bar { width: 100px; height: 4px; background-color: #5e5e5e; border-radius: 2px; position: relative; cursor: pointer; margin-left: 10px; } .volume-level { height: 100%; background-color: var(--light-gray); border-radius: 2px; width: 70%; } /* 响应式设计 */ @media (max-width: 992px) { .sidebar { width: 70px; padding: 15px 10px; } .logo span, .nav-links span { display: none; } .nav-links i { margin-right: 0; font-size: 24px; } .playlists-section { display: none; } .main-content { margin-left: 70px; } } @media (max-width: 768px) { .cards-container { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .now-playing { width: 20%; } .player-controls { width: 50%; } .volume-controls { width: 30%; } } @media (max-width: 576px) { .sidebar { display: none; } .main-content { margin-left: 0; padding: 15px; } .top-bar { flex-direction: column; align-items: flex-start; } .search-bar { width: 100%; margin-top: 10px; } .player-bar { flex-direction: column; height: auto; padding: 10px; } .now-playing, .player-controls, .volume-controls { width: 100%; margin-bottom: 10px; } .volume-controls { justify-content: center; } } </style> </head> <body> <!-- 侧边导航 --> <div class="sidebar"> <div class="logo"> <i class="fas fa-music"></i> <span>Harmony音乐</span> </div> <ul class="nav-links"> <li><a href="#" class="active"><i class="fas fa-home"></i> <span>首页</span></a></li> <li><a href="#"><i class="fas fa-search"></i> <span>搜索</span></a></li> <li><a href="#"><i class="fas fa-book"></i> <span>音乐库</span></a></li> <li><a href="#"><i class="fas fa-compact-disc"></i> <span>专辑</span></a></li> <li><a href="#"><i class="fas fa-microphone-alt"></i> <span>艺术家</span></a></li> <li><a href="#"><i class="fas fa-heart"></i> <span>收藏</span></a></li> </ul> <div class="playlists-section"> <h3>播放列表</h3> <ul class="nav-links"> <li><a href="#"><i class="fas fa-plus-circle"></i> <span>新建播放列表</span></a></li> <li><a href="#"><i class="fas fa-music"></i> <span>最爱歌曲</span></a></li> <li><a href="#"><i class="fas fa-headphones"></i> <span>放松心情</span></a></li> <li><a href="#"><i class="fas fa-running"></i> <span>运动健身</span></a></li> </ul> </div> </div> <!-- 主内容区 --> <div class="main-content"> <div class="top-bar"> <div class="search-bar"> <form method="post" action=""> <input type="text" name="search_query" placeholder="搜索歌曲、艺术家或专辑"> <button type="submit" name="action" value="search"><i class="fas fa-search"></i></button> </form> </div> <?php if(isset($_SESSION['user_id'])): ?> <div class="user-profile"> <img src="https://randomuser.me/api/portraits/men/<?= rand(1,99) ?>.jpg" alt="用户头像"> <span><?= htmlspecialchars($_SESSION['username']) ?></span> </div> <?php else: ?> <div class="user-actions"> <a href="#" class="signup-btn" id="signupBtn">注册</a> <a href="#" class="login-btn" id="loginBtn">登录</a> </div> <?php endif; ?> </div> <!-- 特色推荐 --> <h2 class="section-title">特色推荐</h2> <div class="cards-container"> <?php foreach ($featuredSongs as $song): ?> <div class="card"> <div class="card-img"> <img src="https://picsum.photos/300/300?random=<?= $song['id'] ?>" alt="<?= htmlspecialchars($song['title']) ?>"> <div class="play-btn"> <i class="fas fa-play"></i> </div> </div> <div class="card-title"><?= htmlspecialchars($song['title']) ?></div> <div class="card-subtitle"><?= htmlspecialchars($song['artist_name']) ?></div> </div> <?php endforeach; ?> </div> <!-- 新歌推荐 --> <h2 class="section-title">新歌推荐</h2> <div class="cards-container"> <?php foreach ($newReleases as $song): ?> <div class="card"> <div class="card-img"> <img src="https://picsum.photos/300/300?random=<?= $song['id'] ?>" alt="<?= htmlspecialchars($song['title']) ?>"> <div class="play-btn"> <i class="fas fa-play"></i> </div> </div> <div class="card-title"><?= htmlspecialchars($song['title']) ?></div> <div class="card-subtitle"><?= htmlspecialchars($song['artist_name']) ?></div> </div> <?php endforeach; ?> </div> <!-- 搜索结果 --> <?php if (isset($searchResults) && !empty($searchResults)): ?> <h2 class="section-title">搜索结果</h2> <div class="cards-container"> <?php foreach ($searchResults as $song): ?> <div class="card"> <div class="card-img"> <img src="https://picsum.photos/300/300?random=<?= $song['id'] ?>" alt="<?= htmlspecialchars($song['title']) ?>"> <div class="play-btn"> <i class="fas fa-play"></i> </div> </div> <div class="card-title"><?= htmlspecialchars($song['title']) ?></div> <div class="card-subtitle"><?= htmlspecialchars($song['artist_name']) ?></div> </div> <?php endforeach; ?> </div> <?php endif; ?> </div> <!-- 音乐播放器 --> <div class="player-bar"> <div class="now-playing"> <img src="https://picsum.photos/100/100?random=100" alt="当前播放"> <div class="track-info"> <h4>Blinding Lights</h4> <p>The Weeknd</p> </div> </div> <div class="player-controls"> <div class="control-buttons"> <button><i class="fas fa-random"></i></button> <button><i class="fas fa-step-backward"></i></button> <button class="play-pause"><i class="fas fa-play"></i></button> <button><i class="fas fa-step-forward"></i></button> <button><i class="fas fa-repeat"></i></button> </div> <div class="progress-container"> <div class="progress-time">1:23</div> <div class="progress-bar"> <div class="progress"></div> <div class="progress-handle"></div> </div> <div class="progress-time">3:45</div> </div> </div> <div class="volume-controls"> <button><i class="fas fa-volume-up"></i></button> <div class="volume-bar"> <div class="volume-level"></div> </div> </div> </div> <!-- 登录/注册弹窗 --> <div id="authModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.7); z-index: 1000; justify-content: center; align-items: center;"> <div style="background-color: #282828; width: 100%; max-width: 400px; border-radius: 8px; padding: 30px; position: relative;"> <button id="closeModal" style="position: absolute; top: 15px; right: 15px; background: none; border: none; color: #b3b3b3; font-size: 24px; cursor: pointer;">&times;</button> <div id="loginForm"> <h2 style="text-align: center; margin-bottom: 25px;">登录Harmony音乐</h2> <form method="post" action="" style="display: flex; flex-direction: column;"> <input type="text" name="username" placeholder="用户名" style="background-color: #121212; border: 1px solid #404040; border-radius: 4px; padding: 12px; margin-bottom: 15px; color: white;"> <input type="password" name="password" placeholder="密码" style="background-color: #121212; border: 1px solid #404040; border-radius: 4px; padding: 12px; margin-bottom: 15px; color: white;"> <button type="submit" name="action" value="login" style="background-color: #1DB954; color: white; border: none; border-radius: 30px; padding: 12px; font-weight: bold; cursor: pointer; margin-bottom: 15px;">登录</button> </form> <p style="text-align: center; color: #b3b3b3; margin-top: 15px;"> 还没有账号? <a href="#" id="showSignup" style="color: #1DB954; text-decoration: none; font-weight: bold;">注册</a> </p> </div> <div id="signupForm" style="display: none;"> <h2 style="text-align: center; margin-bottom: 25px;">创建账户</h2> <form method="post" action="" style="display: flex; flex-direction: column;"> <input type="text" name="username" placeholder="用户名" style="background-color: #121212; border: 1px solid #404040; border-radius: 4px; padding: 12px; margin-bottom: 15px; color: white;"> <input type="email" name="email" placeholder="电子邮箱" style="background-color: #121212; border: 1px solid #404040; border-radius: 4px; padding: 12px; margin-bottom: 15px; color: white;"> <input type="password" name="password" placeholder="密码" style="background-color: #121212; border: 1px solid #404040; border-radius: 4px; padding: 12px; margin-bottom: 15px; color: white;"> <button type="submit" name="action" value="register" style="background-color: #1DB954; color: white; border: none; border-radius: 30px; padding: 12px; font-weight: bold; cursor: pointer; margin-bottom: 15px;">注册</button> </form> <p style="text-align: center; color: #b3b3b3; margin-top: 15px;"> 已有账号? <a href="#" id="showLogin" style="color: #1DB954; text-decoration: none; font-weight: bold;">登录</a> </p> </div> </div> </div> <script> // 登录/注册弹窗逻辑 const authModal = document.getElementById('authModal'); const loginForm = document.getElementById('loginForm'); const signupForm = document.getElementById('signupForm'); const showSignup = document.getElementById('showSignup'); const showLogin = document.getElementById('showLogin'); const closeModal = document.getElementById('closeModal'); const loginBtn = document.getElementById('loginBtn'); const signupBtn = document.getElementById('signupBtn'); if (loginBtn) { loginBtn.addEventListener('click', (e) => { e.preventDefault(); authModal.style.display = 'flex'; loginForm.style.display = 'block'; signupForm.style.display = 'none'; }); } if (signupBtn) { signupBtn.addEventListener('click', (e) => { e.preventDefault(); authModal.style.display = 'flex'; loginForm.style.display = 'none'; signupForm.style.display = 'block'; }); } showSignup.addEventListener('click', (e) => { e.preventDefault(); loginForm.style.display = 'none'; signupForm.style.display = 'block'; }); showLogin.addEventListener('click', (e) => { e.preventDefault(); loginForm.style.display = 'block'; signupForm.style.display = 'none'; }); closeModal.addEventListener('click', () => { authModal.style.display = 'none'; }); // 播放按钮点击事件 document.querySelectorAll('.play-btn').forEach(btn => { btn.addEventListener('click', function(e) { e.stopPropagation(); const card = this.closest('.card'); const title = card.querySelector('.card-title').textContent; const artist = card.querySelector('.card-subtitle').textContent; // 更新播放器信息 document.querySelector('.now-playing h4').textContent = title; document.querySelector('.now-playing p').textContent = artist; // 切换播放按钮状态 const playBtn = document.querySelector('.play-pause i'); if (playBtn.classList.contains('fa-play')) { playBtn.classList.remove('fa-play'); playBtn.classList.add('fa-pause'); } }); }); // 播放/暂停按钮 document.querySelector('.play-pause').addEventListener('click', function() { const icon = this.querySelector('i'); if (icon.classList.contains('fa-play')) { icon.classList.remove('fa-play'); icon.classList.add('fa-pause'); } else { icon.classList.remove('fa-pause'); icon.classList.add('fa-play'); } }); </script> </body> </html>

功能说明

这个音乐网站实现了以下核心功能:

  1. 用户系统

    • 用户注册与登录
    • 会话管理
    • 密码安全存储(使用password_hash)
  2. 音乐管理

    • 音乐展示(特色推荐、新歌推荐)
    • 音乐搜索功能
    • 播放次数统计
  3. 播放功能

    • 音乐播放控制
    • 进度条控制
    • 音量控制
    • 当前播放信息展示
    • 响应式设计

      • 适配桌面、平板和手机设备
      • 移动端优化导航
      • 数据库集成

        • 使用PDO连接MySQL数据库
        • 数据安全处理(防止SQL载入)
        • 后续扩展建议

          1. 添加音乐上传功能(管理员界面)
          2. 实现播放列表创建和管理
          3. 添加音乐收藏功能
          4. 集成音乐推荐算法
          5. 添加用户社交功能(关注、分享)
          6. 实现音乐评论系统

          这个音乐网站采用了现代化的深色主题设计,符合当前音乐平台的流行风格,同时确保了良好的用户体验和功能性。

          PHP音乐网站开发教程,如何用PHP开发在线音乐播放网站? 第1张

          PHP音乐网站开发教程,如何用PHP开发在线音乐播放网站? 第2张

          PHP音乐网站开发教程,如何用PHP开发在线音乐播放网站? 第3张

0