/mu

The 3-LOC µ (mu) PHP Micro-framework. Just cuz.

Primary LanguagePHPMIT LicenseMIT

The µ PHP Micro-framework

A "real" :trollface: micro-framework that fits in just 3 lines of code.

The "micro-frameworks" out there weren't micro enough for me, so I brushed up on some of my code golfing skills to create µ.

Check out the code!

Where "line of code" means "as much code as possible crammed into <= 120 characters".

Features

These 3 LOC come jam-packed with features!

Easy, regex-based routing system

Follows the well-established route-to-callable micro-framework pattern.

(new µ)
    ->get('/hello', function () {
        echo "<p>Hello, world!</p>";
    })
    ->run();

Allows you to access parameters from the URL.

(new µ)
    ->get('/hello/(?<name>\w+)', function ($app, $params) {
        echo "<p>Hello, {$params['name']}!</p>";
    })
    ->run();

Supports all your favorite HTTP verbs.

(new µ)
    ->delete('/user/(?<id>\d+)', $fn)
    ->get('/user/(?<id>\d+)', $fn)
    ->head('/user/(?<id>\d+)', $fn)
    ->patch('/user/(?<id>\d+)', $fn)
    ->post('/users', $fn)
    ->put('/user/(?<id>\d+)', $fn)
    ->run();

Simple dependency/config container

use Monolog\Handler\StreamHandler;
use Monolog\Logger;

(new µ)
    ->cfg('log.channel', 'your-app')
    ->cfg('log.handler', function () {
        return new StreamHandler('path/to/your.log', Logger::DEBUG);
    })
    ->cfg('log', function ($app) {
        $log = new Logger($app->cfg('log.channel'));
        $log->pushHandler($app->cfg('log.handler'));
        return $log;
    })
    ->get('/hello/(?<name>\w+)', function ($app, $params) {
        $app->cfg('log')->debug("Said hello to {$params['name']}");
        echo "<p>Hello, {$params['name']}!</p>";
    })
    ->run();

If a callable is provided (like with log.handler above), then it is treated as a factory and is only called once to produce a singleton value for efficient, multiple accesses.

A truly elegant and fluent interface

See previous example (I'm lazy).

Built-in templating system, free of {}

Templates are just PHP files—no mustaches and no frills.

<!-- templates/hello.php -->
<html>
  <head>
    <title>World Greeter</title>
  </head>
  <body>
    <p><?= ucfirst($greeting) ?>, <?= $name ?>!</p>
  </body>
</html>
// index.php
(new µ)
    ->get('/hello/(?<name>\w+)', function ($app, $params) {
        echo $app->view(__DIR__ . '/templates', 'hello', [
            'greeting' => 'howdy',
            'name'     => $params['name'],
        ]);
    })
    ->run();

No Twigs, Plates, or Blades to cut you or poke you. That might feel a little dull, but it's simple.

Design constraints

  • Must have at least a Router, Container, and Templating System as features.
  • Must attempt to incorporate usage patterns (e.g., chainable methods, closures as controllers) that resemble other contemporary micro-frameworks.
  • Must work with error_reporting set to -1 (all errors reported).
  • Must not exceed 3 lines of code (LOC), where each line is <= 120 characters.
  • Must not have dependencies on other packages.
  • May break traditional coding conventions/styles for the sake of brevity.
  • Must be hand-written, not minified/obfuscated by any tools.

It works, but it's really just a joke.

Don't use this in production, or really anywhere. It's just for fun. 😄

If you want to use a production-quality micro-framework, try Slim.

Examples

The code examples in this README are also shipped as working examples in the /examples directory.

To run an example, use the built-in PHP server.

# For the hello1 example:
php -S localhost:8000 examples/hello1.php

Then access http://localhost:8000 in your browser or via cURL.

Tests

A very basic test suite is included, and can be run via:

php test.php