DEV Community

Abdul Haseeb
Abdul Haseeb

Posted on

Make todoApp API in PHP & ReactJS with login register facility.

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
   );
Enter fullscreen mode Exit fullscreen mode

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();
?>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

6. Running the Application:

  1. 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.
  2. 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.

Top comments (0)