Framework
PHP 8.1 · MySQLi · Zero-config discovery

A PHP Framework,
built for building fast.

A batteries-included toolkit: a discovery-driven code generator, a schema‑first database layer, and a broad, well-typed standard library — wired together by a single ./framework CLI.

Why Framework

🔎 Discovery driven

Routes, listeners, models, settings and commands are found by their attributes — nothing is registered in a central file that drifts out of date.

🗄️ Schema-first data

Describe a table once as a model; the build generates its schema, typed queries, entities and requests, and a migration keeps the database in step.

🧭 Typed end to end

Generated classes mean a renamed column or a missing route is a build error, not a surprise at runtime.

⌨️ First-class CLI

Install, build, migrate, watch for changes and generate icons — all from one ./framework binary, which your own commands join.

🧰 Rich standard library

Strings, Arrays, Numbers, Dates, Files, a Dictionary wrapper and more — strict-typed and covered by an extensive test suite.

🔌 Batteries included

Auth, emails, notifications, logging, imports, icons and integrations from OpenAI to MercadoPago, ready to switch on.

Quick start

Add the repository and require the package, then run the installer:

composer.json
"repositories": [
    { "type": "git", "url": "https://github.com/FrameworkPHPAR/Framework.git" }
],
"require": {
    "frameworkphpar/framework": "dev-main#v0.17.0"
}
./vendor/bin/framework install

Read the full setup guide →

A taste of it

One annotated class describes a table. The build turns it into the schema, query, entity and request classes you write against:

#[Model(hasTimestamps: true, canCreate: true, canEdit: true)]
class ProductModel {
    #[Field(isID: true)]
    #[Requested(isID: true)]
    public int $productID;

    #[Field(isUnique: true, length: 100)]
    #[Validate(isRequired: true)]
    #[Requested]
    public string $name;
}

A route is a method with an attribute, typed on both ends:

#[Route("/products/edit", Access::Admin)]
public static function edit(ProductRequest $request): Response {
    $result = Product::validateRequest($request);
    if ($result->hasError()) {
        return Response::error($result->errors);
    }

    Product::edit($request->id, $request);
    return Response::success("PRODUCT_EDITED");
}

Find your way around

The guides are grouped by what you are doing. Everything is in the sidebar — or press ⌘K to search.