DEV Community

Abdul Haseeb
Abdul Haseeb

Posted on

2

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.

Neon image

Build better on Postgres with AI-Assisted Development Practices

Compare top AI coding tools like Cursor and Windsurf with Neon's database integration. Generate synthetic data and manage databases with natural language.

Read more →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

DEV is better (more customized, reading settings like dark mode etc) when you're signed in!

Okay