复用WordPress数据库搭建Node.js后端遇权限错误及数据定位问题求助
解决WordPress数据库复用与Node.js后端搭建问题
一、先搞定数据库连接权限错误
- 核对配置信息:仔细对比
wp-config.php里的DB_USER、DB_PASSWORD、DB_NAME,确保代码里的参数完全一致,MySQL的用户名/密码/库名是区分大小写的,别漏了特殊字符。 - 检查用户访问权限:登录PhpMyAdmin,找到对应数据库的用户,查看
Host字段是否为localhost或%(允许所有地址访问),如果是指定IP,本地Node服务可能无法连接。 - 换用稳定的数据库包:你用的
mysql包已经停止维护,建议换成mysql2,API几乎兼容,安装命令:npm install mysql2,代码里把require('mysql')改成require('mysql2/promise')(用Promise版更适配Express的异步逻辑)。 - 测试连接有效性:直接用PhpMyAdmin的登录账号密码替换代码里的参数,测试能否连接,排除
wp-config.php里的信息是否过时。
二、定位WordPress文章数据
WordPress的核心数据表前缀可以在wp-config.php的$table_prefix变量里找到(默认是wp_,也可能是自定义前缀),带这个前缀的数据库就是当前站点在用的库。核心文章相关表:
wp_posts:存储所有文章、页面、自定义文章类型,通过post_type='post'筛选文章,post_status='publish'是已发布内容,post_title、post_content、post_date是核心字段。wp_postmeta:存储文章的自定义字段(比如缩略图ID、自定义属性),通过post_id关联wp_posts的ID。wp_terms、wp_term_relationships、wp_term_taxonomy:存储文章的分类、标签,通过object_id关联wp_posts的ID,taxonomy='category'是分类,taxonomy='post_tag'是标签。
三、Node.js+Express后端CRUD搭建步骤
1. 配置数据库连接池
用连接池替代单连接,更适合高并发场景:
const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: 'localhost', user: '你的WP数据库用户名', password: '你的WP数据库密码', database: '你的WP数据库名', connectionLimit: 10, queueLimit: 0 }); module.exports = pool;
2. 编写文章CRUD路由
新建routes/posts.js:
const express = require('express'); const router = express.Router(); const pool = require('../db'); // 获取所有已发布文章 router.get('/', async (req, res) => { try { const [rows] = await pool.query(` SELECT ID, post_title, post_content, post_date, post_excerpt FROM wp_posts WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC `); res.json(rows); } catch (err) { console.error(err); res.status(500).json({ error: '获取文章失败' }); } }); // 获取单篇文章 router.get('/:id', async (req, res) => { try { const [rows] = await pool.query(` SELECT ID, post_title, post_content, post_date, post_excerpt FROM wp_posts WHERE ID = ? AND post_type = 'post' AND post_status = 'publish' `, [req.params.id]); if (rows.length === 0) return res.status(404).json({ error: '文章不存在' }); res.json(rows[0]); } catch (err) { console.error(err); res.status(500).json({ error: '获取文章失败' }); } }); // 创建文章(符合WordPress字段规范) router.post('/', async (req, res) => { const { title, content, excerpt } = req.body; try { const [result] = await pool.query(` INSERT INTO wp_posts (post_title, post_content, post_excerpt, post_type, post_status, post_date) VALUES (?, ?, ?, 'post', 'publish', NOW()) `, [title, content, excerpt]);]); res.status(201).json({ id: result.insertId, message: '文章创建成功' }); } catch (err) { console.error(err); res.status(500).json({ error: '创建文章失败' }); } }); // 更新文章 router.put('/:id', async (req, res) => { const { title, content, excerpt } = req.body; try { const [result] = await pool.query(` UPDATE wp_posts SET post_title = ?, post_content = ?, post_excerpt = ?, post_modified = NOW() WHERE ID = ? AND post_type = 'post' `, [title, content, excerpt, req.params.id]); if (result.affectedRows === 0) return res.status(404).json({ error: '文章不存在' }); res.json({ message: '文章更新成功' }); } catch (err) { console.error(err); res.status(500).json({ error: '更新文章失败' }); } }); // 删除文章(用WordPress软删除逻辑,标记为回收站) router.delete('/:id', async (req, res) => { try { const [result] = await pool.query(` UPDATE wp_posts SET post_status = 'trash' WHERE ID = ? AND post_type = 'post' `, [req.params.id]); if (result.affectedRows === 0) return res.status(404).json({ error: '文章不存在' }); res.json({ message: '文章删除成功' }); } catch (err) { console.error(err); res.status(500).json({ error: '删除文章失败' }); } }); module.exports = router;
3. 挂载路由到Express主文件
const express = require('express'); const app = express(); const postsRouter = require('./routes/posts'); app.use(express.json()); // 解析JSON请求体 app.use('/api/posts', postsRouter); const PORT = process.env.PORT || 3001; app.listen(PORT, () => { console.log(`服务运行在端口 ${PORT}`); });
关键注意事项
- 必须用参数化查询(
?占位符),避免SQL注入风险。 - 如果需要获取文章分类/标签,要关联
wp_terms等表,示例SQL:
SELECT p.ID, p.post_title, GROUP_CONCAT(t.name SEPARATOR ', ') AS categories FROM wp_posts p JOIN wp_term_relationships tr ON p.ID = tr.object_id JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN wp_terms t ON tt.term_id = t.term_id WHERE tt.taxonomy = 'category' AND p.post_type = 'post' AND p.post_status = 'publish' GROUP BY p.ID
- 文章缩略图需要从
wp_postmeta的_thumbnail_id字段获取附件ID,再去wp_posts和wp_postmeta拼接图片URL。
内容的提问来源于stack exchange,提问作者Muhammad Hossain
相关产品推荐
相关产品推荐

