Flutter PHP MySQL Login and Register Tutorial With UI. Copy and paste the below code as per your requirements.
Taking Permission of Internet for API Calling
<uses-permission android:name="android.permission.INTERNET" />
android:usesCleartextTraffic="true"
http: ^0.13.4 #to interact with api
fluttertoast: ^8.0.9 #to display toast message
main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:example/register.dart';
import 'package:http/http.dart' as http;
import 'DashBoard.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController user = TextEditingController();
TextEditingController pass = TextEditingController();
Future login() async {
var url = Uri.http("192.168.0.104", '/login/login.php', {'q': '{http}'});
var response = await http.post(url, body: {
"username": user.text,
"password": pass.text,
});
var data = json.decode(response.body);
if (data.toString() == "Success") {
Fluttertoast.showToast(
msg: 'Login Successful',
backgroundColor: Colors.green,
textColor: Colors.white,
toastLength: Toast.LENGTH_SHORT,
);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DashBoard(),
),
);
} else {
Fluttertoast.showToast(
backgroundColor: Colors.red,
textColor: Colors.white,
msg: 'Username and password invalid',
toastLength: Toast.LENGTH_SHORT,
);
}
}
bool isPasswordVisible = false;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.teal.shade200, Colors.purple.shade900])),
child: SingleChildScrollView(
child: Column(
children: [
Align(
alignment: Alignment.topRight,
child: Container(
height: 100,
width: 300,
decoration: const BoxDecoration(
gradient:
LinearGradient(colors: [Colors.red, Colors.yellow]),
boxShadow: [
BoxShadow(
blurRadius: 4,
spreadRadius: 3,
color: Colors.black12)
],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(200),
bottomRight: Radius.circular(200))),
child: Padding(
padding: const EdgeInsets.only(bottom: 35, left: 65),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Text(
'Let\'s',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.white,
shadows: [
Shadow(
color: Colors.black45,
offset: Offset(1, 1),
blurRadius: 5)
]),
),
Text(
' Login',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.pink.shade600,
shadows: const [
Shadow(
color: Colors.black45,
offset: Offset(1, 1),
blurRadius: 5)
]),
),
],
),
),
),
),
const SizedBox(
height: 40,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30)
.copyWith(bottom: 10),
child: TextField(
controller: user,
style: const TextStyle(color: Colors.white, fontSize: 14.5),
decoration: InputDecoration(
prefixIconConstraints:
const BoxConstraints(minWidth: 45),
prefixIcon: const Icon(
Icons.alternate_email_outlined,
color: Colors.white70,
size: 22,
),
border: InputBorder.none,
hintText: 'Enter Username',
hintStyle: const TextStyle(
color: Colors.white60, fontSize: 14.5),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white38)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white70))),
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30)
.copyWith(bottom: 10),
child: TextField(
controller: pass,
style: const TextStyle(color: Colors.white, fontSize: 14.5),
obscureText: isPasswordVisible ? false : true,
decoration: InputDecoration(
prefixIconConstraints:
const BoxConstraints(minWidth: 45),
prefixIcon: const Icon(
Icons.lock,
color: Colors.white70,
size: 22,
),
suffixIconConstraints:
const BoxConstraints(minWidth: 45, maxWidth: 46),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
isPasswordVisible = !isPasswordVisible;
});
},
child: Icon(
isPasswordVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.white70,
size: 22,
),
),
border: InputBorder.none,
hintText: 'Enter Password',
hintStyle: const TextStyle(
color: Colors.white60, fontSize: 14.5),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white38)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white70))),
),
),
const SizedBox(
height: 50,
),
GestureDetector(
onTap: () {
login();
},
child: Container(
height: 53,
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 30),
alignment: Alignment.center,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Colors.black12.withOpacity(.2),
offset: const Offset(2, 2))
],
borderRadius: BorderRadius.circular(100)
.copyWith(bottomRight: const Radius.circular(0)),
gradient: LinearGradient(colors: [
Colors.purple.shade600,
Colors.amber.shade900
])),
child: Text('Login',
style: TextStyle(
color: Colors.white.withOpacity(.8),
fontSize: 15,
fontWeight: FontWeight.bold)),
),
),
const SizedBox(
height: 50,
),
const Text('Don\'t have an account?',
style: TextStyle(color: Colors.white70, fontSize: 13)),
const SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Register()),
);
},
child: Container(
height: 53,
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 30),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: Colors.white60),
borderRadius: BorderRadius.circular(100)
.copyWith(bottomRight: const Radius.circular(0)),
),
child: Text('Sign Up',
style: TextStyle(
color: Colors.white.withOpacity(.8),
fontSize: 15,
fontWeight: FontWeight.bold)),
),
),
const SizedBox(
height: 20,
)
],
),
),
),
),
);
}
}
register.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
import 'DashBoard.dart';
import 'main.dart';
class Register extends StatefulWidget {
const Register({Key? key}) : super(key: key);
@override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register> {
TextEditingController user = TextEditingController();
TextEditingController pass = TextEditingController();
Future register() async {
var url = Uri.http("192.168.0.104", '/login/register.php', {'q': '{http}'});
var response = await http.post(url, body: {
"username": user.text.toString(),
"password": pass.text.toString(),
});
var data = json.decode(response.body);
if (data == "Error") {
Fluttertoast.showToast(
backgroundColor: Colors.orange,
textColor: Colors.white,
msg: 'User already exit!',
toastLength: Toast.LENGTH_SHORT,
);
} else {
Fluttertoast.showToast(
backgroundColor: Colors.green,
textColor: Colors.white,
msg: 'Registration Successful',
toastLength: Toast.LENGTH_SHORT,
);
Navigator.push(context,
MaterialPageRoute(
builder: (context) => DashBoard(),
),
);
}
}
bool isPasswordVisible = false;
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.teal.shade200, Colors.purple.shade900])),
child: SingleChildScrollView(
child: Column(
children: [
Align(
alignment: Alignment.topRight,
child: Container(
height: 100,
width: 300,
decoration: const BoxDecoration(
gradient:
LinearGradient(colors: [Colors.red, Colors.yellow]),
boxShadow: [
BoxShadow(
blurRadius: 4,
spreadRadius: 3,
color: Colors.black12)
],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(200),
bottomRight: Radius.circular(200))),
child: Padding(
padding: const EdgeInsets.only(bottom: 35, left: 65),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Text(
'Let\'s',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.white,
shadows: [
Shadow(
color: Colors.black45,
offset: Offset(1, 1),
blurRadius: 5)
]),
),
Text(
' Register',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.pink.shade600,
shadows: const [
Shadow(
color: Colors.black45,
offset: Offset(1, 1),
blurRadius: 5)
]),
),
],
),
),
),
),
const SizedBox(
height: 40,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30)
.copyWith(bottom: 10),
child: TextField(
controller: user,
style: const TextStyle(color: Colors.white, fontSize: 14.5),
decoration: InputDecoration(
prefixIconConstraints:
const BoxConstraints(minWidth: 45),
prefixIcon: const Icon(
Icons.alternate_email_outlined,
color: Colors.white70,
size: 22,
),
border: InputBorder.none,
hintText: 'Enter Username',
hintStyle: const TextStyle(
color: Colors.white60, fontSize: 14.5),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white38)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white70))),
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30)
.copyWith(bottom: 10),
child: TextField(
controller: pass,
style: const TextStyle(color: Colors.white, fontSize: 14.5),
obscureText: isPasswordVisible ? false : true,
decoration: InputDecoration(
prefixIconConstraints:
const BoxConstraints(minWidth: 45),
prefixIcon: const Icon(
Icons.lock,
color: Colors.white70,
size: 22,
),
suffixIconConstraints:
const BoxConstraints(minWidth: 45, maxWidth: 46),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
isPasswordVisible = !isPasswordVisible;
});
},
child: Icon(
isPasswordVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.white70,
size: 22,
),
),
border: InputBorder.none,
hintText: 'Enter Password',
hintStyle: const TextStyle(
color: Colors.white60, fontSize: 14.5),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white38)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(100).copyWith(
bottomRight: const Radius.circular(0)),
borderSide:
const BorderSide(color: Colors.white70))),
),
),
const SizedBox(
height: 50,
),
GestureDetector(
onTap: () {
register();
},
child: Container(
height: 53,
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 30),
alignment: Alignment.center,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Colors.black12.withOpacity(.2),
offset: const Offset(2, 2))
],
borderRadius: BorderRadius.circular(100)
.copyWith(bottomRight: const Radius.circular(0)),
gradient: LinearGradient(colors: [
Colors.purple.shade600,
Colors.amber.shade900
])),
child: Text('Signup',
style: TextStyle(
color: Colors.white.withOpacity(.8),
fontSize: 15,
fontWeight: FontWeight.bold)),
),
),
const SizedBox(
height: 50,
),
const Text('Already have an account?',
style: TextStyle(color: Colors.white70, fontSize: 13)),
const SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const MyHomePage()),
);
},
child: Container(
height: 53,
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 30),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: Colors.white60),
borderRadius: BorderRadius.circular(100)
.copyWith(bottomRight: const Radius.circular(0)),
),
child: Text('Login',
style: TextStyle(
color: Colors.white.withOpacity(.8),
fontSize: 15,
fontWeight: FontWeight.bold)),
),
),
const SizedBox(
height: 20,
)
],
),
),
),
),
);
}
}
dashboard.dart
import 'package:flutter/material.dart';
class DashBoard extends StatelessWidget {
const DashBoard({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Dashboard'),),
body: const Center(child: Text('Dashboard')),
);
}
}
login.php
<?php
$db = mysqli_connect('localhost','root','','userdata');
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '".$username."' AND password = '".$password."'";
$result = mysqli_query($db,$sql);
$count = mysqli_num_rows($result);
if($count == 1){
echo json_encode("Success");
}
else{
echo json_encode("Error");
}
?>
register.php
<?php
$db = mysqli_connect('localhost','root','','userdata');
if(!$db)
{
echo "Database connection failed";
}
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT username FROM users WHERE username = '".$username."'";
$result = mysqli_query($db,$sql);
$count = mysqli_num_rows($result);
if($count == 1){
echo json_encode("Error");
}else{
$insert = "INSERT INTO users(username,password) VALUES ('".$username."','".$password."')";
$query = mysqli_query($db,$insert);
if($query){
echo json_encode("Success");
}
}
?>
4 responses to “Flutter #101: Flutter PHP MySQL Login and Register Tutorial With UI”
i want only login page with php and i tried using your code as base code and it doesn’t working… What can i do to work it properly? Pls help me…
Copy only login php and dart file as per your requirements.
ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FormatException: Unexpected character (at character 1)
any solution
You may have problem in json encoding…
Use http instead of https which caused this error.