Short URL source code sharing

演示 https://zx.loc.cc

Code

<?php
/**
 * Short URL generator
 */
class ShortUrlDB {
    private $db;

    public function __construct($dbPath = 'shorturl.db') {
        $this->db = new PDO('sqlite:' . $dbPath);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->initDatabase();
    }

    private function initDatabase() {
        $this->db->exec("CREATE TABLE IF NOT EXISTS short_urls (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            long_url TEXT NOT NULL,
            short_code VARCHAR(10) UNIQUE NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            clicks INTEGER DEFAULT 0
        )");
        $this->db->exec("CREATE INDEX IF NOT EXISTS idx_short_code ON short_urls(short_code)");
    }

    public function getDB() {
        return $this->db;
    }
}

class ShortUrlGenerator {
    private $db;
    private const CHARS = "0123456789abcdefghijklmnopqrstuvwxyz";

    public function __construct($db) {
        $this->db = $db;
    }

    public function generateShortCode($url) {
        $hash = crc32($url . microtime());
        $num = sprintf("%u", $hash);

        $code = '';
        while ($num > 0) {
            $code = self::CHARS[$num % 36] . $code;
            $num = intval($num / 36);
        }

        return str_pad(substr($code, 0, 6), 6, '0', STR_PAD_LEFT);
    }

    public function saveShortUrl($longUrl, $customCode = '') {
        // Normalize URL
        if (!preg_match("~^(?:f|ht)tps?://~i", $longUrl)) {
            $longUrl = "http://" . $longUrl;
        }

        // Check if already exists
        $stmt = $this->db->prepare("SELECT short_code FROM short_urls WHERE long_url = ?");
        $stmt->execute([$longUrl]);
        if ($result = $stmt->fetch()) {
            return $result['short_code'];
        }

        // Generate or validate shortcode
        if ($customCode) {
            if (!preg_match('/^[a-zA-Z0-9]{1,10}$/', $customCode)) {
                throw new Exception("Invalid shortcode format");
            }
            if ($this->shortcodeExists($customCode)) {
                throw new Exception("Shortcode already exists");
            }
            $shortCode = $customCode;
        } else {
            $shortCode = $this->generateShortCode($longUrl);
            $attempts = 0;
            while ($this->shortcodeExists($shortCode) && $attempts < 3) {
                $shortCode = $this->generateShortCode($longUrl . $attempts);
                $attempts++;
            }
        }

        // Insert data
        $stmt = $this->db->prepare("INSERT INTO short_urls (long_url, short_code) VALUES (?, ?)");
        $stmt->execute([$longUrl, $shortCode]);

        return $shortCode;
    }

    public function shortcodeExists($shortCode) {
        $stmt = $this->db->prepare("SELECT 1 FROM short_urls WHERE short_code = ? LIMIT 1");
        $stmt->execute([$shortCode]);
        return (bool)$stmt->fetch();
    }

    public function getLongUrl($shortCode) {
        $stmt = $this->db->prepare("SELECT long_url FROM short_urls WHERE short_code = ?");
        $stmt->execute([$shortCode]);

        if ($result = $stmt->fetch()) {
            // Update click count
            $this->db->prepare("UPDATE short_urls SET clicks = clicks + 1 WHERE short_code = ?")
                     ->execute([$shortCode]);
            return $result['long_url'];
        }

        return false;
    }
}

/**
 * Get base URL
 */
function getBaseUrl() {
    $is_https = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off');

    if (!$is_https && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
        $protos = explode(',', strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']));
        $is_https = in_array('https', $protos, true);
    }

    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? '';
    
    // Get current directory path
    $scriptDir = dirname($_SERVER['SCRIPT_NAME'] ?? '');
    if ($scriptDir === '/' || $scriptDir === '\\\\') {
        $scriptDir = '';
    }

    $baseUrl = ($is_https ? 'https://' : 'http://') . $host . $scriptDir;
    return rtrim($baseUrl, '/') . '/';
}

// Main program logic
$db = new ShortUrlDB();
$shortUrlGen = new ShortUrlGenerator($db->getDB());
$baseUrl = getBaseUrl();

// Get request path
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$shortCode = ltrim($path, '/');

// If shortcode, redirect
if ($shortCode && !in_array($shortCode, ['', 'index.php'])) {
    if ($longUrl = $shortUrlGen->getLongUrl($shortCode)) {
        header('Location: ' . $longUrl, true, 301);
        exit;
    } else {
        // http_response_code(404);
        echo '<html><body><h2>404</h2><a href="' . $baseUrl . '">返回</a></body></html>';
        exit;
    }
}

// Handle form submission
$message = '';
$shortUrl = '';
if ($_POST['url'] ?? false) {
    $longUrl = trim($_POST['url']);
    $customCode = trim($_POST['custom_code'] ?? '');

    if (filter_var($longUrl, FILTER_VALIDATE_URL)) {
        try {
            $code = $shortUrlGen->saveShortUrl($longUrl, $customCode);
            $shortUrl = $baseUrl . $code;
            $message = "Success!";
        } catch (Exception $e) {
            $message = "Error: " . $e->getMessage();
        }
    } else {
        $message = "Invalid URL format";
    }
}

// Display page
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>短网址生成器</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; font-family: system-ui, sans-serif; }
        body { background: #f5f7fa; padding: 20px; min-height: 100vh; display: flex; justify-content: center; align-items: center; }
        .container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); max-width: 480px; width: 100%; }
        h1 { text-align: center; margin-bottom: 20px; color: #2c3e50; }
        .message { padding: 10px; margin-bottom: 15px; border-radius: 4px; text-align: center; }
        .success { background: #d4edda; color: #155724; }
        .error { background: #f8d7da; color: #721c24; }
        .form-group { margin-bottom: 15px; }
        label { display: block; margin-bottom: 5px; font-weight: 500; }
        input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; }
        input:focus { outline: none; border-color: #3498db; }
        small { color: #666; font-size: 12px; margin-top: 3px; }
        button { width: 100%; background: #3498db; color: white; border: none; padding: 10px; border-radius: 4px; font-size: 14px; cursor: pointer; }
        button:hover { background: #2980b9; }
        .result { margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 4px; }
        .copy-btn { background: #27ae60; margin-top: 8px; padding: 6px 10px; font-size: 12px; width: auto; }
    </style>
</head>
<body>
    <div class="container">
        <h1>短网址生成器</h1>

        <?php if ($message): ?>
            <div class="message <?php echo strpos($message, '成功') !== false ? 'success' : 'error'; ?>">
                <?php echo htmlspecialchars($message); ?>
            </div>
        <?php endif; ?>

        <form method="POST">
            <div class="form-group">
                <label for="url">长网址</label>
                <input type="url" name="url" placeholder="https://example.com" value="<?php echo htmlspecialchars($_POST['url'] ?? ''); ?>" required>
            </div>

            <div class="form-group">
                <label for="custom_code">自定义短码(可选)</label>
                <input type="text" name="custom_code" placeholder="myurl" value="<?php echo htmlspecialchars($_POST['custom_code'] ?? ''); ?>" maxlength="10">
                <small>字母数字,1-10位</small>
            </div>

            <button type="submit">生成短网址</button>
        </form>

        <?php if ($shortUrl): ?>
            <div class="result">
                <strong>短网址</strong>
                <div style="word-break: break-all; margin: 5px 0; color: #3498db;"><?php echo htmlspecialchars($shortUrl); ?></div>
                <button class="copy-btn" onclick="copyText('<?php echo htmlspecialchars($shortUrl); ?>')">复制链接</button>
            </div>
        <?php endif; ?>
    </div>

    <script>
        function copyText(text) {
            navigator.clipboard.writeText(text.trim()).then(() => {
                const btn = event.target;
                btn.textContent = '已复制';
                setTimeout(() => btn.textContent = '复制链接', 1500);
            }).catch(() => {
                const textarea = document.createElement('textarea');
                textarea.value = text.trim();
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);

                const btn = event.target;
                btn.textContent = '已复制';
                setTimeout(() => btn.textContent = '复制链接', 1500);
            });
        }
    </script>
</body>
</html>

## Static Rules

```txt
#.htaccess - Apache URL rewrite rules[1](@ref)
RewriteEngine On

# If the requested file or directory does not exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]

#. Nginx rewrite rules[1](@ref)
location / {
    try_files $uri $uri/ /index.php?$args;
}
11 Likes

谢谢分享

2 Likes

感谢分享

1 Like

502了

1 Like

502了吗!我这边访问正常呀

现在正常了

宝塔的nginx防火墙忘记开启CDN了

1 Like

谢谢分享,可以在上面优化,加个简单的点击统计之类的

1 Like

感謝無私分享~點讚~

https://zx.loc.cc/loc

测试一下。如果有后台管理就完美了。

感谢大佬的分享

谢谢分享。收藏了。

感谢大佬的分享

谢谢分享,做了点修改,用上了:https://urls.zone.id

1 Like

感谢分享, 不错的玩意

感谢分享,正好要做个类似的

添加伪静态就一直转圈 不知道为啥

感谢,学习

好分享