Flutter PHP

Fetching Data From MySql Database To Flutter App

This article has two Parts

  1. PHP API for fetching data
  2. Flutter Screen of Orders

Part 1: PHI API Explanation

Explanation of PHP code step by step:

  1. Include Necessary Files:
   include('cors.php');
   include('../database.php');

These lines include two external PHP files: cors.php and database.php. These files likely contain functions or configurations needed for handling CORS (Cross-Origin Resource Sharing) and database connection setup.

  1. Set Response Content Type:
   header('Content-Type: application/json');

This line sets the response’s content type to JSON. It indicates that the server will send JSON data in the response.

  1. Initialize an Empty Response Array:
   $response = array();

An empty associative array called $response is created to store the response data, including success status, a message, and the order data.

  1. Check the Request Method:
   if ($_SERVER['REQUEST_METHOD'] === 'GET') {

This conditional statement checks if the HTTP request method is a GET request. It ensures that the code below is executed only for GET requests.

  1. Retrieve Mobile Number from Query Parameters:
   $mobile = $_GET['mobile'];

It retrieves the mobile number from the query parameters of the GET request. This mobile number will be used to filter orders.

  1. Prepare SQL Query to Fetch Orders:
   $sql = "SELECT * FROM checkout WHERE c_mobile = :mobile";
   $stmt = $conn->prepare($sql);
   $stmt->bindParam(':mobile', $mobile);

These lines prepare an SQL query to fetch orders from a table named checkout where the c_mobile column matches the provided mobile number. It uses a prepared statement to safely bind the :mobile parameter.

  1. Execute the SQL Query:
   if ($stmt->execute()) {

This conditional statement checks if the SQL query executed successfully.

  1. Fetch Orders and Build the Response:
   $orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
   $response['success'] = true;
   $response['message'] = "Orders fetched successfully.";
   $response['data'] = $orders;

If the query execution is successful, it fetches the orders as an array of associative arrays. Then, it sets the response’s success status to true, provides a success message, and includes the fetched order data in the response.

  1. Handle Execution Errors:
   } else {
       $response['success'] = false;
       $response['message'] = "Error: " . $stmt->errorInfo();
   }

In case the SQL query execution encounters an error, it sets the success status to false and includes an error message in the response.

  1. Invalid Request Method Handling: } else { $response['success'] = false; $response['message'] = "Invalid request method."; } If the request method is not a GET request, it sets the success status to false and provides a message indicating that the request method is invalid.
  2. Output the Response as JSON:
    php echo json_encode($response);
    Finally, the code converts the $response array into a JSON string and sends it as the response to the client.

This code is designed to handle GET requests for fetching orders by mobile number from a database and respond with the retrieved data in JSON format. The response includes information about the success of the operation and, if successful, the fetched order data.

Part 2: Flutter Screen Explanation

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
  • In this part, we import necessary libraries for the Flutter application. We import dart:convert for JSON decoding, package:flutter/material.dart for Flutter widgets, and package:http/http.dart as http to make HTTP requests.
class Orders extends StatefulWidget {
  const Orders({Key? key}) : super(key: key);
  @override
  State<Orders> createState() => _OrdersState();
}
  • Here, we define a Flutter widget called Orders. It extends StatefulWidget, indicating that its state can change. It has a constructor and a method that returns the state object _OrdersState.
class _OrdersState extends State<Orders> {
  final TextEditingController mobileController = TextEditingController();
  List<Map<String, dynamic>> orders = [];
  bool isLoading = false;
  • This is the state class for the Orders widget. It includes a TextEditingController for handling user input, a list of orders as maps, and a boolean isLoading to track whether data is being loaded.
void searchOrders() async {
  setState(() {
    isLoading = true;
  });
  • searchOrders() is a method that is called when the user clicks the search button. It sets isLoading to true to indicate that data retrieval is in progress.
// Replace with your API endpoint.
final apiUrl = Uri.parse('https://booppers.tk/api/fetch_order.php?mobile=${mobileController.text}');
  • This line creates a URI for the API endpoint to fetch orders. It includes the user’s input (mobile number) as a query parameter.
final response = await http.get(apiUrl);
  • This line sends an HTTP GET request to the API endpoint using the http package and awaits the response.
if (response.statusCode == 200) {
  final Map<String, dynamic> data = json.decode(response.body);
  if (data['success']) {
    setState(() {
      orders = List<Map<String, dynamic>>.from(data['data']);
    });
  } else {
    // Handle API error here
  }
} else {
  // Handle API request error here
}
  • Here, we check the HTTP status code of the response. If it’s 200 (OK), we parse the response body as JSON and check if the ‘success’ field in the data is true. If so, we update the orders list with the retrieved data. If ‘success’ is false, you can add error handling for API errors. If the status code is not 200, you can handle request errors.
setState(() {
  isLoading = false;
});
  • Finally, after handling the API response or errors, we set isLoading back to false to indicate that data retrieval is complete.

The remaining code is related to building the user interface, including widgets like Container, TextField, ElevatedButton, and DataTable, along with their properties and styles. This code allows users to search for orders by mobile number and displays the results in a horizontally scrollable DataTable. If no orders are found, it displays a “No orders found” message.

Fluu Code Of Flutter Screen:

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

class Orders extends StatefulWidget {
  const Orders({Key? key}) : super(key: key);
  @override
  State<Orders> createState() => _OrdersState();
}

class _OrdersState extends State<Orders> {
  final TextEditingController mobileController = TextEditingController();
  List<Map<String, dynamic>> orders = [];
  bool isLoading = false;

  void searchOrders() async {
    setState(() {
      isLoading = true;
    });

    // Replace with your API endpoint.
    final apiUrl =
    Uri.parse('https://booppers.tk/api/fetch_order.php?mobile=${mobileController.text}');

    final response = await http.get(apiUrl);

    if (response.statusCode == 200) {
      final Map<String, dynamic> data = json.decode(response.body);
      if (data['success']) {
        setState(() {
          orders = List<Map<String, dynamic>>.from(data['data']);
        });
      } else {
        // Handle API error here
      }
    } else {
      // Handle API request error here
    }

    setState(() {
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Search Orders'),
        backgroundColor: Colors.pink,
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            Container(
              margin: EdgeInsets.all(30),
              child: Image.network('https://your-image-url-here.com'),
            ),
            Container(
              margin: EdgeInsets.all(10),
              alignment: Alignment.center,
              child: Text('Search Orders', style: TextStyle(fontSize: 25),),
            ),
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: TextField(
                controller: mobileController,
                decoration: InputDecoration(
                  labelText: 'Enter Mobile Number',
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                  ),
                ),
              ),
            ),
            ElevatedButton(
              onPressed: searchOrders,
              child: Text('Search'),
            ),
            if (isLoading)
              CircularProgressIndicator()
            else if (orders.isNotEmpty)
              SingleChildScrollView(
                scrollDirection: Axis.horizontal, // Enable horizontal scrolling
                child: DataTable(
                  columns: const <DataColumn>[
                    DataColumn(label: Text('Order ID')),
                    DataColumn(label: Text('Customer Name')),
                    DataColumn(label: Text('Mobile')),
                    DataColumn(label: Text('State')),
                    DataColumn(label: Text('Address')),
                  ],
                  rows: orders.map((order) {
                    return DataRow(
                      cells: <DataCell>[
                        DataCell(Text(order['id'].toString())),
                        DataCell(Text(order['c_name'].toString())),
                        DataCell(Text(order['c_mobile'].toString())),
                        DataCell(Text(order['c_state'].toString())),
                        DataCell(Text(order['c_address'].toString())),
                      ],
                    );
                  }).toList(),
                ),
              )
            else
              Text('No orders found.'),
          ],
        ),
      ),
    );
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *