如何为Flutter应用与Tailwind+HTML+JS网站共用PHP+MySQL数据库?
解决方案:Flutter + Web 共用 MySQL 数据库(PHP 后端)
核心思路是搭建PHP RESTful API作为中间层,Flutter和Web端都通过调用这个API来操作数据库,避免直接连接MySQL(不安全且跨设备/跨平台无法直接实现)。
一、PHP API 搭建(核心中间层)
1. 数据库连接配置(db_config.php)
<?php $host = 'localhost'; // 远程服务器填公网IP $dbname = 'your_database_name'; $username = 'your_db_user'; $password = 'your_db_password'; try { $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die(json_encode(['status' => 'error', 'message' => $e->getMessage()])); } ?>
2. 示例API:获取用户列表(get_users.php)
<?php require 'db_config.php'; header("Access-Control-Allow-Origin: *"); // 生产环境替换为Web端域名 header("Content-Type: application/json; charset=UTF-8"); try { $stmt = $pdo->query("SELECT id, name, email FROM users"); $users = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode(['status' => 'success', 'data' => $users]); } catch(PDOException $e) { echo json_encode(['status' => 'error', 'message' => $e->getMessage()]); } ?>
3. 示例API:添加用户(add_user.php)
<?php require 'db_config.php'; header("Access-Control-Allow-Origin: *"); header("Content-Type: application/json; charset=UTF-8"); header("Access-Control-Allow-Methods: POST"); header("Access-Control-Allow-Headers: Content-Type"); $data = json_decode(file_get_contents("php://input")); if(!isset($data->name) || !isset($data->email)) { echo json_encode(['status' => 'error', 'message' => '缺少必填字段']); exit; } try { $stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)"); $stmt->bindParam(':name', $data->name); $stmt->bindParam(':email', $data->email); $stmt->execute(); echo json_encode(['status' => 'success', 'message' => '用户添加成功', 'id' => $pdo->lastInsertId()]); } catch(PDOException $e) { echo json_encode(['status' => 'error', 'message' => $e->getMessage()]); } ?>
二、Web端(HTML/JS)调用API示例
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>用户管理</title> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <h2>用户列表</h2> <div id="userList"></div> <h3>添加用户</h3> <input type="text" id="userName" placeholder="用户名"> <input type="email" id="userEmail" placeholder="邮箱"> <button onclick="addUser()">添加</button> <script> async function getUsers() { try { const response = await axios.get('http://你的服务器IP/api/get_users.php'); if(response.data.status === 'success') { let html = '<ul>'; response.data.data.forEach(user => { html += `<li>${user.name} - ${user.email}</li>`; }); html += '</ul>'; document.getElementById('userList').innerHTML = html; } else { alert('获取失败:' + response.data.message); } } catch(error) { alert('请求出错:' + error.message); } } async function addUser() { const name = document.getElementById('userName').value; const email = document.getElementById('userEmail').value; if(!name || !email) { alert('请填写完整信息'); return; } try { const response = await axios.post('http://你的服务器IP/api/add_user.php', { name: name, email: email }); if(response.data.status === 'success') { alert('添加成功'); getUsers(); document.getElementById('userName').value = ''; document.getElementById('userEmail').value = ''; } else { alert('添加失败:' + response.data.message); } } catch(error) { alert('请求出错:' + error.message); } } window.onload = getUsers; </script> </body> </html>
三、Flutter端调用API示例
1. 添加依赖(pubspec.yaml)
dependencies: flutter: sdk: flutter http: ^1.1.0 json_annotation: ^4.8.1 dev_dependencies: build_runner: ^2.4.4 json_serializable: ^6.7.0
2. 模型类(user.dart)
import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class User { final int id; final String name; final String email; User({required this.id, required this.name, required this.email}); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); }
运行flutter pub run build_runner build生成序列化代码。
3. API调用逻辑(api_service.dart)
import 'dart:convert'; import 'package:http/http.dart' as http; import 'user.dart'; class ApiService { static const String baseUrl = 'http://你的服务器IP/api'; static Future<List<User>> getUsers() async { final response = await http.get(Uri.parse('$baseUrl/get_users.php')); if (response.statusCode == 200) { final data = json.decode(response.body); if (data['status'] == 'success') { return (data['data'] as List).map((item) => User.fromJson(item)).toList(); } else { throw Exception(data['message']); } } else { throw Exception('请求失败:${response.statusCode}'); } } static Future<void> addUser(String name, String email) async { final response = await http.post( Uri.parse('$baseUrl/add_user.php'), headers: {'Content-Type': 'application/json'}, body: json.encode({'name': name, 'email': email}), ); final data = json.decode(response.body); if (data['status'] != 'success') { throw Exception(data['message']); } } }
4. 页面示例(user_page.dart)
import 'package:flutter/material.dart'; import 'api_service.dart'; import 'user.dart'; class UserPage extends StatefulWidget { const UserPage({super.key}); @override State<UserPage> createState() => _UserPageState(); } class _UserPageState extends State<UserPage> { List<User> _users = []; final _nameController = TextEditingController(); final _emailController = TextEditingController(); @override void initState() { super.initState(); _fetchUsers(); } void _fetchUsers() async { try { final users = await ApiService.getUsers(); setState(() { _users = users; }); } catch (e) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('获取用户失败:$e'))); } } void _addUser() async { final name = _nameController.text.trim(); final email = _emailController.text.trim(); if (name.isEmpty || email.isEmpty) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请填写完整信息'))); return; } try { await ApiService.addUser(name, email); ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('添加成功'))); _nameController.clear(); _emailController.clear(); _fetchUsers(); } catch (e) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('添加失败:$e'))); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('用户管理')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _nameController, decoration: const InputDecoration(labelText: '用户名'), ), TextField( controller: _emailController, decoration: const InputDecoration(labelText: '邮箱'), keyboardType: TextInputType.emailAddress, ), const SizedBox(height: 16), ElevatedButton(onPressed: _addUser, child: const Text('添加用户')), const SizedBox(height: 24), Expanded( child: ListView.builder( itemCount: _users.length, itemBuilder: (context, index) { final user = _users[index]; return ListTile( title: Text(user.name), subtitle: Text(user.email), ); }, ), ), ], ), ), ); } }
关键注意事项
- 跨域问题:生产环境替换
Access-Control-Allow-Origin: *为Web端具体域名,比如header("Access-Control-Allow-Origin: https://your-web-domain.com"); - 安全性:
- 禁止在前端代码中暴露数据库密码
- PHP API必须用PDO预处理语句防止SQL注入
- 可添加API密钥验证,在请求头携带密钥,PHP端校验
- 服务器部署:PHP文件需部署在支持PHP的服务器(Apache/Nginx),远程数据库需允许服务器IP访问
- 测试流程:先用Postman验证API功能,再对接Web和Flutter端
内容的提问来源于stack exchange,提问作者Sanjeev Chauhan
相关产品推荐
相关产品推荐

