Skip to content

Instantly share code, notes, and snippets.

@pimbrouwers
Last active May 28, 2020 14:06
Show Gist options
  • Save pimbrouwers/93fc248c6ac1a0276271b6422180e1c5 to your computer and use it in GitHub Desktop.
Save pimbrouwers/93fc248c6ac1a0276271b6422180e1c5 to your computer and use it in GitHub Desktop.
Turnpike

Turnpike

<?php
$db = new Turnpike\Db($dsn, DB_USER, DB_PASS);
$viewEngine = new Turnpike\PhpViewEngine(TEMPLATE_ROOT);
$mux = new Turnpike\Router;

// Middleware 
$mux->Run(function (Turnpike\Request $req, Turnpike\Response $res) {
  // ...
}
          
// Controllers
$userController = new MyApp\Features\User\UserController($viewEngine);
$mux->RouteMethod('/^\/user\/login\/?$/i', $userController, 'Login');
          
// Handle incoming request 
$mux->Execute(function ($request, $response) use ($viewEngine) {
  $response->setBody($viewEngine->render('404.php'));
});
<?php
namespace Turnpike;
class Controller
{
protected $viewEngine;
function __construct(PhpViewEngine $viewEngine)
{
$this->viewEngine = $viewEngine;
}
}
<?php
namespace Turnpike;
use PDO;
class Db extends PDO
{
public function __construct($dsn, $username = null, $password = null, $options = [])
{
$default_options = [
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];
$options = array_replace($default_options, $options);
parent::__construct($dsn, $username, $password, $options);
}
public function Qry($sql, $args = null)
{
if (!$args) {
return $this->query($sql);
}
$stmt = $this->prepare($sql);
$stmt->execute($args);
return $stmt;
}
}
<?php
namespace Turnpike;
class PhpViewEngine
{
private $templateRoot;
function __construct(string $templateRoot)
{
$this->templateRoot = $templateRoot;
}
function render(string $templatePath, $data = null)
{
// buffer the page
ob_start();
// extract page key/value's
if (is_array($data)) {
extract($data);
} else if (is_object($data)) {
extract(get_object_vars($data));
}
// include template
include_once($this->templateRoot . $templatePath);
return ob_get_clean();
}
}
<?php
namespace Turnpike;
class Request
{
private $method;
private $uri;
private $headers;
private $query;
public function __construct()
{
$this->bootstrap();
}
public function GetMethod(): string
{
return $this->method;
}
public function GetUri(): string
{
return $this->uri;
}
public function GetQuery(): array
{
return !empty($this->query) ? $this->query : [];
}
public function GetBody() : array
{
switch ($this->method) {
case 'POST':
return filter_input_array(INPUT_POST);
default:
return array();
}
}
public function GetHeaders() : array
{
return $this->headers;
}
public function GetCookie(string $name)
{
return filter_input(INPUT_COOKIE, $name, FILTER_SANITIZE_STRING);
}
private function Bootstrap() : void
{
$args = array(
'REQUEST_METHOD' => FILTER_DEFAULT,
'QUERY_STRING' => FILTER_DEFAULT,
'REQUEST_URI' => FILTER_DEFAULT);
$serverVars = filter_input_array(INPUT_SERVER, $args);
$this->method = $serverVars['REQUEST_METHOD'];
$this->uri = str_replace('?' . $serverVars['QUERY_STRING'], '', $serverVars['REQUEST_URI']);
$this->headers = getallheaders() ?? array();
$this->query = filter_input_array(INPUT_GET);
}
}
<?php
namespace Turnpike;
class Response
{
private $headers = array();
private $statusCode = 200;
private $body = '';
public function AddHeader(string $name, string $value): void
{
$this->headers[$name] = $value;
}
public function SetContentType(string $contentType)
{
$this->AddHeader('Content-Type', $contentType);
}
public function GetStatusCode(): int
{
return $this->statusCode;
}
public function SetStatusCode(int $code): void
{
$this->statusCode = $code;
}
public function SetCookie(string $name, string $content)
{
setcookie($name, $content, 0, '/');
}
public function RemoveCookie(string $name)
{
setcookie($name, '', 1, '/');
}
public function GetBody(): string
{
return $this->body;
}
public function SetBody(string $body): void
{
$this->body = $body;
}
public function Execute(): void
{
foreach ($this->headers as $k => $v) {
header($k . ': ' . $v);
}
http_response_code($this->statusCode);
echo $this->body;
exit;
}
public function Redirect(string $url)
{
header('Location: '.$url, true, 301);
exit();
}
}
<?php
namespace Turnpike;
class Router
{
private $routes = array();
private $middleware = array();
public function Route(string $pattern, $callback)
{
$this->routes[$pattern] = $callback;
}
public function RouteMethod(string $pattern, $instance, string $method)
{
$this->routes[$pattern] = [$instance, $method];
}
public function Run(callable $middleware)
{
array_push($this->middleware, $middleware);
}
public function Execute(callable $notFoundHandler = null)
{
$request = new Request;
$response = new Response;
$notFound = true;
foreach ($this->middleware as $k => $m) {
if (is_callable($m)) {
call_user_func_array($m, array($request, $response));
}
}
foreach ($this->routes as $pattern => $action) {
if (is_callable($action) || is_array($action)) {
if (preg_match($pattern, $request->getUri(), $params)) {
$notFound = false;
call_user_func_array($action, array_merge(array($request, $response), array_slice($params, 1)));
}
}
}
if ($notFound && is_callable($notFoundHandler)) {
$response->setStatusCode(404);
call_user_func_array($notFoundHandler, array($request, $response));
}
$response->execute();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment