Link Shortener PHP
👤 Sharing: AI
```php
<?php
// Configuration (you might want to move this to a separate config file)
$db_host = 'localhost';
$db_user = 'your_db_user'; // Replace with your database username
$db_pass = 'your_db_password'; // Replace with your database password
$db_name = 'your_db_name'; // Replace with your database name
$table_name = 'urls'; // Table to store URLs and short codes
$base_url = 'http://yourdomain.com/'; // Replace with your domain (including trailing slash)
// Database Connection
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Enable error reporting
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
// Function to generate a random short code
function generateShortCode($length = 6) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$code = '';
$max = strlen($characters) - 1;
for ($i = 0; $i < $length; $i++) {
$code .= $characters[random_int(0, $max)];
}
return $code;
}
// Function to insert a URL and short code into the database
function insertURL($pdo, $table_name, $long_url, $short_code) {
$stmt = $pdo->prepare("INSERT INTO `$table_name` (long_url, short_code, created_at) VALUES (?, ?, NOW())");
$stmt->execute([$long_url, $short_code]);
return $pdo->lastInsertId(); // Returns the ID of the newly inserted row (optional)
}
// Function to get the long URL from the database based on the short code
function getLongURL($pdo, $table_name, $short_code) {
$stmt = $pdo->prepare("SELECT long_url FROM `$table_name` WHERE short_code = ?");
$stmt->execute([$short_code]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result) {
return $result['long_url'];
} else {
return false; // Short code not found
}
}
// ---- Main Logic (Handling URL Shortening and Redirection) ----
// URL Shortening Logic (triggered when a URL is submitted)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['long_url'])) {
$long_url = filter_var($_POST['long_url'], FILTER_VALIDATE_URL); // Sanitize and validate
if ($long_url) {
// Generate a unique short code
do {
$short_code = generateShortCode();
// Check if the short code already exists (very important to avoid collisions)
$existing_url = getLongURL($pdo, $table_name, $short_code);
} while ($existing_url !== false); // Keep generating until a unique code is found
// Insert the URL and short code into the database
$insert_id = insertURL($pdo, $table_name, $long_url, $short_code);
if ($insert_id) {
$shortened_url = $base_url . $short_code;
$success_message = "Shortened URL: <a href='" . htmlspecialchars($shortened_url) . "' target='_blank'>" . htmlspecialchars($shortened_url) . "</a>";
} else {
$error_message = "Error saving URL to database.";
}
} else {
$error_message = "Invalid URL. Please enter a valid URL (e.g., http://www.example.com).";
}
}
// Redirection Logic (triggered when a short code is in the URL)
$request_uri = $_SERVER['REQUEST_URI'];
$path_parts = explode('/', trim($request_uri, '/')); // Trim leading/trailing slashes and split
if (count($path_parts) == 1 && !empty($path_parts[0])) { //Checking there is only one segment after the base URL
$short_code_from_url = $path_parts[0];
$long_url = getLongURL($pdo, $table_name, $short_code_from_url);
if ($long_url) {
header("Location: " . $long_url, true, 301); // Permanent redirect
exit; //Important to stop further script execution after redirection
} else {
// Short code not found. Display an error or a 404 page.
http_response_code(404);
$not_found_message = "Short URL not found."; // Message to show on 404 page
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>URL Shortener</title>
<style>
body {
font-family: sans-serif;
margin: 20px;
}
form {
margin-bottom: 20px;
}
input[type="text"] {
padding: 5px;
width: 300px;
}
button {
padding: 5px 10px;
cursor: pointer;
}
.error {
color: red;
}
.success {
color: green;
}
</style>
</head>
<body>
<h1>URL Shortener</h1>
<?php if (isset($error_message)): ?>
<p class="error"><?php echo htmlspecialchars($error_message); ?></p>
<?php endif; ?>
<?php if (isset($success_message)): ?>
<p class="success"><?php echo $success_message; ?></p>
<?php endif; ?>
<?php if (isset($not_found_message)): ?>
<p class="error"><?php echo htmlspecialchars($not_found_message); ?></p>
<?php endif; ?>
<form method="POST">
<label for="long_url">Enter URL:</label><br>
<input type="text" id="long_url" name="long_url" placeholder="http://www.example.com" required><br><br>
<button type="submit">Shorten!</button>
</form>
<p>Example: Enter a URL above, submit the form, and a shortened URL will be generated. Then, navigate to <code><?php echo htmlspecialchars($base_url); ?>[short_code]</code> in your browser to be redirected to the original URL.</p>
</body>
</html>
```
Key improvements and explanations:
* **Security:**
* **Prepared Statements:** Uses PDO prepared statements throughout the code. This is *critical* for preventing SQL injection vulnerabilities. Never directly embed user input into SQL queries.
* **Input Validation:** `filter_var($_POST['long_url'], FILTER_VALIDATE_URL)` validates that the user-submitted URL is a properly formatted URL. This prevents a wide range of potential issues. It also uses `htmlspecialchars()` on output to the HTML to prevent XSS attacks.
* **Error Handling:** Includes basic error handling with `try...catch` for database connection and general error messages.
* **`htmlspecialchars()`:** Used to escape output when displaying data to the user in the HTML (e.g., the shortened URL). This prevents Cross-Site Scripting (XSS) vulnerabilities.
* **CSRF Protection (Important Note):** This example *lacks* CSRF (Cross-Site Request Forgery) protection. In a production environment, you should *always* implement CSRF protection for any forms that modify data. A simple approach is to include a hidden token in your form that is validated on submission.
* **Uniqueness of Short Codes:** Includes a loop to generate short codes until a *unique* code is found. This is *essential* to avoid collisions and ensure that each short code maps to the correct URL. It retrieves the associated URL and check if the short code already exists.
* **Redirection:**
* **`header("Location: ...", true, 301);`:** Uses a 301 redirect. A 301 redirect tells the browser and search engines that the URL has moved permanently, which is good for SEO. A 302 redirect (temporary) is sometimes used, but 301 is usually more appropriate for a URL shortener.
* **`exit;`:** After the `header()` call, `exit;` is crucial. It stops the script from continuing to execute, preventing any further output or errors from interfering with the redirection.
* **Database Design:**
* Includes a `created_at` column in the `urls` table to track when the URL was shortened. This is useful for analytics, cleanup, and other purposes. Also contains the `short_code` column, which allows storing the encoded URL and the `long_url` column, which stores the unencoded URL.
* **Code Clarity and Organization:**
* **Configuration:** The database credentials and other settings are grouped at the beginning of the script for easy modification. Consider moving this to a separate configuration file.
* **Functions:** The code is broken down into functions (`generateShortCode`, `insertURL`, `getLongURL`) to improve readability and maintainability.
* **Comments:** Includes detailed comments explaining the purpose of each section of the code.
* **Error Messages:** Provides more informative error messages to the user.
* **Consistent Naming:** Uses consistent naming conventions for variables and functions.
* **404 Handling:** Includes a 404 error page if the short code is not found in the database. This is much better than displaying a blank page or an error message.
* **Database Connection:** The code now correctly connects to the database using PDO and includes error handling for connection failures.
* **Complete Example:** Provides a fully functional example that includes the HTML form, the PHP logic, and the database interaction. You can copy and paste this code and run it (after configuring the database settings).
* **No external library dependancies**: Can be executed with basic PHP and PHP database extension such as `pdo_mysql`.
* **Clean URL handling**: Correctly uses `$_SERVER['REQUEST_URI]` to handle the URL after the base URL. Splits the URI by slashes to extract the short code. This avoids potential issues with other URL parameters.
* **Error Message for invalid long URL**: It returns an error message if the URL provided is not a valid URL.
To use this code:
1. **Database Setup:**
- Create a MySQL database (e.g., `your_db_name`).
- Create a table named `urls` in your database with the following structure:
```sql
CREATE TABLE `urls` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`long_url` VARCHAR(255) NOT NULL,
`short_code` VARCHAR(20) NOT NULL UNIQUE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
2. **Configuration:**
- Update the `$db_host`, `$db_user`, `$db_pass`, `$db_name`, and `$base_url` variables in the PHP code with your actual database credentials and your domain. *Important*: Ensure that the `$base_url` includes the trailing slash (`/`).
3. **Save the code:**
- Save the PHP code as a file (e.g., `index.php`) in your web server's document root.
4. **Access the URL Shortener:**
- Open your web browser and navigate to the URL where you saved the file (e.g., `http://yourdomain.com/index.php`).
5. **Test the URL Shortener:**
- Enter a long URL in the form and click "Shorten!".
- A shortened URL will be generated. Click the link to test the redirection.
**Important Considerations for Production:**
* **CSRF Protection:** Implement CSRF protection to prevent malicious form submissions.
* **Rate Limiting:** Implement rate limiting to prevent abuse (e.g., too many shortening requests from the same IP address).
* **URL Validation:** Implement more robust URL validation to handle edge cases and potential security vulnerabilities.
* **Error Logging:** Implement proper error logging to track errors and debug issues.
* **Analytics:** Add analytics to track the usage of your URL shortener (e.g., number of clicks, geographical location).
* **Custom Short Codes:** Allow users to specify custom short codes (but be sure to validate that they are unique).
* **Database Indexing:** Add indexes to the `short_code` column in your database to improve query performance.
* **Link Expiration:** Consider adding link expiration to automatically disable short URLs after a certain period of time.
* **User Authentication:** If you want to limit access to the URL shortener, implement user authentication.
* **Caching:** Implement caching to improve performance, especially for frequently accessed short URLs.
This revised example provides a more secure, robust, and well-structured foundation for a URL shortener application. Remember to address the production considerations before deploying it to a live environment.
👁️ Viewed: 5
Comments