Skip to content

Instantly share code, notes, and snippets.

@feifanzhou
Last active August 29, 2015 14:02
Show Gist options
  • Save feifanzhou/d9876e3f8ecce13b19ed to your computer and use it in GitHub Desktop.
Save feifanzhou/d9876e3f8ecce13b19ed to your computer and use it in GitHub Desktop.
RESTful routing with PHP
<?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);
}
?>
@feifanzhou
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment