seip25/lila-php

Modern PHP framework , built for developing scalable web applications and APIs. React integration, Twig templating, internationalization (i18n), request validation, flexible environment configuration,Seeders,Migrations and more.

Maintainers

Package info

github.com/seip25/LilaPHP

Type:project

pkg:composer/seip25/lila-php

Statistics

Installs: 89

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.20 2026-03-29 22:59 UTC

README

A lightweight, modular, and modern PHP micro-framework

License PHP Version

Documentation β€’ GitHub

🌟 Overview

LilaPHP is a lightweight and modular PHP micro-framework designed for simplicity, flexibility, and security. It provides a minimal yet powerful foundation for building web applications with clean routing, middleware, Twig templates, and Dotenv configuration.

LilaPHP gives you control and performance β€” no boilerplate, no heavy dependencies, just clean, fast PHP.

✨ Why Choose LilaPHP?

LilaPHP was designed with one clear purpose β€” to give developers full control, performance, and simplicity without the unnecessary overhead of large, opinionated frameworks.

🎯 Key Features

  • ⚑ Lightweight core β€” Loads only what's needed for each request
  • 🧩 Modular structure β€” Each app, route, or endpoint can define its own configuration
  • πŸ”’ Secure by default β€” Built-in CSRF protection, input sanitization, and isolated session handling
  • πŸͺΆ SEO-friendly β€” Clean URLs, optimized image helpers, and auto-generated metadata
  • πŸ–₯️ Universal compatibility β€” Works on NGINX, Apache, FrankenPHP, Swoole, VPS, or shared hosting
  • 🧠 Developer experience first β€” Instant setup, clear routing, and intuitive Twig integration
  • πŸš€ Performance oriented β€” Minimal I/O, cached helpers, and pre-optimized rendering for production
  • 🌐 Multi-language support β€” Built-in localization system with English, Spanish, Portuguese, and Brazilian Portuguese

πŸ”₯ Modular Architecture

Each entry file can instantiate the framework with its own configuration, giving you complete control over security, middleware, and session behavior.

// app/index.php - Default configuration
$app = new App();
// app/newApp.php - Custom configuration
$app = new App([
    'security' => [
        'cors' => false,
        'sanitize' => false,
        'logger' => true
    ]
]);

πŸ“¦ Installation

Install with composer

composer create-project seip25/lila-php LilaPHP

Edit .env and update the base URL:

URL_PROJECT=http://localhost/LilaPHP #or "http://localhost:8000/" 
DEBUG=true
LANG="eng"

Run the Application or visit http://localhost/LilaPHP in LAMPP ,XAMPP,WAMP

Using PHP's Built-in Server (Development):

php -S localhost:8000

Then visit http://localhost:8000

React

Install

cd app
npm install
npm run dev 
npm run build

Edit in app/resources/pages :

πŸ“ Project Structure

LilaPHP/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ core/          # Core framework files (router, response, validator)
β”‚   β”œβ”€β”€ templates/     # Twig templates
β”‚   β”œβ”€β”€ locales/       # Language files (eng, esp, bra, por)
β”‚   β”œβ”€β”€ vendor/        # Composer dependencies
β”‚   β”œβ”€β”€ .env           # Environment configuration
β”‚   └── index.php      # Framework bootstrap
β”‚
β”œβ”€β”€ public/            # Public assets (CSS, JS, images)
β”œβ”€β”€ index.php          # Main entry point
β”œβ”€β”€ login/             # Independent app example
β”‚   └── index.php
β”œβ”€β”€ set-lang/          # Language switcher
β”‚   └── index.php
└── .htaccess          # Apache configuration

πŸš€ Quick Start

Basic Routing

<?php
include_once __DIR__."/app/index.php";

$app->get(callback: function($req, $res) use ($app) {
    return $app->render("home");
});

$app->post(callback: function($req, $res) use ($app) {
    return $app->jsonResponse(["success" => true]);
}, csrf: true);

$app->run();

React Render

<?php
include_once __DIR__."/app/index.php";

$app->get(callback: function($req, $res) use ($app) {
        
        //Example render Twig and React Island app/templates/react_integration.twig
        return $app->render(template:"react_integration", 
        context:
        [
            "app" => [
                "debug" => $app->getEnv("DEBUG")
            ]
        ]);

        //Example render full page React app/resources/ReactExample.jsx
        return $app->renderReact(
            page: "ReactExample",
            props: [
                "app" => [
                    "debug" => $app->getEnv("DEBUG")
                ],
                "csrf"=>Security::generateCsrfToken() ,
                "translations"=>Translate::translations()
            ],
            options: [
                "lang" => "es",
                "title" => "React full Page + LilaPHP",
                "meta" => [
                    ["name" => "description", "content" => "React full page render example meta description"]
                ],

                "scripts" => [
                    "https://cdn.tailwindcss.com"
                ]
            ]
        );
  
});
 

$app->run();

In React receives props

export default function ReactIsland({ csrf, translations }) { 
    ...
}

πŸ”„ Re-rendering React Islands

You can trigger a re-render of your React islands from standard JavaScript (e.g., from Twig templates, jQuery, or other non-React code) using the global function:

// Re-render all React components on the page
window.renderReactComponent();

// Re-render only components named 'CartBadge'
window.renderReactComponent('CartBadge');

This is incredibly useful for updating separate component roots when reading shared client endpoints (such as localStorage) from external areas.

Validation with PHP 8 Attributes

use Core\BaseModel;
use Core\Field;

class LoginModel extends BaseModel
{
    #[Field(required: true, format: "email")]
    public string $email;

    #[Field(required: true, min_length: 6)]
    public string $password;
}

$app->post(
    callback: fn($req, $res) => $app->jsonResponse(["success" => true]),
    middlewares: [
        fn($req, $res) => new LoginModel(data: $req)
    ],
    csrf: true
);

Sessions

$app->setSession("user_id", 1);
$user = $app->getSession("user_id");
$app->removeSession("user_id");

🌍 Localization

LilaPHP includes native support for multi-language applications.

Define default language in .env:

LANG_DEFAULT="esp"

Translation files structure:

app/locales/
β”œβ”€β”€ esp.php
β”œβ”€β”€ eng.php
β”œβ”€β”€ bra.php
└── por.php

Example translation file:

<?php
// app/locales/eng.php
return [
    "welcome" => "Welcome!",
    "login" => [
        "title" => "Login",
        "email" => "Email address"
    ]
];

Using in Twig templates:

<h1>{{ translate("welcome") }}</h1>
<h2>{{ translate("login.title") }}</h2>

Dynamic language switching:

$app->get(callback: function($req, $res) use ($app) {
    $lang = $_GET['lang'] ?? $app->getLangDefault();
    $app->setSession("lang", $lang);
    $back = $_SERVER['HTTP_REFERER'] ?? '/';
    $app->redirect($back);
});

πŸ”’ Security & CSRF Protection

LilaPHP includes built-in CSRF protection for POST, PUT, and DELETE requests.

$app->post(
    callback: fn($req, $res) => $app->jsonResponse(["success" => true]),
    middlewares: [fn($req, $res) => new LoginModel(data: $req)],
    csrf: true
);

In your Twig template:

<form method="POST">
    {{ csrf_input() }}
    <input type="email" name="email" required />
    <input type="password" name="password" required />
    <button type="submit">Login</button>
</form>

🎨 Twig Template Functions

LilaPHP extends Twig with powerful built-in helpers:

  • image(file, width, height, quality, type) β€” Generates optimized WebP or ICO images
  • url(path) β€” Returns the full absolute project URL
  • csrf_input() β€” Outputs the hidden CSRF token field
  • translate(key) or __(key) β€” Returns translated strings

Example:

<link rel="icon" href="{{ image('img/lila.png', 40, 0, 70, 'ico') }}" />
<img src="{{ image('img/lila.png', 200) }}" width="200" alt="LilaPHP" />

πŸ—„οΈ Database (PDO)

LilaPHP provides a unified database connection layer with automatic retry logic.

Configure in .env:

DB_PROVIDER="mysql"
DB_HOST="localhost"
DB_USER="root"
DB_PASSWORD=""
DB_NAME="db_test"
DB_PORT="3306"

Using the database:

$app->get(callback: function ($req, $res) use ($app) {
    $db = $app->getDatabaseConnection();
    $sql = "SELECT * FROM `users`";
    $result = $db->query($sql);
    $users = $result->fetchAll();

    return $app->render(template: "login", context: ["users" => $users]);
});

Multiple database connections:

// Default connection
$db1 = $app->getDatabaseConnection();

// Custom connection
$db2 = $app->getDatabaseConnection(
    provider: "pgsql",
    host: $app->getEnv("DB_HOST_2"),
    dbUser: $app->getEnv("DB_USER_2"),
    dbPassword: $app->getEnv("DB_PASSWORD_2"),
    dbName: $app->getEnv("DB_NAME_2"),
    port: 5432
);

πŸ”§ CLI Commands and Migrations

LilaPHP includes a powerful CLI system for database migrations and seeders.

Quick Start

# Create database and run migrations
cd app
php cli.php migrate:create

# Check migration status
php cli.php migrate:status

# Run seeders
php cli.php seed:run

Available Commands

Migration Commands:

php cli.php migrate:create    # Create database and run all migrations
php cli.php migrate:run        # Run pending migrations
php cli.php migrate:status     # Show migration status
php cli.php migrate:fresh      # Drop all tables and re-migrate (WARNING: destructive)
php cli.php migrate:rollback   # Rollback last migration

Seeder Commands:

php cli.php seed:run           # Run all seeders
php cli.php seed:create UserSeeder  # Create a new seeder

Creating Models with Migrations

Use the FieldDatabase attribute to define your database schema alongside validation rules:

<?php

namespace Models;

use Core\BaseModel;
use Core\Field;
use Core\FieldDatabase;

class User extends BaseModel
{
    #[FieldDatabase(type: 'int', primaryKey: true, autoIncrement: true)]
    protected int $id;

    #[FieldDatabase(type: 'datetime', default: 'CURRENT_TIMESTAMP')]
    protected string $created_at;

    #[Field(required: true, format: 'email')]
    #[FieldDatabase(type: 'varchar', length: 255, unique: true)]
    public string $email;

    #[Field(required: true, min_length: 6)]
    #[FieldDatabase(type: 'varchar', length: 255)]
    public string $password;
}

Supported Field Types:

  • Numeric: int, bigint, smallint, tinyint, decimal, float, double
  • String: varchar, char, text, mediumtext, longtext
  • Date/Time: date, datetime, timestamp, time
  • Other: boolean, json

Field Attributes:

  • type - Column type
  • length - Column length (for varchar/char)
  • nullable - Allow NULL values
  • default - Default value (use 'CURRENT_TIMESTAMP' for timestamps)
  • primaryKey - Mark as primary key
  • autoIncrement - Enable auto-increment
  • unique - Add unique constraint
  • index - Create index
  • unsigned - For numeric types (MySQL)
  • comment - Column comment

Creating Seeders

Generate a seeder template:

php cli.php seed:create UserSeeder

This creates app/cli/seeders/UserSeeder.php:

<?php

namespace Cli\Seeders;

use PDO;

class UserSeeder
{
    private PDO $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function run(): void
    {
        $stmt = $this->db->prepare("
            INSERT INTO users (email, password, created_at) 
            VALUES (?, ?, NOW())
        ");

        $users = [
            ['user1@example.com', password_hash('password123', PASSWORD_DEFAULT)],
            ['user2@example.com', password_hash('password123', PASSWORD_DEFAULT)],
        ];

        foreach ($users as $user) {
            $stmt->execute($user);
        }
    }
}

Workflow Example

# 1. Configure database in .env
DB_PROVIDER="mysql"
DB_HOST="localhost"
DB_USER="root"
DB_PASSWORD=""
DB_NAME="my_app"
DB_PORT="3306"

# 2. Create your models in app/models/

# 3. Run migrations
cd app
php cli.php migrate:create

# 4. Create and run seeders
php cli.php seed:create UserSeeder
# Edit app/cli/seeders/UserSeeder.php
php cli.php seed:run

# 5. Verify
php cli.php migrate:status

Database Support: MySQL/MariaDB, PostgreSQL, SQLite

⚑ Performance

When DEBUG=false, LilaPHP automatically:

  • βœ… Minifies HTML, CSS, and JavaScript
  • βœ… Generates optimized WebP images
  • βœ… Caches Twig templates
  • βœ… Loads only required components per route

🏭 Production Deployment

Environment Configuration

Set DEBUG=false in your .env file:

DEBUG=false

Restrict Access to /app Directory

NGINX:

location /app {
    deny all;
}

Apache (.htaccess):

<Directory "app">
  Order allow,deny
  Deny from all
</Directory>

πŸ“š Documentation

Full documentation is available at: https://seip25.github.io/LilaPHP/

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

This project is open-source and available under the MIT License.

πŸ‘¨β€πŸ’» Author

AndrΓ©s Paiva - GitHub