Official documentation
Build with PHPAML.
From first project to production.
Complete guide to the autonomous AML environment and the PHPAML MVC mini-framework.
Three paths, a first result in under five minutes
AML bundles PHP and Composer, creates the selected structure, and installs its dependencies automatically. Choose the classic application for MVC, AML View for a declarative reactive interface, or API for a focused JSON service.
aml create my-project
cd my-project
aml serveaml create-view-app my-interface
cd my-interface
aml serveaml create-api my-api
cd my-api
aml serveThen open http://127.0.0.1:8910. Use aml doctor whenever you want to verify the environment. For the current folder, use aml create ..
Creation commands produce a runnable project directly. The browser then reloads after each supported change.
Three readable structures, one configuration model
PHPAML separates responsibilities without adding empty folders. The classic project keeps app and its WebApp route map. AML View organizes backend and interface code under src. An API removes views and uses one route class per resource.
app/ ├── Controllers/ ├── Models/ └── views/ routes/WebApp.php public/index.php
src/
├── controllers/
├── models/
├── middleware/
├── locales/
└── views/
├── pages/
├── components/
├── layouts/
├── states/
└── stylesheets/
routes/WebApp.phpsrc/
├── controllers/
├── models/
├── repositories/
├── requests/
├── resources/
├── middleware/
└── routes/
└── MovieRoute.php
public/index.phpConfiguration without a configs folder
In new projects, phpaml.json stores shareable choices while .env stores secrets and machine-specific values. PHPAML builds runtime/config/app.php automatically. That generated file belongs to the runtime and must never be edited.
Request lifecycle
- public/index.php loads phpaml.json and .env.
- Middleware processes the request.
- The router discovers routes/ or src/routes/.
- The container injects controller dependencies.
- The action returns HTML, JSON, or a redirect.
Move from aml_env to runtime
Older projects use aml_env, info.json, or app/View. The migration also renames app/View to app/UI. Always preview the conversion before applying it. AML creates a backup under runtime/storage/migrations before renaming files and updating known references.
aml migrate:structure
aml migrate:structure --apply --yes
aml doctor --offline
aml testruntime/storage/migrations/structure-<date>/
AML command reference
On first launch, AML asks for English or French. Output, diagnostics, and errors follow that choice. AML_LANG=en or AML_LANG=fr temporarily overrides it.
aml create .Create in the current folderaml create my-projectCreate a classic app folderaml create-view-app my-uiCreate an AML View applicationaml create-api my-apiCreate a focused JSON APIaml installInstall engine and dependenciesaml serveStart from port 8910 with live reloadaml routesList registered routesaml testRun tests/run.phpaml buildCreate a verified production archiveaml deploy productionBuild and deploy a configured profileaml deploy:rollback productionRestore the previous releaseaml make:controller UserGenerate a controlleraml make:model UserGenerate a modelaml make:middleware AuthGenerate middlewareaml make:migration create_users_tableGenerate a migrationaml env:initCreate .env from .env.exampleaml env:listList variables and mask secretsaml env:get APP_DEBUGRead one variableaml env:set APP_DEBUG falseCreate or update one variableaml db:showShow database configurationaml doctorCheck AML and the projectaml cache:clearClear application cacheaml update --checkCheck for a new releaseaml updateInstall the latest releaseaml language frChange the CLI languageUseful options
aml create project --version 0.1.0
aml create project --offline
aml install --production
aml install --refresh
aml doctor --offline
aml doctor --port 8080
aml doctor --production --json
aml update --version 1.3.0Routes, requests, and controllers
'GET /users/{id}' => [
'handler' => [UserController::class, 'show'],
'middleware' => [AuthMiddleware::class],
'name' => 'users.show',
],public function show(Request $request): Response
{
return $this->json(['id' => $request->attribute('id')]);
}Request provides method(), path(), query(), input(), cookie(), header(), server(), and attribute(). JSON is decoded automatically. An unknown route returns 404; an unsupported method returns 405.
return Response::html('<h1>Hello</h1>');
return Response::json(['ok' => true], 201);
return Response::redirect('/login');
return $this->view('users/show.php', ['user' => $user]);Declarative views and assets
Classic applications may keep PHP templates and partials. An AML View application places pages, components, layouts, and states in src/views. Stylesheets are discovered automatically under src/views/stylesheets, while AML serves the JavaScript engine automatically.
src/views/pages/home/page.php
src/views/components/Navigation.php
src/views/layouts/DashboardLayout.php
src/views/stylesheets/pages/home.css
assets/images/hero.webp
public/favicon.svgConfigure .env from the command line
aml env:init
aml env:set APP_DEBUG false
aml env:get APP_DEBUG
aml env:listenv:init copies .env.example; --force replaces an existing file. env:list masks passwords, secrets, keys, and tokens. Never commit .env to Git.
SQLite, MySQL, and migrations
SQLite is the default local database. AML creates runtime/storage/database.sqlite and records root/root by convention; SQLite does not actually use these credentials.
aml db:configure sqlite
aml db:configure sqlite --path storage/app.sqlite
aml db:show
aml db:configure mysql --host 127.0.0.1 --port 3306 \
--database phpaml --user root --password rootTransactional migrations
aml make:migration create_users_table
aml migrate
aml migrate:rollback --steps 1Migrations are recorded in aml_migrations. Migrations are ordered and locked. migrate:rollback runs down() in reverse order. QueryBuilder provides all() and insert(); use prepared PDO for everything else.
Validation, CSRF, and middleware
$valid = $validator->validate($request->input(), [
'email' => ['required', 'email'],
'name' => ['required', 'string', 'min:2', 'max:100'],
]);Rules: required, email, string, min:n, and max:n. Protect write routes with CsrfMiddleware and add <?= $this->csrfField() ?> to forms. For an API, use X-CSRF-Token.
SecurityHeadersMiddleware adds security headers; error details are hidden when APP_DEBUG=false.
Test and prepare for production
aml test
aml install --production
aml doctor --production --json
aml routesaml test uses AML's private PHP and runs tests/run.php. --production excludes development dependencies and optimizes the autoloader.
aml serve is for development only. In production: a PHP-compatible HTTP server, HTTPS, APP_DEBUG=false, minimal permissions, backups, and appropriate authentication.
Solve common problems
The aml command is not found
Open a new terminal and check PATH: %LOCALAPPDATA%\Programs\PHPAML\bin on Windows, /usr/local/bin on macOS/Linux.
The AML environment is missing
From the project root, run aml install.
CSS or JavaScript does not load
Check /public/, filename casing, and run aml serve from the folder containing public/index.php.
Port 8000 is busy
aml doctor --port 8080aml serve 127.0.0.1:8080
GitHub is unavailable
Use aml create project --offline or aml install --offline to reuse the cache.
Control SEO from AML
AML centralizes metadata, generates search-engine files, and audits the published HTML.
aml seo:init
aml seo:set base_url "https://example.com"
aml seo:set title "My website"
aml seo:set description "A clear description between 50 and 160 characters."
aml seo:disallow /admin
aml seo:allow /admin/public
aml seo:generate
aml seo:audit https://example.com --jsonseo:generate creates public/sitemap.xml and public/robots.txt from static GET routes. Disallowed routes are removed from the sitemap. seo:audit checks the title, description, canonical URL, Open Graph, Twitter Cards, JSON-LD, language, viewport, H1, images, and HTTPS.
A disallow rule guides crawlers but does not protect a page. Use authentication and middleware for private areas.
Build and deploy anywhere
aml build runs the tests, checks public/.htaccess, and creates a ZIP archive, manifest, and SHA-256 checksum in output/. Secrets and non-runtime material are excluded: .env, logs, SQLite databases, tests, temporary files, output/, and deliverables/.
aml build
aml build --skip-tests
aml deploy:configure production --host example.com --user deploy \
--path /home/deploy/site --port 22 --key ~/.ssh/id_ed25519
aml deploy:check production
aml deploy production
aml deploy:rollback productionChoose a strategy
releasesTimestamped releases, current symlink, and atomic rollbackpublic-htmlShared hosting with a separate public_htmlsftp-onlyServer without SSH shell accessaml deploy:configure hostinger --host example.com --user deploy \
--path /home/user/domains/example.com \
--strategy public-html \
--public-path /home/user/domains/example.com/public_html \
--key ~/.ssh/id_ed25519The private profile is stored in ~/.phpaml/deploy.json with 600 permissions. AML stores no passwords: use an SSH key. The domain must point to public/ or, with public-html, to the configured public path. Visitors get /about, never /index.php/about.
AML removes incomplete archives when disk space or output/ access fails. Temporary GitHub errors are retried automatically up to three times.
Install components independently
AML creation commands configure the correct components automatically. In an existing Composer project, declare collaborating prerelease packages together so the root project explicitly accepts their stability level.
composer require \
phpaml/view:^0.1@beta \
phpaml/engine:^0.1@betacomposer require \
phpaml/data:^0.2@alpha \
phpaml/data-mongodb:^0.1@alphaEngine, Data, and i18n can also be installed alone. The MongoDB adapter requires the PHP mongodb extension, while SQL Data requires PDO.
Build a declarative, reactive interface
AML View is PHPAML’s optional frontend layer. PHP renders the first document, then Engine manages state, effects, collections, themes, and navigation locally.
aml create-view-app my-interface
cd my-interface
aml serve
# http://127.0.0.1:8910src/
├── controllers/
├── models/
├── middleware/
└── views/
├── pages/{route}/page.php
├── components/
├── layouts/
├── states/{Loading,Error,NotFound}.php
├── stylesheets/
├── themes/
└── assets/src/views, src/controllers, and src/models are required. CSS is collected from src/views/stylesheets. Imported assets stay in assets; favicon, robots.txt, and sitemap.xml stay in public/.
#[State]
public int $count = 0;
public function body(): View
{
return VStack(
Heading('AML View')->class('page-title'),
Text("Count: {$this->count}"),
Button('Add one')->onClick(fn () => $this->count++),
);
}Compiled interactions run in the browser without calling PHP again. Effects provide dependencies, cleanup, debounce, throttle, latest cancellation, loading/success/error states, and cycle protection.
Engine replaces only the RouterView boundary, preserves the document, updates history, metadata, and focus, then uses Loading, Error, or NotFound for the response state.
JSON internationalization
aml install i18n
aml i18n:add es
aml i18n:list
aml i18n:check
aml i18n:missing fr
aml i18n:set-default enOrganize files freely under src/locales/{locale}. Paths become dotted keys, parameters use :name, one/other plural forms use the count, and LocaleResolver selects a supported locale from the route, cookie, or Accept-Language.