Web-based Game Leaderboard JavaScript, PHP, MySQL

👤 Sharing: AI
Okay, here's a basic implementation of a web-based game leaderboard using JavaScript (client-side), PHP (server-side), and MySQL (database). I'll provide code snippets for each part along with explanations.  This example focuses on core functionality (submitting scores and retrieving the leaderboard).  It lacks features like user authentication, detailed error handling, and robust security measures. Consider it a starting point.

**1. Database Setup (MySQL)**

First, you need to create a database and a table to store the scores.  You can use phpMyAdmin, MySQL Workbench, or the MySQL command-line client.

```sql
-- Create the database (if it doesn't exist)
CREATE DATABASE IF NOT EXISTS game_leaderboard;

-- Use the database
USE game_leaderboard;

-- Create the leaderboard table
CREATE TABLE IF NOT EXISTS scores (
    id INT AUTO_INCREMENT PRIMARY KEY,
    player_name VARCHAR(255) NOT NULL,
    score INT NOT NULL,
    submission_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```

**Explanation:**

*   `CREATE DATABASE IF NOT EXISTS game_leaderboard;`: Creates the database to hold our leaderboard data if one doesn't already exist.
*   `USE game_leaderboard;`: Tells MySQL that we want to work within the `game_leaderboard` database.
*   `CREATE TABLE IF NOT EXISTS scores (...)`: Creates a table named `scores` to store the player names, scores, and submission times.
    *   `id INT AUTO_INCREMENT PRIMARY KEY`:  A unique ID for each entry, automatically incrementing.  The `PRIMARY KEY` constraint ensures each ID is unique, and it's indexed for faster lookups.
    *   `player_name VARCHAR(255) NOT NULL`:  The player's name (string, maximum 255 characters).  `NOT NULL` means this field cannot be empty.
    *   `score INT NOT NULL`:  The player's score (integer). `NOT NULL` means this field cannot be empty.
    *   `submission_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP`:  The date and time the score was submitted.  `DEFAULT CURRENT_TIMESTAMP` automatically sets it to the current time when a new row is inserted.

**2. PHP (Server-Side Logic)**

Create two PHP files: `submit_score.php` (to handle score submissions) and `get_leaderboard.php` (to retrieve the leaderboard data).

**`submit_score.php`**

```php
<?php
// Database credentials
$servername = "localhost"; // Or your server address
$username = "your_username";
$password = "your_password";
$dbname = "game_leaderboard";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Get data from POST request (sent by JavaScript)
$playerName = $_POST['player_name'];
$score = $_POST['score'];

// Sanitize input (important for security!)
$playerName = htmlspecialchars($playerName);  // Prevent XSS
$score = intval($score); // Ensure score is an integer

// Prepare and execute SQL query (using prepared statement to prevent SQL injection)
$stmt = $conn->prepare("INSERT INTO scores (player_name, score) VALUES (?, ?)");
$stmt->bind_param("si", $playerName, $score); // "s" for string, "i" for integer

if ($stmt->execute()) {
    echo "Score submitted successfully";
} else {
    echo "Error submitting score: " . $stmt->error;
}

$stmt->close();
$conn->close();

?>
```

**Explanation:**

*   **Database Connection:** Establishes a connection to the MySQL database using your credentials.  **Important:**  Replace `"your_username"`, `"your_password"`, and `"game_leaderboard"` with your actual database credentials.
*   **Error Handling:** Checks if the connection was successful. If not, it terminates the script and displays an error message.
*   **Retrieving Data:**  `$_POST['player_name']` and `$_POST['score']` retrieve the player's name and score that were sent from the JavaScript code via an HTTP POST request.
*   **Input Sanitization:**
    *   `htmlspecialchars($playerName)`:  Converts special characters to HTML entities (e.g., `<` becomes `&lt;`). This prevents Cross-Site Scripting (XSS) attacks where malicious code could be injected into the leaderboard.
    *   `intval($score)`: Converts the score to an integer.  This helps prevent unexpected data types and potential errors.
*   **Prepared Statement:**  The code uses a *prepared statement* to insert the data into the database.  This is crucial for preventing SQL injection attacks.  Instead of directly embedding the player's name and score into the SQL query string, we use placeholders (`?`).
    *   `$stmt = $conn->prepare(...)`:  Prepares the SQL statement with placeholders.
    *   `$stmt->bind_param("si", $playerName, $score)`:  Binds the player's name (string, "s") and score (integer, "i") to the placeholders.
    *   `$stmt->execute()`:  Executes the prepared statement.
*   **Response:**  Echoes a success or error message to the client (JavaScript).
*   **Closing Connections:**  Closes the prepared statement and the database connection to release resources.

**`get_leaderboard.php`**

```php
<?php
// Database credentials (same as submit_score.php)
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "game_leaderboard";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// SQL query to retrieve the top scores (order by score descending, limit to top 10)
$sql = "SELECT player_name, score FROM scores ORDER BY score DESC LIMIT 10";
$result = $conn->query($sql);

$leaderboard = array(); // Create an empty array to store the leaderboard data

if ($result->num_rows > 0) {
    // Fetch each row and add it to the leaderboard array
    while($row = $result->fetch_assoc()) {
        $leaderboard[] = $row;
    }
}

// Convert the leaderboard array to JSON and send it to the client
header('Content-Type: application/json'); // Set the content type to JSON
echo json_encode($leaderboard);

$conn->close();
?>
```

**Explanation:**

*   **Database Connection:** Similar to `submit_score.php`, it connects to the database.
*   **SQL Query:**
    *   `SELECT player_name, score FROM scores ORDER BY score DESC LIMIT 10`:  Selects the player's name and score from the `scores` table.
    *   `ORDER BY score DESC`:  Sorts the results in descending order of score (highest score first).
    *   `LIMIT 10`:  Limits the results to the top 10 scores.
*   **Fetching Data:**
    *   `$result = $conn->query($sql)`: Executes the SQL query.
    *   The `while` loop iterates through each row of the result set.
    *   `$row = $result->fetch_assoc()`: Fetches a row as an associative array (where keys are column names).
    *   `$leaderboard[] = $row`: Appends the row to the `$leaderboard` array.
*   **JSON Encoding:**
    *   `header('Content-Type: application/json')`:  Sets the HTTP header to indicate that the response is in JSON format.
    *   `echo json_encode($leaderboard)`:  Converts the `$leaderboard` array into a JSON string and sends it as the response.  JSON is a standard format for exchanging data between a server and a web browser.
*   **Closing Connection:**  Closes the database connection.

**3. HTML & JavaScript (Client-Side)**

Create an HTML file (e.g., `index.html`) with JavaScript to interact with the PHP scripts.

```html
<!DOCTYPE html>
<html>
<head>
    <title>Game Leaderboard</title>
    <style>
        body { font-family: sans-serif; }
        #leaderboard-container { margin-top: 20px; }
        table { border-collapse: collapse; width: 50%; }
        th, td { border: 1px solid black; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Game Leaderboard</h1>

    <div>
        <label for="player-name">Your Name:</label>
        <input type="text" id="player-name" name="player-name"><br><br>
        <label for="score">Your Score:</label>
        <input type="number" id="score" name="score"><br><br>
        <button onclick="submitScore()">Submit Score</button>
    </div>

    <div id="leaderboard-container">
        <h2>Top Scores</h2>
        <table id="leaderboard-table">
            <thead>
                <tr>
                    <th>Player</th>
                    <th>Score</th>
                </tr>
            </thead>
            <tbody>
                <!-- Leaderboard data will be inserted here -->
            </tbody>
        </table>
    </div>

    <script>
        function submitScore() {
            const playerName = document.getElementById('player-name').value;
            const score = document.getElementById('score').value;

            // Basic validation
            if (!playerName || !score) {
                alert("Please enter your name and score.");
                return;
            }

            fetch('submit_score.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded' // Important for sending form data
                },
                body: 'player_name=' + encodeURIComponent(playerName) + '&score=' + encodeURIComponent(score)
            })
            .then(response => response.text())
            .then(data => {
                alert(data); // Display the response from PHP (success/error)
                getLeaderboard(); // Refresh the leaderboard
                document.getElementById('player-name').value = '';
                document.getElementById('score').value = '';

            })
            .catch(error => {
                console.error('Error:', error);
                alert('An error occurred while submitting the score.');
            });
        }


        function getLeaderboard() {
            fetch('get_leaderboard.php')
            .then(response => response.json())
            .then(data => {
                const leaderboardTableBody = document.getElementById('leaderboard-table').getElementsByTagName('tbody')[0];
                leaderboardTableBody.innerHTML = ''; // Clear existing data

                data.forEach(entry => {
                    const row = leaderboardTableBody.insertRow();
                    const playerCell = row.insertCell();
                    const scoreCell = row.insertCell();
                    playerCell.textContent = entry.player_name;
                    scoreCell.textContent = entry.score;
                });
            })
            .catch(error => {
                console.error('Error:', error);
                alert('An error occurred while fetching the leaderboard.');
            });
        }

        // Load the leaderboard when the page loads
        window.onload = getLeaderboard;
    </script>
</body>
</html>
```

**Explanation:**

*   **HTML Structure:**
    *   Basic HTML structure with a title, input fields for player name and score, a submit button, and a table to display the leaderboard.
    *   CSS is included for basic styling.
*   **JavaScript:**
    *   **`submitScore()` function:**
        *   Gets the player's name and score from the input fields.
        *   Performs basic validation to ensure both fields are filled.
        *   Uses the `fetch` API to send a POST request to `submit_score.php`.
            *   `method: 'POST'`:  Specifies that we're using the POST method to send the data.
            *   `headers: { 'Content-Type': 'application/x-www-form-urlencoded' }`:  Sets the `Content-Type` header to `application/x-www-form-urlencoded`, which is the standard format for sending form data in POST requests.
            *   `body: 'player_name=' + encodeURIComponent(playerName) + '&score=' + encodeURIComponent(score)`:  Constructs the request body as a URL-encoded string.  `encodeURIComponent()` is used to properly encode the player's name and score to handle special characters.
        *   Handles the response from `submit_score.php` (displays a success or error message using `alert()`).
        *   Calls `getLeaderboard()` to refresh the leaderboard after a successful submission.
        *   Clears the input fields.
        *   Includes error handling using `.catch()` to catch and log any errors that occur during the `fetch` request.
    *   **`getLeaderboard()` function:**
        *   Uses the `fetch` API to send a GET request to `get_leaderboard.php`.
        *   Parses the JSON response from `get_leaderboard.php` using `.then(response => response.json())`.
        *   Clears the existing leaderboard table data.
        *   Iterates through the leaderboard data and dynamically creates table rows and cells to display the player names and scores.
        *   Includes error handling to catch and log any errors.
    *   **`window.onload = getLeaderboard;`:**  Calls the `getLeaderboard()` function when the page finishes loading to initially populate the leaderboard.

**How to Run:**

1.  **Save the files:** Save the PHP files (`submit_score.php`, `get_leaderboard.php`) and the HTML file (`index.html`) in a directory accessible to your web server (e.g., `htdocs` in XAMPP or `www` in WAMP).
2.  **Start your web server:**  Start XAMPP, WAMP, or any other web server you're using.
3.  **Access the page:** Open your web browser and go to `http://localhost/your_directory/index.html` (replace `your_directory` with the actual name of the directory where you saved the files).
4.  **Submit scores and view the leaderboard.**

**Important Considerations and Improvements:**

*   **Security:**  This example has *minimal* security measures.  In a real-world application, you *must* implement robust security, including:
    *   **User Authentication:** Require users to log in to prevent unauthorized score submissions.
    *   **Input Validation:**  More thorough input validation on the server-side to prevent malicious data from being stored in the database (e.g., checking the score range).
    *   **SQL Injection Prevention:**  The prepared statements help, but you should also be careful with any dynamically generated SQL.
    *   **Cross-Site Scripting (XSS) Prevention:**  The `htmlspecialchars()` function helps, but consider using a templating engine that automatically escapes output.
    *   **Rate Limiting:** Implement rate limiting to prevent users from submitting scores too frequently.
*   **Error Handling:** Add more comprehensive error handling to both the PHP and JavaScript code to provide better feedback to the user and log errors for debugging.
*   **User Interface (UI):** Enhance the user interface with better styling, error messages, and loading indicators.
*   **Pagination:** If you have a large number of scores, implement pagination to display the leaderboard in manageable chunks.
*   **Real-time Updates:**  Consider using WebSockets to provide real-time updates to the leaderboard whenever a new score is submitted.
*   **Database Indexing:**  For large datasets, add indexes to the `scores` table to improve query performance.  Specifically, an index on the `score` column would be beneficial.
*   **Frameworks:** Consider using a PHP framework (e.g., Laravel, Symfony) or a JavaScript framework (e.g., React, Vue.js, Angular) to structure your code and simplify development.
*   **Configuration:**  Store database credentials in a separate configuration file instead of directly embedding them in the code.
*   **Password Hashing:** If you implement user authentication, *never* store passwords in plain text. Use a strong hashing algorithm (e.g., bcrypt) to hash the passwords before storing them in the database.

This complete example gives you a solid foundation for building your own game leaderboard. Remember to prioritize security and add features to make it more user-friendly and robust.
👁️ Viewed: 8

Comments