PHP LogoURL Shortener

A URL shortener is an online service or application that converts a long Uniform Resource Locator (URL) into a much shorter, unique URL. This shorter URL typically redirects users to the original long URL when accessed.

Why Use a URL Shortener?
1. Readability and Aesthetics: Long, complex URLs can look messy and be difficult to share, especially in print or presentations. Shortened URLs are cleaner and more appealing.
2. Social Media Character Limits: Platforms like Twitter have strict character limits. Short URLs allow users to include links without consuming too many characters.
3. Click Tracking and Analytics: Many URL shorteners provide analytics on how many times a link has been clicked, the geographical location of clicks, and the referring sources. This data is invaluable for marketing campaigns.
4. Memorability: Shorter URLs are easier to remember and type manually, though custom short URLs (e.g., bit.ly/MyCampaign) enhance this further.

How URL Shorteners Work:
1. Input: A user provides a long URL to the shortener service.
2. Short Code Generation: The service generates a unique, short alphanumeric string (the 'short code' or 'alias'). This code is typically 5-10 characters long and is designed to be unique within the system.
3. Mapping Storage: The long URL is stored in a database, associated with its newly generated short code. This mapping is crucial for redirection.
4. Short URL Creation: The short code is appended to the shortener's domain (e.g., `https://your-shortener.com/xyz123`). This forms the complete short URL.
5. Redirection: When a user accesses the short URL (e.g., `https://your-shortener.com/xyz123`), the shortener service looks up `xyz123` in its database. It retrieves the corresponding long URL and issues an HTTP 301 (Permanent Redirect) or 302 (Found/Temporary Redirect) status code, along with the original long URL in the `Location` header. The user's browser then automatically redirects to the original long URL.

Key Components of a URL Shortener:
* Database: To store the mapping between short codes and long URLs (e.g., MySQL, PostgreSQL, MongoDB).
* Unique Short Code Generator: An algorithm to produce short, unique strings. This could involve base62 encoding sequential IDs, generating random strings, or a combination.
* API/User Interface: For users to submit long URLs and retrieve short ones.
* Redirection Logic: Server-side code (e.g., PHP, Python, Node.js) to handle incoming short URLs and perform the HTTP redirection.

Example Code

<?php

// --- Configuration ---
$dataFile = 'urls.json'; // A simple JSON file to store URL mappings for this example

// Determine the base URL for shortened links. This assumes the PHP script is directly accessible.
$shortUrlBase = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . "?s=";

// --- Helper Functions ---

/
 * Generates a random alphanumeric string for use as a short code.
 * @param int $length The desired length of the short code.
 * @return string A random string.
 */
function generateRandomString($length = 6) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

/
 * Loads URL mappings from the data file.
 * @param string $dataFile Path to the JSON data file.
 * @return array An associative array of mappings (shortCode => longUrl).
 */
function loadMappings($dataFile) {
    if (!file_exists($dataFile)) {
        // If the file doesn't exist, create an empty one
        file_put_contents($dataFile, json_encode([]));
    }
    $content = file_get_contents($dataFile);
    return json_decode($content, true); // true for associative array
}

/
 * Saves URL mappings to the data file.
 * @param string $dataFile Path to the JSON data file.
 * @param array $mappings An associative array of mappings.
 */
function saveMappings($dataFile, $mappings) {
    file_put_contents($dataFile, json_encode($mappings, JSON_PRETTY_PRINT));
}

// --- Main Logic ---
$message = ''; // Message to display to the user
$shortenedUrl = ''; // The generated short URL

if (isset($_GET['s']) && !empty($_GET['s'])) {
    // --- Handle Redirection for a Short URL ---
    $shortCode = $_GET['s'];
    $mappings = loadMappings($dataFile);

    if (isset($mappings[$shortCode])) {
        $longUrl = $mappings[$shortCode];
        // Perform HTTP 302 (Found) redirection
        header("Location: " . $longUrl, true, 302);
        exit(); // Important to exit after redirection
    } else {
        $message = "Short URL not found or expired.";
        // Optionally, redirect to homepage or a custom 404 page
        // header("Location: " . $_SERVER['PHP_SELF']); exit();
    }
} elseif (isset($_POST['long_url']) && !empty($_POST['long_url'])) {
    // --- Handle Shortening a New URL ---
    $longUrl = filter_var($_POST['long_url'], FILTER_SANITIZE_URL); // Sanitize the URL

    if (filter_var($longUrl, FILTER_VALIDATE_URL)) {
        $mappings = loadMappings($dataFile);

        // Check if the long URL has already been shortened
        $existingShortCode = array_search($longUrl, $mappings);
        if ($existingShortCode !== false) {
            $shortenedUrl = $shortUrlBase . $existingShortCode;
            $message = "This URL was already shortened!";
        } else {
            // Generate a unique short code
            $shortCode = generateRandomString();
            // Ensure the generated short code is truly unique
            while (isset($mappings[$shortCode])) {
                $shortCode = generateRandomString();
            }

            // Store the new mapping
            $mappings[$shortCode] = $longUrl;
            saveMappings($dataFile, $mappings);

            $shortenedUrl = $shortUrlBase . $shortCode;
            $message = "URL shortened successfully!";
        }
    } else {
        $message = "Please enter a valid URL.";
    }
}

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP URL Shortener</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 20px; background-color: #f0f2f5; color: #333; display: flex; justify-content: center; align-items: center; min-height: 100vh; }
        .container { background: #fff; padding: 40px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); max-width: 600px; width: 100%; text-align: center; }
        h1 { color: #007bff; margin-bottom: 30px; font-size: 2.2em; }
        form { display: flex; flex-direction: column; gap: 20px; }
        label { font-size: 1.1em; color: #555; text-align: left; margin-bottom: -10px; }
        input[type="url"] { padding: 12px 15px; border: 1px solid #ced4da; border-radius: 6px; font-size: 1em; width: 100%; box-sizing: border-box; transition: border-color 0.3s; }
        input[type="url"]:focus { border-color: #007bff; outline: none; box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25); }
        button { padding: 12px 25px; background-color: #007bff; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 1.1em; transition: background-color 0.3s ease, transform 0.2s ease; margin-top: 10px; }
        button:hover { background-color: #0056b3; transform: translateY(-1px); }
        .message { margin-top: 25px; padding: 12px; border-radius: 6px; font-weight: bold; font-size: 0.95em; text-align: left; }
        .message.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .message.error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
        .result { margin-top: 25px; padding: 15px; background-color: #e9f7ff; border: 1px solid #b3d9ff; border-radius: 6px; word-wrap: break-word; text-align: left; }
        .result strong { display: block; margin-bottom: 8px; color: #0056b3; }
        .result a { color: #007bff; text-decoration: none; font-weight: bold; transition: color 0.3s; }
        .result a:hover { text-decoration: underline; color: #0056b3; }
    </style>
</head>
<body>
    <div class="container">
        <h1>PHP URL Shortener</h1>

        <?php if (!empty($message)): ?>
            <div class="message <?php echo strpos($message, 'successfully') !== false || strpos($message, 'already shortened') !== false ? 'success' : 'error'; ?>">
                <?php echo htmlspecialchars($message); ?>
            </div>
        <?php endif; ?>

        <form method="POST">
            <label for="long_url">Enter a long URL to shorten:</label>
            <input type="url" id="long_url" name="long_url" placeholder="https://example.com/very/long/path/to/your/resource/page" required>
            <button type="submit">Shorten URL</button>
        </form>

        <?php if (!empty($shortenedUrl)): ?>
            <div class="result">
                <strong>Your shortened URL is:</strong>
                <a href="<?php echo htmlspecialchars($shortenedUrl); ?>" target="_blank" rel="noopener noreferrer">
                    <?php echo htmlspecialchars($shortenedUrl); ?>
                </a>
            </div>
        <?php endif; ?>
    </div>
</body>
</html>