URL Shortener PHP, SQL

👤 Sharing: AI
Okay, here's a basic URL shortener implementation using PHP and SQL (MySQL), along with explanations.  This example focuses on functionality and clarity rather than extensive error handling or security hardening.  It's a starting point you can expand upon.

```php
<?php

// Database Configuration
$db_host = "localhost";  // Or your database host
$db_user = "root";       // Your database username
$db_pass = "";          // Your database password
$db_name = "url_shortener"; // Your database name

// Create connection
$conn = new mysqli($db_host, $db_user, $db_pass, $db_name);

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

// Helper function to generate a short code
function generateShortCode($length = 6) {
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $code = '';
    $max = strlen($characters) - 1;
    for ($i = 0; $i < $length; $i++) {
        $code .= $characters[rand(0, $max)];
    }
    return $code;
}

// Function to shorten URL
function shortenURL($longURL, $conn) {
    $shortCode = generateShortCode();

    // Check if short code already exists (rare, but possible)
    $stmt = $conn->prepare("SELECT id FROM urls WHERE short_code = ?");
    $stmt->bind_param("s", $shortCode);
    $stmt->execute();
    $stmt->store_result();

    if ($stmt->num_rows > 0) {
        $stmt->close();
        // Code already exists, generate a new one recursively.  Might want to limit recursion depth.
        return shortenURL($longURL, $conn); // Recursive call
    }

    $stmt->close();

    // Insert into database
    $stmt = $conn->prepare("INSERT INTO urls (long_url, short_code, created_at) VALUES (?, ?, NOW())");
    $stmt->bind_param("ss", $longURL, $shortCode);

    if ($stmt->execute()) {
        $stmt->close();
        return $shortCode; // Return the short code
    } else {
        $stmt->close();
        return false; // Indicate failure
    }
}


// Function to get long URL from short code
function getLongURL($shortCode, $conn) {
    $stmt = $conn->prepare("SELECT long_url FROM urls WHERE short_code = ?");
    $stmt->bind_param("s", $shortCode);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        $stmt->close();
        return $row['long_url'];
    } else {
        $stmt->close();
        return false; // Short code not found
    }
}

// --- Handle Form Submission (Shorten URL) ---
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["long_url"])) {
    $longURL = $_POST["long_url"];

    // Validate URL format (basic)
    if (filter_var($longURL, FILTER_VALIDATE_URL)) {
        $shortCode = shortenURL($longURL, $conn);

        if ($shortCode) {
            $shortenedURL = "http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . "/" . $shortCode; // Construct the shortened URL. Important: Add a trailing slash after the directory name
            $message = "Shortened URL: <a href='" . htmlspecialchars($shortenedURL) . "'>" . htmlspecialchars($shortenedURL) . "</a>";  // Display as a link. Use htmlspecialchars for security.
        } else {
            $message = "Error shortening URL.";
        }
    } else {
        $message = "Invalid URL format.";
    }
}

// --- Handle Short Code Redirect ---
$requestURI = $_SERVER['REQUEST_URI'];
$pathParts = explode('/', trim($requestURI, '/'));  // Split the URI into parts. Trim leading/trailing slashes.
if (count($pathParts) > 0) {  //Check if there are elements in the array.
    $shortCodeFromURL = $pathParts[count($pathParts) - 1];  //Get the last part of the URI, which is assumed to be the short code.
    $longURL = getLongURL($shortCodeFromURL, $conn);

    if ($longURL) {
        header("Location: " . $longURL);
        exit();
    }
}

?>

<!DOCTYPE html>
<html>
<head>
    <title>URL Shortener</title>
</head>
<body>

    <h1>URL Shortener</h1>

    <form method="post">
        <label for="long_url">Enter Long URL:</label>
        <input type="url" id="long_url" name="long_url" required>
        <button type="submit">Shorten</button>
    </form>

    <?php if (isset($message)): ?>
        <p><?php echo $message; ?></p>
    <?php endif; ?>

</body>
</html>

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

**Explanation and Key Concepts:**

1.  **Database Setup:**
    *   The code starts by defining database connection details (`$db_host`, `$db_user`, `$db_pass`, `$db_name`).  **Important:**  Replace these with your actual database credentials.
    *   It establishes a connection to the MySQL database using `mysqli`.
    *   Error handling is included to check if the connection was successful.

2.  **Database Table (`urls`)**:

    You'll need to create a table in your database to store the URL mappings.  Here's the SQL to create the table:

    ```sql
    CREATE TABLE urls (
        id INT AUTO_INCREMENT PRIMARY KEY,
        long_url VARCHAR(255) NOT NULL,
        short_code VARCHAR(10) NOT NULL UNIQUE,  -- Make sure the short code is unique
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
    ```

    *   `id`:  A unique identifier for each URL mapping (auto-incrementing primary key).
    *   `long_url`:  The original, long URL (VARCHAR, adjust the length as needed).
    *   `short_code`:  The generated short code (VARCHAR).  The `UNIQUE` constraint ensures that each short code is only used once.
    *   `created_at`:  A timestamp indicating when the URL was shortened.

3.  **`generateShortCode()` Function:**
    *   This function generates a random string of characters (alphanumeric) to serve as the short code.
    *   The `$length` parameter controls the length of the short code (default is 6).  You can adjust this.  A longer code means more possible unique URLs.

4.  **`shortenURL()` Function:**
    *   Takes the long URL and the database connection as input.
    *   Generates a unique short code using `generateShortCode()`.
    *   **Important:**  It checks if the generated short code *already exists* in the database.  This is crucial to avoid collisions. If the code exists, it calls itself recursively to generate a new one.
    *   It prepares an SQL `INSERT` statement to add the long URL, short code, and creation timestamp to the `urls` table.
    *   It uses a prepared statement (`$conn->prepare()`) to prevent SQL injection vulnerabilities.
    *   `$stmt->bind_param("ss", $longURL, $shortCode)` binds the long URL and short code as strings ("ss") to the prepared statement.
    *   `$stmt->execute()` executes the SQL query.
    *   Returns the short code if the insertion was successful, or `false` if there was an error.

5.  **`getLongURL()` Function:**
    *   Takes the short code and the database connection as input.
    *   Prepares an SQL `SELECT` statement to retrieve the long URL associated with the given short code.
    *   Uses a prepared statement for security.
    *   Executes the query and fetches the result.
    *   Returns the long URL if found, or `false` if the short code doesn't exist in the database.

6.  **Form Handling (Shorten URL):**
    *   Checks if the request method is `POST` and if the `long_url` field was submitted.
    *   Retrieves the long URL from the `$_POST` array.
    *   **URL Validation:** Uses `filter_var()` with `FILTER_VALIDATE_URL` to perform a basic check that the input is a valid URL format.  This is important to prevent invalid data from being stored in the database.
    *   Calls `shortenURL()` to get the short code.
    *   If the shortening is successful, it constructs the shortened URL (e.g., `http://yourdomain.com/shortcode`) and displays it to the user.
    *   Includes error handling for invalid URLs and database errors.

7.  **Short Code Redirection:**

    *   Retrieves the request URI using `$_SERVER['REQUEST_URI']`.
    *   Parses the URI to extract the short code (assuming the short code is the last segment of the URI).  This is done using `explode()`.
    *   Calls `getLongURL()` to retrieve the corresponding long URL.
    *   If a long URL is found, it uses the `header("Location: ...")` function to redirect the user to the original URL.
    *   `exit()` is called after `header()` to ensure that no further code is executed after the redirect.

8.  **HTML Form:**
    *   A simple HTML form allows the user to enter a long URL and submit it.
    *   The form's `method` is set to `post`.
    *   The `required` attribute ensures that the user must enter a URL.
    *   The `type="url"` attribute provides basic client-side validation for the URL.
    *   A paragraph displays the shortened URL or any error messages.

9.  **Security Considerations:**
    *   **SQL Injection Prevention:** Prepared statements (`$conn->prepare()`) are used to prevent SQL injection vulnerabilities.  Always use prepared statements when dealing with user input in SQL queries.
    *   **Cross-Site Scripting (XSS) Prevention:** `htmlspecialchars()` is used when displaying the shortened URL to prevent XSS attacks.  Always escape user-generated content before displaying it on the page.
    *   **Rate Limiting:**  Consider implementing rate limiting to prevent users from excessively shortening URLs. This can help prevent abuse.
    *   **Input Validation:**  While the code includes basic URL validation, you might want to add more robust validation to handle various URL formats and potentially block malicious URLs.
    *   **Output Encoding:** Ensure proper output encoding to prevent character encoding issues. UTF-8 is generally recommended.
    *   **HTTPS:**  Use HTTPS to encrypt the communication between the user's browser and your server.  This is essential for protecting sensitive data, especially if you're dealing with user accounts or other private information.
    *   **CSRF Protection:** For more advanced forms, consider adding CSRF (Cross-Site Request Forgery) protection.

**How to Run This Code:**

1.  **Set up a web server (e.g., Apache, Nginx) with PHP installed.**
2.  **Install MySQL (or a similar SQL database).**
3.  **Create the `url_shortener` database.**
4.  **Create the `urls` table** (using the SQL code provided above).
5.  **Configure the database connection details** in the PHP code (`$db_host`, `$db_user`, `$db_pass`, `$db_name`).
6.  **Save the PHP code as a `.php` file** (e.g., `index.php`).
7.  **Place the `.php` file in your web server's document root.**
8.  **Access the file through your web browser** (e.g., `http://localhost/index.php`).

**Example Usage:**

1.  Open the URL shortener page in your browser.
2.  Enter a long URL (e.g., `https://www.example.com/very/long/path/to/resource`).
3.  Click the "Shorten" button.
4.  The page will display the shortened URL (e.g., `http://localhost/your_project_directory/abcdef`).
5.  Click on the shortened URL. You should be redirected to the original long URL.

**Important Notes:**

*   **Error Handling:**  The code includes basic error handling, but you should add more robust error handling for production environments.
*   **Security:** This example provides a basic level of security, but you should implement more comprehensive security measures for a real-world application.  Pay particular attention to input validation, output encoding, and protection against common web vulnerabilities.
*   **Customization:** You can customize the short code length, the characters used in the short code, and the database structure to suit your needs.
*   **Base URL:** The shorted URL is constructed based on `$_SERVER['HTTP_HOST']` and `dirname($_SERVER['PHP_SELF'])`, which works fine in many cases. However, in some scenarios (e.g., behind a proxy, running in a different directory), you may need to explicitly define the base URL for your URL shortener to ensure the shortened URLs are correct.
*   **URL rewriting**:  For cleaner URLs (e.g., `http://yourdomain.com/abcdef` instead of `http://yourdomain.com/index.php/abcdef`), you can use URL rewriting (e.g., with Apache's `mod_rewrite` or Nginx configuration).
*   **Alternative database**: You can adapt this example to use other databases like PostgreSQL, but you'll need to adjust the database connection and SQL queries accordingly.

This comprehensive example should provide a good foundation for building your own URL shortener application with PHP and SQL. Remember to prioritize security and error handling as you develop your application further.
👁️ Viewed: 9

Comments