THE MODULAR PHP FRAMEWORK
~ Pragmatically Opinionated ~
Every feature is a power-up. Equip what you need, leave the rest. No forced load-outs.
Everything is a module. Vendor, third-party, and app code all follow the same pattern. Equip, swap, or remove at will.
Swap any class implementation with a single attribute. Like changing weapons mid-battle. No config files needed.
Before and After hooks on any method. Modify behavior without touching source code. Like enchanting your gear.
Decouple "something happened" from reactions. Dispatch events, observers react. Clean signal system.
No XML. No YAML. No DSL. PHP 8.5+ attributes and native code. Your IDE actually understands everything.
Loud errors that guide you to the fix. Like helpful NPCs who tell you exactly where to go. No more cryptic stack traces.
Real PHP attributes. Real power. Each spell (attribute) unlocks a new ability for your application.
// Swap any class. One attribute. #[Preference(replaces: FlatRate::class)] class ZoneShipping extends FlatRate { public function calculate( Cart $cart, ): Rate { return $this->rateByAddress( $cart->address, ); } }
// Enchant any method. Before & After hooks. #[Plugin(target: OrderService::class)] class OrderLogger { #[Before] public function beforePlace( Order $order, ): ?Order { $this->logger->info( 'Placing order', ['id' => $order->id], ); return null; } }
// React to events. Decoupled & clean. #[Observer(UserCreatedEvent::class)] class SendWelcomeEmail { public function handle( UserCreatedEvent $event, ): void { $user = $event->getUser(); $this->mailer->send( new WelcomeEmail($user), ); } }
// Fast travel. PHP attributes as routes. class ProductController { #[Get('/products/{id}')] public function show( int $id, ): Response { $product = $this->productRepo->find($id); return new Response($product); } }
The old ways are powerful but broken. Time for a new hero to rise.
Marko's clean architecture means AI agents can build, test, and ship modules effortlessly. Your most powerful party member.