Last active
August 29, 2015 14:02
-
-
Save feifanzhou/d9876e3f8ecce13b19ed to your computer and use it in GitHub Desktop.
RESTful routing with PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$bn = basename($_SERVER['SCRIPT_NAME'], '.php'); | |
$p = explode('_', $bn); | |
$model_name = substr($p[0], 0, -1); | |
$model_path = "../models/$model_name.php"; | |
include_once($model_path); | |
include_once('../../config/routes.php'); | |
$controller_name = $p[0]; | |
function loadRESTfulView($controllerName, $action, $_options) { | |
$path = "../views/$controllerName/$action.php"; | |
$options = $_options; | |
include($path); | |
} | |
function autoload($class_name) { | |
include_once ('../models/' . lcfirst($class_name) . '.php'); | |
} | |
spl_autoload_register('autoload'); | |
$view_dir = "../views/$model_name"; | |
// ************************ INTERESTING STUFF STARTS HERE ************************ // | |
// Adapted from Rails RESTful routing | |
// http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions | |
// Get current page URL | |
$current_path = $_SERVER["REQUEST_URI"]; | |
// Split current path into components | |
$p = explode('/', $current_path); | |
array_walk($p, function(&$o) { // For each component | |
// Strip out GET parameters — the stuff after the question mark in a URL like on Google | |
$l = strpos($o, '?'); // Get position of question mark | |
if ($l) // If there is a question mark | |
$o = substr($o, 0, $l); // Get part of URL before question mark | |
}); | |
// Ignore the domain — just want the path (part of URL after domain) | |
$current_path = $p[1]; | |
// Create a variable to hold the controller action | |
$action = ''; | |
// Create a variable to hold the id (define -1 to be error) | |
$id = -1; | |
// Server should return HTML (unless JSON is specified in URL) | |
$type = 'html'; | |
if (isset($p[2])) { // If there is a second component to the path — only for certain routes | |
$t = explode('.', $p[2]); // Second part may include a dot-extension, like .json or .html | |
$id = intval($t[0]); // Get integer value of stuff before the dot, or the whole component if no dot | |
if (isset($t[1])) // If there is a type | |
$type = $t[1]; // Set the variable for the type | |
} | |
if ($id > -1) // If there is an ID | |
$current_path = $current_path . '/' . $id; // Start to build up the path again, after breaking it apart | |
// Slug is being ignored here | |
// Slug is an optional name after the ID that makes the URL more readable | |
// Look at StackOverflow URLs — they include the question as part of the URL | |
// But the URLs still work without all that stuff | |
// Better for SEO, but not necessary, so we ignore any slug here | |
if (preg_match("/^[a-zA-Z]+s$/", $current_path)) { // Match URL with only one component, ending in 's' | |
// Ending in 's' because this part of a route should be plural | |
// Note that this doesn't work for really weird plurals (that don't end in 's') | |
if ($_SERVER['REQUEST_METHOD'] == 'GET') | |
$action = 'index'; | |
else if ($_SERVER['REQUEST_METHOD'] == 'POST') | |
$action = 'create'; | |
} | |
else if (preg_match("/^[a-zA-Z]+\/new$/", $current_path)) { // Match URL with one component and another that says 'new' | |
$action = 'new'; | |
} | |
else if ($id > -1) { // If there is an ID | |
if ($_SERVER['REQUEST_METHOD'] == 'GET') | |
$action = 'show'; | |
else if ($_SERVER['REQUEST_METHOD'] == 'PUT') | |
$action = 'update'; | |
else if ($_SERVER['REQUEST_METHOD'] == 'DELETE') | |
$action = 'destroy'; | |
} | |
else if ($id > -1 && isset($p[3]) && $p[3] == 'edit') { // If there is an ID and URL has 'edit' | |
if ($_SERVER['REQUEST_METHOD'] == 'GET') | |
$action = 'edit'; | |
} | |
// At this point, if the URL matches correctly, $action is set to a method name | |
// 'index', 'new', 'create', 'show', 'edit', 'update', or 'destroy' | |
// Otherwise (if the URL doesn't match anything), $action is blank | |
if ($type == 'json') | |
header('Content-type: application/json'); // Tell browser that response is in JSON format | |
if (strlen($action) == 0) { // Didn't match any RESTful route | |
// Have controller custom-handle request with everything that we know | |
handle_request($current_path, $_SERVER['REQUEST_METHOD'], array_merge($_GET, $_POST), $type); | |
} | |
else { | |
$params = array_merge($_GET, $_POST); | |
$params['action'] = $action; | |
$params['type'] = $type; | |
if ($id > -1) { | |
$params['id'] = $id; | |
$action($params); // Call method by name: http://php.net/manual/en/functions.variable-functions.php | |
} | |
else | |
$action($params); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Well-commented version, original file here:
https://github.com/feifanzhou/Pails/blob/master/app/controllers/ControllerBase.php