You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在PHP中实现基于posts表的无问号自定义文章URL

嘿,这个需求其实就是URL重写/路由映射的经典场景——把美观的RESTful风格URL转成后端能识别的查询逻辑,同时让浏览器地址栏保持干净无?。我分几个关键步骤给你拆解,不管你用传统服务器还是现代后端框架都能搞定:

一、先搞定Web服务器的URL重写(传统后端必备)

浏览器发起www.example.com/posts/10110501请求时,服务器默认会去找posts目录下名为10110501的文件,显然这不存在,所以需要把这个请求转发给你的后端入口脚本(比如index.phpapp.js),同时把编号传递过去。

如果你用Apache:

在网站根目录创建.htaccess文件,添加以下规则:

RewriteEngine On
# 跳过真实存在的文件/目录(比如静态图片、CSS),避免干扰
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 把/posts/xxx格式的URL重写为/index.php?post_id=xxx,[L]表示这是最后一条规则
RewriteRule ^posts/(\d+)$ index.php?post_id=$1 [L]

如果你用Nginx:

在你的server配置块里添加以下规则(推荐用try_files替代if,更符合Nginx的最佳实践):

location /posts {
    # 先尝试访问真实文件/目录,不存在就转发给后端入口
    try_files $uri $uri/ /index.php?post_id=$1;
    # 提取URL中的数字编号,传递给后端
    rewrite ^/posts/(\d+)$ /index.php?post_id=$1 break;
}

二、后端脚本接收编号并查询文章

现在后端入口脚本已经能拿到post_id参数了,接下来就是查询数据库渲染页面:

举个PHP的例子:

<?php
// 假设你已经用PDO连接了数据库
if (isset($_GET['post_id'])) {
    $postId = $_GET['post_id'];
    // 一定要用预处理语句,防止SQL注入!
    $query = "SELECT * FROM posts WHERE random_id = ?";
    $stmt = $pdo->prepare($query);
    $stmt->execute([$postId]);
    $post = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($post) {
        // 渲染单篇文章页面,比如输出标题、内容
        echo "<h1>{$post['title']}</h1>";
        echo "<div>{$post['content']}</div>";
    } else {
        // 编号不存在时返回404
        http_response_code(404);
        echo "文章不存在";
    }
}
?>

如果用Node.js(Express框架):

其实Express本身支持路由匹配,甚至可以跳过服务器重写,直接在代码里配置:

const express = require('express');
const app = express();
const mysql = require('mysql2/promise'); // 用mysql2示例

// 定义路由,:postId是动态参数,匹配/posts/后面的数字
app.get('/posts/:postId', async (req, res) => {
    const postId = req.params.postId;
    // 连接数据库查询
    const connection = await mysql.createConnection({host:'localhost', user:'root', password:'xxx', database:'your_db'});
    const [rows] = await connection.execute('SELECT * FROM posts WHERE random_id = ?', [postId]);
    
    if (rows.length > 0) {
        // 用模板引擎渲染页面,比如EJS
        res.render('post', { post: rows[0] });
    } else {
        res.status(404).send('文章不存在');
    }
});

app.listen(3000, () => console.log('服务器启动'));

三、前端要生成正确的链接

最后一步,在文章摘要列表里,链接要直接指向干净的URL,比如PHP里:

<!-- 假设你从数据库查询出了文章列表 -->
<?php foreach ($posts as $post): ?>
    <div class="post-summary">
        <h3><a href="/posts/<?php echo $post['random_id']; ?>"><?php echo $post['title']; ?></a></h3>
        <p><?php echo $post['excerpt']; ?></p>
    </div>
<?php endforeach; ?>

这样用户点击后,地址栏就会显示www.example.com/posts/10110501,完全没有?符号。

额外注意事项

  • 确保数据库里的random_id唯一索引,避免多个文章对应同一个URL的问题。
  • 处理404场景:如果用户手动输入不存在的编号,后端要返回404页面,提升用户体验。
  • 如果你用Laravel、Vue Router这类现代框架,它们本身有成熟的路由系统,直接配置路由规则即可,不用手动写服务器重写规则。

内容的提问来源于stack exchange,提问作者Tim T. Joe

火山引擎 最新活动