Paramclasses Academy - Blog

Tutorials Details

←
Post 27 of 40
→

How to Connect Flutter with PHP and MySQL Using REST APIs | Param Classes

How to Connect Flutter with PHP and MySQL Using REST APIs | Param Classes

November 3, 2026

❖ How to Connect Flutter with PHP and MySQL Using REST APIs

❖ Welcome to Param Classes!

Welcome to another practical Flutter App Development tutorial at Param Classes!

In previous tutorials, we learned how to send HTTP requests using GET, POST, PUT, and DELETE methods. We also understood how Flutter communicates with REST APIs and receives JSON data from a server.

Now, let's connect Flutter with a real backend.

Suppose you are developing a Student Management Application. You want to save student details in a MySQL database and display those details inside your Flutter application.

For this purpose, we can use:

  • Flutter: Frontend mobile application.

  • PHP: Backend programming language.

  • MySQL: Database for storing student records.

  • REST API: Communication between Flutter and PHP.

  • HTTP Package: Sends requests from Flutter to PHP.

In this tutorial, we will build a basic Student Management API using PHP and MySQL and connect it with Flutter.

✦ 1. Understand Flutter, PHP, MySQL and REST API

Before starting practical development, understand how these technologies work together.

Flutter: Flutter creates the mobile application interface. Users can enter student information, click buttons, and view records.

PHP: PHP receives requests from Flutter, processes the data, communicates with MySQL, and returns responses.

MySQL: MySQL stores student information in database tables.

REST API: REST API provides endpoints through which Flutter communicates with PHP.

The complete communication flow looks like this:

Flutter App → HTTP Request → PHP REST API → MySQL Database

When the PHP API completes the operation, it returns a JSON response:

MySQL Database → PHP API → JSON Response → Flutter App

✦ 2. Install the Required Software

Before creating the application, make sure you have the following software installed:

  1. Flutter SDK

  2. Android Studio or VS Code

  3. PHP

  4. MySQL

  5. XAMPP

  6. Postman (optional, for testing APIs)

For beginners, XAMPP is a convenient way to run Apache and MySQL locally.

Official websites:

Start Apache and MySQL from the XAMPP Control Panel.

✦ 3. Create a MySQL Database

Open your browser and visit:

http://localhost/phpmyadmin

Create a database named:

flutter_student_db

Now open the SQL tab and execute:

CREATE DATABASE flutter_student_db;

USE flutter_student_db;

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    mobile VARCHAR(15) NOT NULL,
    course VARCHAR(100) NOT NULL
);

Our students table contains four columns:

Column Purpose
id Unique student ID
name Student name
mobile Student mobile number
course Student course

The id column automatically generates a unique ID for every new student.

✦ 4. Create a PHP API Project

Open your XAMPP installation directory.

Go to:

C:\xampp\htdocs

Create a new folder:

flutter_api

Inside this folder, create a PHP file:

db.php

Add the following database connection code:

<?php

header("Content-Type: application/json; charset=UTF-8");

$host = "localhost";
$username = "root";
$password = "";
$database = "flutter_student_db";

$conn = new mysqli(
    $host,
    $username,
    $password,
    $database
);

if ($conn->connect_error) {

    http_response_code(500);

    echo json_encode([
        "status" => false,
        "message" => "Database connection failed"
    ]);

    exit;
}

$conn->set_charset("utf8mb4");

?>

Understanding the code:

  • $host contains the MySQL server address.

  • $username contains the database username.

  • $password contains the database password.

  • $database contains the database name.

  • new mysqli() creates a database connection.

  • set_charset() sets the character encoding.

The default XAMPP MySQL username is commonly root, with an empty password in a fresh local installation. If your database credentials are different, update them accordingly.

✦ 5. Create a PHP API to Insert Student Data

Now create a file:

insert_student.php

Add this code:

<?php

include "db.php";

if ($_SERVER["REQUEST_METHOD"] == "POST") {

    $name = $_POST["name"] ?? "";
    $mobile = $_POST["mobile"] ?? "";
    $course = $_POST["course"] ?? "";

    if (
        empty($name) ||
        empty($mobile) ||
        empty($course)
    ) {

        echo json_encode([
            "status" => false,
            "message" => "All fields are required"
        ]);

        exit;
    }

    $stmt = $conn->prepare(
        "INSERT INTO students (name, mobile, course)
         VALUES (?, ?, ?)"
    );

    $stmt->bind_param(
        "sss",
        $name,
        $mobile,
        $course
    );

    if ($stmt->execute()) {

        echo json_encode([
            "status" => true,
            "message" => "Student inserted successfully"
        ]);

    } else {

        http_response_code(500);

        echo json_encode([
            "status" => false,
            "message" => "Insert failed"
        ]);

    }

    $stmt->close();

} else {

    http_response_code(405);

    echo json_encode([
        "status" => false,
        "message" => "POST method required"
    ]);

}

$conn->close();

?>

Explanation:

  1. include "db.php" connects PHP with MySQL.

  2. $_SERVER["REQUEST_METHOD"] checks the request method.

  3. $_POST receives form data.

  4. prepare() prepares the SQL statement.

  5. bind_param() safely binds the values.

  6. execute() executes the INSERT query.

  7. json_encode() returns the response in JSON format.

Using prepared statements helps protect database operations against SQL injection.

✦ 6. Create a PHP API to Fetch Student Records

Create another file:

fetch_students.php

Add:

<?php

include "db.php";

if ($_SERVER["REQUEST_METHOD"] == "GET") {

    $result = $conn->query(
        "SELECT id, name, mobile, course
         FROM students
         ORDER BY id DESC"
    );

    $students = [];

    while ($row = $result->fetch_assoc()) {

        $students[] = $row;

    }

    echo json_encode([
        "status" => true,
        "data" => $students
    ]);

} else {

    http_response_code(405);

    echo json_encode([
        "status" => false,
        "message" => "GET method required"
    ]);

}

$conn->close();

?>

This API retrieves all student records from MySQL and returns them as JSON.

For example, the response may look like this:

{
  "status": true,
  "data": [
    {
      "id": 1,
      "name": "Rahul",
      "mobile": "9876543210",
      "course": "Flutter"
    },
    {
      "id": 2,
      "name": "Amit",
      "mobile": "9876543211",
      "course": "PHP"
    }
  ]
}

✦ 7. Create a PHP API to Update Student Records

Create:

update_student.php

Add:

<?php

include "db.php";

if ($_SERVER["REQUEST_METHOD"] == "POST") {

    $id = $_POST["id"] ?? "";
    $name = $_POST["name"] ?? "";
    $mobile = $_POST["mobile"] ?? "";
    $course = $_POST["course"] ?? "";

    if (
        empty($id) ||
        empty($name) ||
        empty($mobile) ||
        empty($course)
    ) {

        echo json_encode([
            "status" => false,
            "message" => "All fields are required"
        ]);

        exit;
    }

    $stmt = $conn->prepare(
        "UPDATE students
         SET name = ?, mobile = ?, course = ?
         WHERE id = ?"
    );

    $stmt->bind_param(
        "sssi",
        $name,
        $mobile,
        $course,
        $id
    );

    if ($stmt->execute()) {

        echo json_encode([
            "status" => true,
            "message" => "Student updated successfully"
        ]);

    } else {

        http_response_code(500);

        echo json_encode([
            "status" => false,
            "message" => "Update failed"
        ]);

    }

    $stmt->close();

} else {

    http_response_code(405);

    echo json_encode([
        "status" => false,
        "message" => "POST method required"
    ]);

}

$conn->close();

?>

This API updates student details using the student ID.

✦ 8. Create a PHP API to Delete Student Records

Create:

delete_student.php

Add:

<?php

include "db.php";

if ($_SERVER["REQUEST_METHOD"] == "POST") {

    $id = $_POST["id"] ?? "";

    if (empty($id)) {

        echo json_encode([
            "status" => false,
            "message" => "Student ID is required"
        ]);

        exit;
    }

    $stmt = $conn->prepare(
        "DELETE FROM students WHERE id = ?"
    );

    $stmt->bind_param("i", $id);

    if ($stmt->execute()) {

        if ($stmt->affected_rows > 0) {

            echo json_encode([
                "status" => true,
                "message" => "Student deleted successfully"
            ]);

        } else {

            echo json_encode([
                "status" => false,
                "message" => "Student not found"
            ]);

        }

    } else {

        http_response_code(500);

        echo json_encode([
            "status" => false,
            "message" => "Delete failed"
        ]);

    }

    $stmt->close();

} else {

    http_response_code(405);

    echo json_encode([
        "status" => false,
        "message" => "POST method required"
    ]);

}

$conn->close();

?>

For this beginner example, update and delete use POST requests. A REST API can also use PUT and DELETE methods when the backend is designed to support them.

✦ 9. Test PHP APIs Before Connecting Flutter

Before writing Flutter code, test your backend APIs.

Open the following URL in your browser:

http://localhost/flutter_api/fetch_students.php

You should receive a JSON response containing the student records.

For POST APIs, use Postman or another API testing tool.

Insert API:

http://localhost/flutter_api/insert_student.php

Select POST and choose form-data or x-www-form-urlencoded.

Add these fields:

  • name: Rahul

  • mobile: 9876543210

  • course: Flutter

Update API:

http://localhost/flutter_api/update_student.php

Select POST and send:

  • id: 1

  • name: Rahul Kumar

  • mobile: 9876543210

  • course: Advanced Flutter

Delete API:

http://localhost/flutter_api/delete_student.php

Select POST and send:

  • id: 1

Testing PHP APIs separately makes it easier to identify backend errors before connecting Flutter.

✦ 10. Create a Flutter Project

Now create a Flutter application:

flutter create student_app

Open the project in Android Studio or VS Code.

Install the HTTP package:

flutter pub add http

Open lib/main.dart and import:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

✦ 11. Understand the API URL in Flutter

When using XAMPP on your computer, the API address depends on where Flutter is running.

For Android Emulator:

http://10.0.2.2/flutter_api/

For a physical Android phone:

http://YOUR_COMPUTER_IP/flutter_api/

For example:

http://192.168.1.5/flutter_api/

Replace the example IP with your computer's actual local network IP. Your phone and computer should be connected to the same network, and your firewall must allow the connection.

Important: Do not use localhost inside the Android emulator to access your computer's XAMPP server. In the emulator, localhost refers to the emulator itself. Use 10.0.2.2 for the host computer.

✦ 12. Create a Flutter Student Registration and List Application

For a beginner-friendly demonstration, we will use one screen containing a registration form and a list of students.

Replace the code in lib/main.dart with:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: StudentScreen(),
    );
  }
}

class StudentScreen extends StatefulWidget {
  const StudentScreen({super.key});

  @override
  State<StudentScreen> createState() => _StudentScreenState();
}

class _StudentScreenState extends State<StudentScreen> {

  final nameController = TextEditingController();
  final mobileController = TextEditingController();
  final courseController = TextEditingController();

  final String baseUrl =
      'http://10.0.2.2/flutter_api/';

  List students = [];

  bool loading = false;

  @override
  void initState() {
    super.initState();
    fetchStudents();
  }

  Future<void> fetchStudents() async {

    setState(() {
      loading = true;
    });

    try {

      final response = await http.get(
        Uri.parse('${baseUrl}fetch_students.php'),
      );

      if (response.statusCode == 200) {

        final result = jsonDecode(response.body);

        if (result['status'] == true) {

          setState(() {
            students = result['data'];
          });

        }

      } else {

        showMessage('Unable to fetch students');

      }

    } catch (e) {

      showMessage('Connection Error: $e');

    } finally {

      if (mounted) {
        setState(() {
          loading = false;
        });
      }

    }
  }

  Future<void> insertStudent() async {

    if (
      nameController.text.trim().isEmpty ||
      mobileController.text.trim().isEmpty ||
      courseController.text.trim().isEmpty
    ) {

      showMessage('Please fill all fields');

      return;
    }

    try {

      final response = await http.post(

        Uri.parse('${baseUrl}insert_student.php'),

        body: {
          'name': nameController.text.trim(),
          'mobile': mobileController.text.trim(),
          'course': courseController.text.trim(),
        },

      );

      final result = jsonDecode(response.body);

      if (response.statusCode == 200 &&
          result['status'] == true) {

        nameController.clear();
        mobileController.clear();
        courseController.clear();

        showMessage(result['message']);

        await fetchStudents();

      } else {

        showMessage(result['message'] ?? 'Insert failed');

      }

    } catch (e) {

      showMessage('Error: $e');

    }
  }

  Future<void> deleteStudent(String id) async {

    try {

      final response = await http.post(

        Uri.parse('${baseUrl}delete_student.php'),

        body: {
          'id': id,
        },

      );

      final result = jsonDecode(response.body);

      if (response.statusCode == 200 &&
          result['status'] == true) {

        showMessage(result['message']);

        await fetchStudents();

      } else {

        showMessage(result['message'] ?? 'Delete failed');

      }

    } catch (e) {

      showMessage('Error: $e');

    }
  }

  void showMessage(String message) {

    if (!mounted) return;

    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
      ),
    );

  }

  @override
  void dispose() {

    nameController.dispose();
    mobileController.dispose();
    courseController.dispose();

    super.dispose();

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(
        title: const Text('Student Management'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
      ),

      body: Padding(

        padding: const EdgeInsets.all(15),

        child: Column(

          children: [

            TextField(
              controller: nameController,
              decoration: const InputDecoration(
                labelText: 'Student Name',
                border: OutlineInputBorder(),
              ),
            ),

            const SizedBox(height: 10),

            TextField(
              controller: mobileController,
              keyboardType: TextInputType.phone,
              decoration: const InputDecoration(
                labelText: 'Mobile Number',
                border: OutlineInputBorder(),
              ),
            ),

            const SizedBox(height: 10),

            TextField(
              controller: courseController,
              decoration: const InputDecoration(
                labelText: 'Course',
                border: OutlineInputBorder(),
              ),
            ),

            const SizedBox(height: 10),

            SizedBox(

              width: double.infinity,

              child: ElevatedButton(

                onPressed: insertStudent,

                child: const Text('Save Student'),

              ),

            ),

            const Divider(),

            const Text(
              'Student Records',
              style: TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
            ),

            const SizedBox(height: 10),

            if (loading)
              const CircularProgressIndicator(),

            Expanded(

              child: RefreshIndicator(

                onRefresh: fetchStudents,

                child: ListView.builder(

                  physics:
                      const AlwaysScrollableScrollPhysics(),

                  itemCount: students.length,

                  itemBuilder: (context, index) {

                    final student = students[index];

                    return Card(

                      child: ListTile(

                        title: Text(student['name']),

                        subtitle: Text(
                          '${student['mobile']} - ${student['course']}',
                        ),

                        trailing: IconButton(

                          icon: const Icon(
                            Icons.delete,
                            color: Colors.red,
                          ),

                          onPressed: () {

                            deleteStudent(
                              student['id'].toString(),
                            );

                          },

                        ),

                      ),

                    );

                  },

                ),

              ),

            ),

          ],

        ),

      ),

    );

  }
}

This example demonstrates:

  • GET: Fetch student records.

  • POST: Insert student details.

  • POST: Send a delete request to the PHP API.

  • JSON: Decode the API response.

  • ListView: Display student records.

  • RefreshIndicator: Reload the student list.

The update API is already created in PHP. You can connect it to an Edit button as an additional exercise.

✦ 13. Configure Android Internet Access

Open:

android/app/src/main/AndroidManifest.xml

Add this permission before the application tag:

<uses-permission android:name="android.permission.INTERNET" />

For a local XAMPP demonstration using HTTP, Android's cleartext traffic restrictions may also need configuration for your development environment. Prefer HTTPS for deployed applications rather than enabling unrestricted HTTP traffic in production.

✦ 14. Common Problems and Their Solutions

Problem 1: Connection refused

Possible reason:

  • Apache is not running.

  • Wrong IP address.

  • Incorrect API folder path.

Solution: Start Apache and verify the API URL in your browser.

Problem 2: Flutter cannot connect to localhost

Solution: Use 10.0.2.2 for the Android emulator or your computer's local IP address for a physical phone.

Problem 3: Database connection failed

Solution: Check MySQL username, password, database name, and server status.

Problem 4: JSON parsing error

Solution: Check whether PHP is returning valid JSON. PHP warnings, notices, or HTML error pages can break JSON parsing.

Problem 5: Data is not inserting

Solution: Check the POST field names, PHP validation, SQL query, and database table structure.

✦ 15. Security Best Practices

When building real-world applications, remember:

  1. Use prepared statements for database queries.

  2. Validate user input on the PHP server.

  3. Use HTTPS for production API communication.

  4. Never expose database credentials in Flutter code.

  5. Implement authentication and authorization for protected endpoints.

  6. Do not trust user input coming from a mobile application.

  7. Return appropriate HTTP status codes.

  8. Avoid exposing sensitive server errors to application users.

✦ 16. Practical Assignment for Beginners

Now create your own Flutter + PHP + MySQL Student Management Application.

Your project should include:

  1. Student Registration Form.

  2. Student Name, Mobile and Course fields.

  3. Insert Student API.

  4. Fetch Student API.

  5. Student List screen.

  6. Edit Student functionality.

  7. Delete Student functionality.

  8. Success and error messages.

  9. Refresh Student List button.

  10. MySQL database integration.

Try to build the complete CRUD application step by step.

This project will help you understand how mobile applications communicate with backend servers.

❖ Conclusion

Connecting Flutter with PHP and MySQL is an important skill for developing database-driven mobile applications.

In this tutorial, we learned how to create a MySQL database, develop PHP REST APIs, send HTTP requests from Flutter, and display student records inside a mobile application.

We also understood how GET, POST, PUT, and DELETE operations work with a PHP backend.

At Param Classes, we focus on practical programming lessons that help beginners understand frontend, backend, database, and API integration.

Keep practicing and try creating your own real-world applications using Flutter, PHP, and MySQL.

Keep Learning, Keep Building with Param Classes!

←
Post 27 of 40
→