Flutter PHP MySQL – Remplir ListView avec des Images et du Texte
Flutter est un framework pour la création d'applications mobiles, à la fois pour Android et iOS. En fait, vous pouvez même l'utiliser pour créer des applications Web et de bureau. Il s'agit d'un framework mature et bien supporté qui est actuellement en vogue.
MySQL, quant à lui, est une base de données principalement utilisée pour héberger des données pour les applications Web et mobiles. Il est gratuit et est probablement le cadre SGBDR le plus populaire du marché. En général, nous aimons l'utiliser avec PHP qui est un langage de programmation côté serveur. PHP et MySQL sont une combinaison qui alimente la plupart des sites Web.
Dans cette leçon, nous voulons voir comment travailler à la fois avec la base de données MySQL et l'application Flutter. Nous effectuons simplement un HTTP GET sur le serveur PHP MySQL, téléchargeons les données et remplissons notre liste personnalisée avec des images et du texte. Ensuite, lorsqu'une seule carte de notre liste est cliquée, nous ouvrons une page de détails en passant par les données que nous avons téléchargées de MySQL.
Demo
Voici la démo de ce qui est créé dans le projet.

Tutoriel vidéo
Voici le tutoriel vidéo :
1. PHP
Tout d'abord, nous devons écrire du code PHP qui va :
- Se connecter à la base de données mysql en utilisant la classe
mysqli. - Sélectionner tous les enregistrements de notre table de base de données mysql.
- Retourner les résultats dans un tableau PHP.
- Coder en JSON ce tableau et l'imprimer à l'appelant.
(a). index.php
C'est le seul fichier que nous avons. Nous écrivons du code PHP orienté objet. La première étape dans ce fichier est de créer une classe Constants qui contiendra les informations d'identification de notre base de données. Rappelez-vous que nous hébergeons notre base de données dans MySQL, nous devons donc définir les informations d'identification comme le nom de la base de données, le nom d'utilisateur ainsi que le mot de passe.
Dans le fichier index.php, nous écrivons la balise PHP d'ouverture :
<?php
Ensuite, nous créons la classe avec les informations d'identification statiques de la base de données :
class Constants
{
//DATABASE DETAILS
static $DB_SERVER="localhost";
static $DB_NAME="spacecraftsDB";
static $USERNAME="root";
static $PASSWORD="";
Puis définissons l'instruction sql pour sélectionner toutes les données de la base de données :
static $SQL_SELECT_ALL="SELECT * FROM spacecraftsTB";
}
Dans le même fichier php procéder à la création d'une autre classe qui accueillera nos méthodes CRUD :
class Spacecrafts
{
Dans cette classe nous allons définir une fonction pour se connecter à notre base de données en utilisant mysqli. Nous passons le serveur de base de données, le nom de la base de données, le nom d'utilisateur et le mot de passe au constructeur de notre classe mysqli. Ensuite si la connexion est erratique, nous retournons null sinon nous retournons notre instance mysqli :
public function connect()
{
$con=new mysqli(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
if($con->connect_error)
{
// echo "Unable To Connect"; - For debug
return null;
}else
{
//echo "Connected"; - For debug
return $con;
}
}
La fonction suivante va nous permettre de sélectionner des données depuis notre base de données mysql. Nous allons récupérer les données de la base de données, puis pousser ces données dans un tableau, puis coder et imprimer ce tableau :
public function select()
{
$con=$this->connect();
if($con != null)
{
$result=$con->query(Constants::$SQL_SELECT_ALL);
if($result->num_rows>0)
{
$spacecrafts=array();
while($row=$result->fetch_array())
{
array_push($spacecrafts, array("id"=>$row['id'],"name"=>$row['name'],
"propellant"=>$row['propellant'],"destination"=>$row['destination'],
"image_url"=>$row['image_url'],"technology_exists"=>$row['technology_exists']));
}
print(json_encode(array_reverse($spacecrafts)));
}else
{
print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
}
$con->close();
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
}
Voici le code complet de index.php :
<?php
class Constants
{
//DATABASE DETAILS
static $DB_SERVER="localhost";
static $DB_NAME="spacecraftsDB";
static $USERNAME="root";
static $PASSWORD="";
//STATEMENTS
static $SQL_SELECT_ALL="SELECT * FROM spacecraftsTB";
}
class Spacecrafts
{
/*******************************************************************************************************************************************/
/*
1.CONNECT TO DATABASE.
2. RETURN CONNECTION OBJECT
*/
public function connect()
{
$con=new mysqli(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
if($con->connect_error)
{
// echo "Unable To Connect"; - For debug
return null;
}else
{
//echo "Connected"; - For debug
return $con;
}
}
/*******************************************************************************************************************************************/
/*
1.SELECT FROM DATABASE.
*/
public function select()
{
$con=$this->connect();
if($con != null)
{
$result=$con->query(Constants::$SQL_SELECT_ALL);
if($result->num_rows>0)
{
$spacecrafts=array();
while($row=$result->fetch_array())
{
array_push($spacecrafts, array("id"=>$row['id'],"name"=>$row['name'],
"propellant"=>$row['propellant'],"destination"=>$row['destination'],
"image_url"=>$row['image_url'],"technology_exists"=>$row['technology_exists']));
}
print(json_encode(array_reverse($spacecrafts)));
}else
{
print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
}
$con->close();
}else{
print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
}
}
}
$spacecrafts=new Spacecrafts();
$spacecrafts->select();
//end
2. Dart
La partie suivante consiste à écrire notre code Dart. Dart est le langage de programmation que nous utilisons pour créer notre application Flutter. Nous n'avons qu'un seul fichier :
(a). main.dart
Commencez par ajouter les imports :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:convert';
Créez une classe appelée Spacecraft pour représenter un vaisseau spatial. C'est notre classe modèle. Nous définissons les propriétés de cet engin spatial comme des instances de cette classe. Ces propriétés comprennent l'id, le nom, l'URL de l'image et le propulseur.
class Spacecraft {
final String id;
final String name, imageUrl, propellant;
Ces propriétés seront reçues via le constructeur :
Spacecraft({
this.id,
this.name,
this.imageUrl,
this.propellant,
});
Nous aurons une fonction responsable de la conversion des données JSON dans notre objet Spacecraft :
factory Spacecraft.fromJson(Map<String, dynamic> jsonData) {
return Spacecraft(
id: jsonData['id'],
name: jsonData['name'],
propellant: jsonData['propellant'],
imageUrl: "http://192.168.12.2/PHP/spacecrafts/images/"+jsonData['image_url'],
);
}
}
Nous aurons également besoin de créer un écran qui listera nos données. Nous listons nos données dans une ListView. Nous devons donc créer un élément ListView. Lorsque cet élément ListView est cliqué, nous allons ouvrir la page de détails et montrer les résultats dans un autre écran :
Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
decoration: BoxDecoration(border: Border.all(color: Colors.orange)),
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
child: Image.network(spacecraft.imageUrl),
padding: EdgeInsets.only(bottom: 8.0),
),
Row(children: <Widget>[
Padding(
child: Text(
spacecraft.name,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
Text(" | "),
Padding(
child: Text(
spacecraft.propellant,
style: new TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
]),
],
),
),
),
onTap: () {
//We start by creating a Page Route.
//A MaterialPageRoute is a modal route that replaces the entire
//screen with a platform-adaptive transition.
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: spacecraft),
);
//A Navigator is a widget that manages a set of child widgets with
//stack discipline.It allows us navigate pages.
Navigator.of(context).push(route);
});
}
}
Vous serez peut-être intéressé par la façon dont nous téléchargeons les données JSON depuis le serveur. La première étape est de définir une fonction qui retourne un objet Future. Cette méthode sera une asynchrone afin de ne pas bloquer notre interface utilisateur Thread. Le paramètre générique de cette fonction sera une liste de vaisseaux spatiaux :
Future<List<Spacecraft>> downloadJSON() async {
Définissez ensuite un endpoint JSON. C'est l'URL contre laquelle nous allons exécuter une requête HTTP GET. Ensuite, exécutez ce endpoint en utilisant la fonction get() :
final jsonEndpoint =
"http://192.168.12.2/PHP/spacecrafts";
final response = await get(jsonEndpoint);
Nous allons également vérifier le code de réponse si nous avons réussi. Un code de statut de réponse de 200 implique le succès, que nous avons réussi à communiquer avec le serveur. Nous décodons donc le corps de la réponse JSON en une liste. C'est cette liste que nous allons rendre dans notre listview :
if (response.statusCode == 200) {
List spacecrafts = json.decode(response.body);
return spacecrafts
.map((spacecraft) => new Spacecraft.fromJson(spacecraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}
Voici le code complet :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:convert';
class Spacecraft {
final String id;
final String name, imageUrl, propellant;
Spacecraft({
this.id,
this.name,
this.imageUrl,
this.propellant,
});
factory Spacecraft.fromJson(Map<String, dynamic> jsonData) {
return Spacecraft(
id: jsonData['id'],
name: jsonData['name'],
propellant: jsonData['propellant'],
imageUrl: "http://192.168.12.2/PHP/spacecrafts/images/"+jsonData['image_url'],
);
}
}
class CustomListView extends StatelessWidget {
final List<Spacecraft> spacecrafts;
CustomListView(this.spacecrafts);
Widget build(context) {
return ListView.builder(
itemCount: spacecrafts.length,
itemBuilder: (context, int currentIndex) {
return createViewItem(spacecrafts[currentIndex], context);
},
);
}
Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
decoration: BoxDecoration(border: Border.all(color: Colors.orange)),
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
child: Image.network(spacecraft.imageUrl),
padding: EdgeInsets.only(bottom: 8.0),
),
Row(children: <Widget>[
Padding(
child: Text(
spacecraft.name,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
Text(" | "),
Padding(
child: Text(
spacecraft.propellant,
style: new TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
]),
],
),
),
),
onTap: () {
//We start by creating a Page Route.
//A MaterialPageRoute is a modal route that replaces the entire
//screen with a platform-adaptive transition.
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: spacecraft),
);
//A Navigator is a widget that manages a set of child widgets with
//stack discipline.It allows us navigate pages.
Navigator.of(context).push(route);
});
}
}
//Future is n object representing a delayed computation.
Future<List<Spacecraft>> downloadJSON() async {
final jsonEndpoint =
"http://192.168.12.2/PHP/spacecrafts";
final response = await get(jsonEndpoint);
if (response.statusCode == 200) {
List spacecrafts = json.decode(response.body);
return spacecrafts
.map((spacecraft) => new Spacecraft.fromJson(spacecraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}
class SecondScreen extends StatefulWidget {
final Spacecraft value;
SecondScreen({Key key, this.value}) : super(key: key);
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Detail Page')),
body: new Container(
child: new Center(
child: Column(
children: <Widget>[
Padding(
child: new Text(
'SPACECRAFT DETAILS',
style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0),
textAlign: TextAlign.center,
),
padding: EdgeInsets.only(bottom: 20.0),
),
Padding(
//`widget` is the current configuration. A State object's configuration
//is the corresponding StatefulWidget instance.
child: Image.network('${widget.value.imageUrl}'),
padding: EdgeInsets.all(12.0),
),
Padding(
child: new Text(
'NAME : ${widget.value.name}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
),
Padding(
child: new Text(
'PROPELLANT : ${widget.value.propellant}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
)
], ),
),
),
);
}
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new Scaffold(
appBar: new AppBar(title: const Text('MySQL Images Text')),
body: new Center(
//FutureBuilder is a widget that builds itself based on the latest snapshot
// of interaction with a Future.
child: new FutureBuilder<List<Spacecraft>>(
future: downloadJSON(),
//we pass a BuildContext and an AsyncSnapshot object which is an
//Immutable representation of the most recent interaction with
//an asynchronous computation.
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Spacecraft> spacecrafts = snapshot.data;
return new CustomListView(spacecrafts);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
//return a circular progress indicator.
return new CircularProgressIndicator();
},
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
//end
Télécharger
Voici les ressources de référence :
| --- |
|---|