Home >Backend Development >PHP Tutorial >Creating a TodoList with PHP and the Lithe Framework: A Complete Guide

Creating a TodoList with PHP and the Lithe Framework: A Complete Guide

Patricia Arquette
Patricia ArquetteOriginal
2024-11-20 21:22:18773browse

Criando uma TodoList com PHP e o Framework Lithe: Um Guia Completo

In this tutorial, we will create a working TodoList application using Lithe. You will learn how to structure your project, create interactive views, and implement a RESTful API to manage your tasks. This project will serve as an excellent example of how to build modern web applications with PHP.

Prerequisites

  • PHP 7.4 or higher
  • Composer installed
  • MySQL
  • Basic knowledge of PHP and JavaScript

Project Structure

First, let's create a new Lithe project:

composer create-project lithephp/lithephp todo-app
cd todo-app

Configuring the Database

Edit the .env file in the project root with the following settings:

DB_CONNECTION_METHOD=mysqli
DB_CONNECTION=mysql
DB_HOST=localhost
DB_NAME=lithe_todos
DB_USERNAME=root
DB_PASSWORD=
DB_SHOULD_INITIATE=true

Creating the migration

Run the command to create a new migration:

php line make:migration CreateTodosTable

Edit the generated migration file in src/database/migrations/:

return new class
{
    public function up(mysqli $db): void
    {
        $query = "
            CREATE TABLE IF NOT EXISTS todos (
                id INT(11) AUTO_INCREMENT PRIMARY KEY,
                title VARCHAR(255) NOT NULL,
                completed BOOLEAN DEFAULT FALSE,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
            )
        ";
        $db->query($query);
    }

    public function down(mysqli $db): void
    {
        $query = "DROP TABLE IF EXISTS todos";
        $db->query($query);
    }
};

Run the migration:

php line migrate

Implementing the Model

Generate a new model:

php line make:model Todo

Edit the file src/models/Todo.php:

namespace App\Models;

use Lithe\Database\Manager as DB;

class Todo
{
    public static function all(): array
    {
        return DB::connection()
            ->query("SELECT * FROM todos ORDER BY created_at DESC")
            ->fetch_all(MYSQLI_ASSOC);
    }

    public static function create(array $data): ?array
    {
        $stmt = DB::connection()->prepare(
            "INSERT INTO todos (title, completed) VALUES (?, ?)"
        );
        $completed = false;
        $stmt->bind_param('si', $data['title'], $completed);
        $success = $stmt->execute();

        if ($success) {
            $id = $stmt->insert_id;
            return [
                'id' => $id,
                'title' => $data['title'],
                'completed' => $completed
            ];
        }

        return null;
    }

    public static function update(int $id, array $data): bool
    {
        $stmt = DB::connection()->prepare(
            "UPDATE todos SET completed = ? WHERE id = ?"
        );
        $stmt->bind_param('ii', $data['completed'], $id);
        return $stmt->execute();
    }

    public static function delete(int $id): bool
    {
        $stmt = DB::connection()->prepare("DELETE FROM todos WHERE id = ?");
        $stmt->bind_param('i', $id);
        return $stmt->execute();
    }
}

Creating the Controller

Generate a new controller:

php line make:controller TodoController

Edit the file src/http/controllers/TodoController.php:

namespace App\Http\Controllers;

use App\Models\Todo;
use Lithe\Http\Request;
use Lithe\Http\Response;

class TodoController
{
    public static function index(Request $req, Response $res)
    {
        return $res->view('todo.index');
    }

    public static function list(Request $req, Response $res)
    {
        $todos = Todo::all();
        return $res->json($todos);
    }

    public static function store(Request $req, Response $res)
    {
        $data = (array) $req->body();
        $todo = Todo::create($data);
        $success = $todo ? true : false;

        return $res->json([
            'success' => $success,
            'message' => $success ? 'Tarefa criada com sucesso' : 'Falha ao criar tarefa',
            'todo' => $todo
        ]);
    }

    public static function update(Request $req, Response $res)
    {
        $id = $req->param('id');
        $data = (array) $req->body();
        $success = Todo::update($id, $data);

        return $res->json([
            'success' => $success,
            'message' => $success ? 'Tarefa atualizada com sucesso' : 'Falha ao atualizar tarefa'
        ]);
    }

    public static function delete(Request $req, Response $res)
    {
        $id = $req->param('id');
        $success = Todo::delete($id);

        return $res->json([
            'success' => $success,
            'message' => $success ? 'Tarefa removida com sucesso' : 'Falha ao remover tarefa'
        ]);
    }
}

Creating the Views

Create the src/views/todo directory and add the index.php file:

<!DOCTYPE html>
<html>
<head>
    <title>TodoList com Lithe</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
        }

        body {
            min-height: 100vh;
            background-color: #ffffff;
            padding: 20px;
        }

        .container {
            max-width: 680px;
            margin: 0 auto;
            padding: 40px 20px;
        }

        h1 {
            color: #1d1d1f;
            font-size: 34px;
            font-weight: 700;
            margin-bottom: 30px;
        }

        .todo-form {
            display: flex;
            gap: 12px;
            margin-bottom: 30px;
            border-bottom: 1px solid #e5e5e7;
            padding-bottom: 30px;
        }

        .todo-input {
            flex: 1;
            padding: 12px 16px;
            font-size: 17px;
            border: 1px solid #e5e5e7;
            border-radius: 10px;
            background-color: #f5f5f7;
            transition: all 0.2s;
        }

        .todo-input:focus {
            outline: none;
            background-color: #ffffff;
            border-color: #0071e3;
        }

        .add-button {
            padding: 12px 20px;
            background: #0071e3;
            color: white;
            border: none;
            border-radius: 10px;
            font-size: 15px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s;
        }

        .add-button:hover {
            background: #0077ED;
        }

        .todo-list {
            list-style: none;
        }

        .todo-item {
            display: flex;
            align-items: center;
            padding: 16px;
            border-radius: 10px;
            margin-bottom: 8px;
            transition: background-color 0.2s;
        }

        .todo-item:hover {
            background-color: #f5f5f7;
        }

        .todo-checkbox {
            width: 22px;
            height: 22px;
            margin-right: 15px;
            cursor: pointer;
        }

        .todo-text {
            flex: 1;
            font-size: 17px;
            color: #1d1d1f;
        }

        .completed {
            color: #86868b;
            text-decoration: line-through;
        }

        .delete-button {
            padding: 8px 12px;
            background: none;
            color: #86868b;
            border: none;
            border-radius: 6px;
            font-size: 15px;
            cursor: pointer;
            opacity: 0;
            transition: all 0.2s;
        }

        .todo-item:hover .delete-button {
            opacity: 1;
        }

        .delete-button:hover {
            background: #f5f5f7;
            color: #ff3b30;
        }

        .loading {
            text-align: center;
            padding: 20px;
            color: #86868b;
        }

        .error {
            color: #ff3b30;
            text-align: center;
            padding: 20px;
        }
    </style>
</head>
<body>
    <div>



<h2>
  
  
  Configurando as Rotas
</h2>

<p>Atualize o arquivo src/App.php para incluir as rotas da TodoList:<br>
</p>

<pre class="brush:php;toolbar:false">use App\Http\Controllers\TodoController;

$app = new \Lithe\App;

// Rota para a página principal
$app->get('/', [TodoController::class, 'index']);

// Rotas da API
$app->get('/todos/list', [TodoController::class, 'list']);
$app->post('/todos', [TodoController::class, 'store']);
$app->put('/todos/:id', [TodoController::class, 'update']);
$app->delete('/todos/:id', [TodoController::class, 'delete']);

$app->listen();

Running the Application

To start the development server, run:

php line serve

Go to http://localhost:8000 in your browser to see the application in operation.

Implemented Features

Our TodoList has the following features:

  1. To-do list in reverse chronological order
  2. Addition of new tasks
  3. Marking tasks as completed/pending
  4. Task removal
  5. Responsive and user-friendly interface
  6. Visual feedback for all actions
  7. Error handling

Conclusion

You now have a fully functional TodoList application built with Lithe. This example demonstrates how to create a modern web application with PHP, including:

  • Proper MVC code structure
  • RESTful API Implementation
  • Interactive user interface
  • Database integration
  • Error handling
  • User feedback

From here, you can expand the application by adding new features such as:

  • User authentication
  • Task categorization
  • Expiration dates
  • Filters and search

To continue learning about Lithe, head over to Linktree, where you can access Discord, documentation, and more!

The above is the detailed content of Creating a TodoList with PHP and the Lithe Framework: A Complete Guide. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn