You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 14:45:03