Getting Started
MonkeysLegion is a full-stack PHP framework focused on developer joy and production-grade defaults.
If you’ve used Laravel’s elegance, Symfony’s rigor, or Next.js’s DX, you’ll feel at home in minutes—minus the heavyweight baggage.
Why MonkeysLegion?
Modular: Every feature—routing, templates, auth, i18n—lives in a separate Composer package. Pick only what you need.
Typed: PHP 8.4+, constructor DI, strict DTO validation, and reflection-powered auto-wiring.
Zero-config DX: Hot-reload dev server, one CLI for every workflow, and .mlc files for human-friendly config.
Batteries included: JWT auth, attribute-based policies, PSR-14 event bus, Prometheus metrics, and more.
1 · Create a new project
composer create-project monkeyscloud/monkeyslegion-skeleton myapp
cd myapp
php vendor/bin/ml key:generate # RSA keypair for JWT signing
php vendor/bin/ml serve --open # starts the hot-reload dev server
Open http://localhost:8000 and you’ll see “Hello MonkeysLegion!” served by the Router and Template engine.
2 · Project anatomy
myapp/
├─ app/
│ ├─ Controller/ # HTTP / CLI controllers
│ ├─ Entity/ # Attribute-mapped domain objects
│ └─ Repository/ # Query + data-access classes
├─ config/ # .mlc environment config
├─ database/
│ ├─ migrations/ # Generated migration classes
│ └─ seeders/ # Data fixtures
├─ public/ # Web root (index.php, JS/CSS, images)
├─ resources/
│ └─ views/ # .ml.php templates and components
└─ vendor/ # Composer dependencies
Everything is PSR-4 autoloaded; add namespaces anywhere under app/.
3 · Your first route
src/Http/Controller/PostController.php
use MonkeysLegion\Router\Attribute\Route;
use Laminas\Diactoros\Response\JsonResponse;
final class PostController
{
#[Route('GET', '/posts')]
public function index(): JsonResponse
{
return new JsonResponse([
['id'=>1,'title'=>'First post'],
['id'=>2,'title'=>'Second post'],
]);
}
}
Save—dev server auto-refreshes—and http://localhost:8000/posts returns JSON.
4 · Persisting data
php vendor/bin/ml make:entity Post
Edit the generated entity, then:
php vendor/bin/ml migrate
A migration class is created and executed; your MySQL schema is now in sync.
Use the out-of-the-box EntityRepository:
$posts = $container->get(App\Repository\PostRepository::class)->findAll();
5 · Adding auth
php vendor/bin/ml make:controller AuthController
Inside:
#[Route('POST','/login')]
public function login(LoginUser $dto, AuthService $auth): JsonResponse
{
[$token] = $auth->attempt($dto->email, $dto->password);
return new JsonResponse(['token'=>$token]);
}
Protect routes with a policy:
#[Can('edit', Post::class)]
#[Route('PUT','/posts/{id}')]
public function update(...) { … }
JwtAuthMiddleware + AuthorizationMiddleware enforce everything.
6 · Next steps
Topic | Where to go |
---|---|
Requirements & Installation | |
Entities & Migrations | |
Templates & Components | |
CLI reference | |
Telemetry & Metrics | |
Deployment guide |
Join #monkeyslegion on Slack.
File issues or feature requests on GitHub.
Read the full package docs linked above.
Happy coding—you’re officially a Legionnaire! 🐒🎉