Request-Route-Ракушки-Response
No model, no view, no controller, no MVC.
No ORM. No template.
No convention, no configuration.
No middleware. No framwork. No WAF.
Ranyuen/Little is a simple & scalable kernel to constract all size of Web applications. Based on Ranyuen/Di & Symfony Components.
cf. codeguy/Slim
cf. silexphp/Silex
- Simple routing API like every micro WAFs.
- DI/AOP support with Ranyuen/Di.
- Pluggable routing logic.
composer require ranyuen/little
Support PHP >=7.4.
For more details please see tests/ directory.
For small Web pages.
<?php
require 'vendor/autoload.php';
use Ranyuen\Little\Router;
use Ranyuen\Little\Request;
$r = new Router();
$r->get('/', function () {
return 'Hello.';
});
$r->error(404, function () {
return 'Not Found';
});
$r->group('/blog', function ($r) {
$r->get('/:year/:month/:date', function ($year, $month, $date) {
return "View articles at $year-$month-$date.";
})
->assert('year', '/\d{4}/')
->assert('month', '/\d{1,2}/')
->assert('date', '/\d{1,2}/');
$r->get('/category', function ($name = 'all') {
return "List articles in $name.";
});
$r->error(404, function ($req) {
return "{$req->getPathInfo()} is not found.";
});
});
$r->run(Request::createFromGlobals())->send();
For more large pages we can use controller class.
<?php
require 'vendor/autoload.php';
use Ranyuen\Little\Router;
use Ranyuen\Little\Request;
class IndexController {
public function index() {
return 'Hello.';
}
public function notFound() {
return 'Not Found';
}
}
class BlogController {
public function show($year, $month, $date) {
return "View articles at $year-$month-$date.";
}
public function category($name = 'all') {
return "List articles in $name.";
}
public function notFound($req) {
return "{$req->getPathInfo()} is not found.";
}
}
$r = new Router();
$r->get('/', 'IndexController@index');
$r->error(404, 'IndexController@notFound');
$r->group('/blog', function ($r) {
$r->get('/:year/:month/:date', 'BlogController@show')
->assert('year', '/\d{4}/')
->assert('month', '/\d{1,2}/')
->assert('date', '/\d{1,2}/');
$r->get('/category', 'BlogController@category');
$r->error(404, 'BlogController@notFound');
});
$r->run(Request::createFromGlobals())->send();
For complex pages config or annotations are useful.
<?php
require 'vendor/autoload.php';
use Ranyuen\Di\Container;
use Ranyuen\Little\Router;
use Ranyuen\Little\Request;
use Ranyuen\Little\Response;
class IndexController {
/** @Route('/') */
public function index() {
return 'Hello.';
}
/** @Route(error=404) */
public function notFound() {
return 'Not Found';
}
}
/** @Route('/blog') */
class BlogController {
/**
* @Inject
* @var PDO
*/
private $db;
/** @Inject */
private $view;
/** @Inject */
private $auth;
/** @Route('/:year/:month/:date',assert={year:'/\d{4}/',month:'/\d{1,2}/',date:'/\d{1,2}/'}) */
public function show($year, $month, $date) {
return "View articles at $year-$month-$date.";
}
/** @Route('/category') */
public function category($name = 'all') {
return "List articles in $name.";
}
/**
* @Route('/edit/:id?')
* @Wrap('auth')
*/
public function edit(Request $req, $id = 0) {
return $this->view->render('blog/edit');
}
/**
* @Route('/save/:id',via=POST)
* @Wrap('auth')
*/
public function save(Request $req, $id, $title, $content) {
$id = (int)$id;
if (0 === $id) {
$statement = $this->db->prepare('INSERT INTO blog(title, content) VALUES (:title, :content)');
} else {
$statement = $this->db->prepare('UPDATE blog SET title = :title, content = :content WHERE id = :id');
$statement->bindParam('id', $id);
}
$statement->bindParam('title', $title);
$statement->bindParam('title', $content);
$statement->execute();
return new Response('', 303, ['Location' => '/blog/']);
}
/**
* @Route('/save/:id',via=DELETE)
* @Wrap('auth')
*/
public function destroy(Request $req, $id) {
$statement = $this->db->prepare('DELETE blog WHERE id = :id');
$statement->bindParam('id', $id);
$statement->execute();
return new Response('', 303, ['Location' => '/blog/']);
}
/** @Route(error=403) */
public function forbidden() {
return new Response('', 403);
}
/** @Route(error=404) */
public function notFound(Request $req) {
return "{$req->getPathInfo()} is not found.";
}
}
$c = new Container();
$c['db'] = function (Container $c) {
return new \PDO('mysql:host=localhost;dbname=rrrr;charset=utf8', 'user', 'password');
};
$c['view'] = function (Container $c) {
// Some template engine.
};
$c['auth'] = $c->protect(function ($invocation, $args) {
$req = $args[0];
if (fail($req)) { // Some authentication logic.
throw new \Ranyuen\Little\Exception\Forbidden();
}
return call_user_func_array($invocation, $args);
});
Router::plugin('Ranyuen\Little\Plugin\ControllerAnnotationRouter');
$r = new Router($c);
$r->registerController('IndexController');
$r->registerController('BlogController');
$req = Request::createFromGlobals();
$res = $r->run($req);
$res->send();