Make todoApp API in PHP & ReactJS with login register facility.
Abdul Haseeb
Posted on August 31, 2024
To create a login, registration, and ToDo application using PHP for the backend and React.js for the frontend, you would follow these steps:
Backend (PHP)
You'll create an API using PHP to handle the login, registration, and CRUD operations for the ToDo application.
1. Database Setup:
- Create a MySQL database, e.g.,
todoapp
. - Create two tables:
-
users
for storing user credentials. -
todos
for storing tasks.
-
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
);
CREATE TABLE todos (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
task VARCHAR(255) NOT NULL,
completed BOOLEAN DEFAULT FALSE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
2. PHP API Endpoints:
Create a file named api.php
that will handle the backend logic.
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, DELETE, PUT');
header('Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "todoapp";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Get the request method
$method = $_SERVER['REQUEST_METHOD'];
$request = explode('/', trim($_SERVER['PATH_INFO'],'/'));
switch($request[0]) {
case 'register':
if ($method == 'POST') {
$data = json_decode(file_get_contents("php://input"), true);
$username = $data['username'];
$password = password_hash($data['password'], PASSWORD_DEFAULT);
$sql = "INSERT INTO users (username, password) VALUES ('$username', '$password')";
if ($conn->query($sql) === TRUE) {
echo json_encode(["message" => "User registered successfully!"]);
} else {
echo json_encode(["error" => "Error: " . $sql . "<br>" . $conn->error]);
}
}
break;
case 'login':
if ($method == 'POST') {
$data = json_decode(file_get_contents("php://input"), true);
$username = $data['username'];
$password = $data['password'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$user = $result->fetch_assoc();
if (password_verify($password, $user['password'])) {
echo json_encode(["message" => "Login successful!", "user_id" => $user['id']]);
} else {
echo json_encode(["error" => "Invalid password!"]);
}
} else {
echo json_encode(["error" => "User not found!"]);
}
}
break;
case 'todos':
if ($method == 'GET') {
$user_id = intval($request[1]);
$sql = "SELECT * FROM todos WHERE user_id = $user_id";
$result = $conn->query($sql);
$todos = [];
while($row = $result->fetch_assoc()) {
$todos[] = $row;
}
echo json_encode($todos);
} elseif ($method == 'POST') {
$data = json_decode(file_get_contents("php://input"), true);
$user_id = $data['user_id'];
$task = $data['task'];
$sql = "INSERT INTO todos (user_id, task) VALUES ($user_id, '$task')";
if ($conn->query($sql) === TRUE) {
echo json_encode(["message" => "Task added successfully!"]);
} else {
echo json_encode(["error" => "Error: " . $sql . "<br>" . $conn->error]);
}
} elseif ($method == 'PUT') {
$data = json_decode(file_get_contents("php://input"), true);
$id = intval($request[1]);
$task = $data['task'];
$completed = $data['completed'] ? 1 : 0;
$sql = "UPDATE todos SET task='$task', completed=$completed WHERE id=$id";
if ($conn->query($sql) === TRUE) {
echo json_encode(["message" => "Task updated successfully!"]);
} else {
echo json_encode(["error" => "Error: " . $sql . "<br>" . $conn->error]);
}
} elseif ($method == 'DELETE') {
$id = intval($request[1]);
$sql = "DELETE FROM todos WHERE id=$id";
if ($conn->query($sql) === TRUE) {
echo json_encode(["message" => "Task deleted successfully!"]);
} else {
echo json_encode(["error" => "Error: " . $sql . "<br>" . $conn->error]);
}
}
break;
default:
echo json_encode(["message" => "Invalid request"]);
break;
}
$conn->close();
?>
Frontend (React.js)
You would create a simple React.js application that interacts with the PHP API.
1. React Project Setup:
- Initialize a new React project.
- Set up React Router for navigation.
- Install Axios for making API calls.
npx create-react-app todo-app
cd todo-app
npm install axios react-router-dom
2. Login Component:
import React, { useState } from 'react';
import axios from 'axios';
const Login = ({ setUser }) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async (e) => {
e.preventDefault();
try {
const response = await axios.post('http://localhost/api.php/login', {
username,
password
});
setUser(response.data.user_id);
} catch (error) {
console.error("Login failed", error);
}
};
return (
<form onSubmit={handleLogin}>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" required />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" required />
<button type="submit">Login</button>
</form>
);
};
export default Login;
3. Register Component:
import React, { useState } from 'react';
import axios from 'axios';
const Register = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleRegister = async (e) => {
e.preventDefault();
try {
const response = await axios.post('http://localhost/api.php/register', {
username,
password
});
alert(response.data.message);
} catch (error) {
console.error("Registration failed", error);
}
};
return (
<form onSubmit={handleRegister}>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" required />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" required />
<button type="submit">Register</button>
</form>
);
};
export default Register;
4. Todo Component:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const TodoApp = ({ user }) => {
const [todos, setTodos] = useState([]);
const [task, setTask] = useState('');
useEffect(() => {
const fetchTodos = async () => {
try {
const response = await axios.get(`http://localhost/api.php/todos/${user}`);
setTodos(response.data);
} catch (error) {
console.error("Error fetching tasks", error);
}
};
fetchTodos();
}, [user]);
const addTask = async (e) => {
e.preventDefault();
try {
const response = await axios.post('http://localhost/api.php/todos', {
user_id: user,
task
});
setTask('');
setTodos([...todos, response.data]);
} catch (error) {
console.error("Error adding task", error);
}
};
const toggleComplete = async (id, completed) => {
try {
await axios.put(`http://localhost/api.php/todos/${id}`, {
completed: !completed
});
setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !completed } : todo));
} catch (error) {
console.error("Error updating task", error);
}
};
const deleteTask = async (id) => {
try {
await axios.delete(`http://localhost/api.php/todos/${id}`);
setTodos(todos.filter(todo => todo.id !== id));
} catch (error) {
console.error("Error deleting task", error);
}
};
return (
<div>
<h2>Your Todo List</h2>
<form onSubmit={addTask}>
<input
type="text"
value={task}
onChange={(e) => setTask(e.target.value)}
placeholder="New Task"
required
/>
<button type="submit">Add Task</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<span
style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}
onClick={() => toggleComplete(todo.id, todo.completed)}
>
{todo.task}
</span>
<button onClick={() => deleteTask(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
};
export default TodoApp;
5. App Component and Routing:
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom';
import Login from './Login';
import Register from './Register';
import TodoApp from './TodoApp';
const App = () => {
const [user, setUser] = useState(null);
return (
<Router>
<nav>
<Link to="/">Login</Link>
<Link to="/register">Register</Link>
{user && <Link to="/todos">TodoApp</Link>}
</nav>
<Routes>
<Route path="/" element={<Login setUser={setUser} />} />
<Route path="/register" element={<Register />} />
{user && <Route path="/todos" element={<TodoApp user={user} />} />}
</Routes>
</Router>
);
};
export default App;
6. Running the Application:
-
Backend:
- Make sure your Apache server is running (or any other server that supports PHP).
- Place your
api.php
file in the appropriate directory (e.g.,htdocs
if using XAMPP). - Ensure the MySQL database and tables are created as described.
-
Frontend:
- Start your React application:
npm start
- Your React app should now be running at
http://localhost:3000
.
7. Testing the Application:
-
Register: Go to
/register
, create a new user. - Login: After registering, log in with the newly created user.
- Todo App: After logging in, access the todo list, add, update, and delete tasks.
Summary
You've now set up a full-stack application with a PHP backend for handling user registration, login, and CRUD operations on a ToDo list, and a React.js frontend to interact with these API endpoints. This setup gives you a basic structure to build upon, adding more features as required.
Posted on August 31, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.