Skip to content

Instantly share code, notes, and snippets.

@kzap
Created October 20, 2012 01:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kzap/3921631 to your computer and use it in GitHub Desktop.
Save kzap/3921631 to your computer and use it in GitHub Desktop.
klein.php controller#action helper function
<?php
function addControllerMap($controllerMapCollection, $method = array('GET', 'POST'), $route = '*', $controllerMap = null) {
global $__controllerMaps;
// parse arguments
$args = func_get_args();
switch (count($args)) {
case 1:
$controllerMap = $controllerMapCollection;
$controllerMapCollection = $method = $route = null;
break;
case 2:
$controllerMap = $method;
$route = $controllerMapCollection;
$controllerMapCollection = $method = null;
break;
case 3:
$controllerMap = $route;
$route = $method;
$method = $controllerMapCollection;
$controllerMapCollection = null;
break;
case 4:
default:
break;
}
// parse $controllerMap
if (is_array($controllerMap)) {
if (isset($controllerMap['controller'])) {}
elseif (isset($controllerMap['c'])) { $controllerMap['controller'] = $controllerMap['c']; unset($controllerMap['c']); }
} elseif (is_string($controllerMap)) {
$tempControllerMap = explode('#', $controllerMap);
$controllerMap = array();
if (isset($tempControllerMap[0])) { $controllerMap['controller'] = $tempControllerMap[0]; }
if (isset($tempControllerMap[1])) { $controllerMap['action'] = $tempControllerMap[1]; }
}
// if has collection
if (!empty($controllerMapCollection)) {
foreach($controllerMapCollection as $collection) {
if (!is_array($collection)) { continue; }
// set subVars
$subMethod = $method;
$subRoute = $route;
$subControllerMap = $collection[count($collection)-1];
switch (count($collection)) {
case 2:
$subRoute .= $collection[0];
break;
case 3:
$subRoute .= $collection[1];
$subMethod = $collection[0];
break;
}
// parse $controllerMap
if (is_array($subControllerMap)) {
if (isset($subControllerMap['controller'])) {}
elseif (isset($subControllerMap['c'])) { $subControllerMap['controller'] = $subControllerMap['c']; unset($subControllerMap['c']); }
} elseif (is_string($subControllerMap)) {
$tempSubControllerMap = explode('#', $subControllerMap);
$subControllerMap = array();
if (isset($tempSubControllerMap[0])) { $subControllerMap['controller'] = $tempSubControllerMap[0]; }
if (isset($tempSubControllerMap[1])) { $subControllerMap['action'] = $tempSubControllerMap[1]; }
}
// attach default controller and action
$subControllerMap = array_merge((array) $controllerMap, (array) $subControllerMap);
addControllerMap($subMethod, $subRoute, $subControllerMap);
}
} else {
$controllerCallback = function($request, $response, $app) use ($controllerMap) {
//DEFAULTS
$controllerPath = '/controllers/';
$controllerFileExt = '.php';
$controllerSuffix = 'Controller';
$actionSuffix = 'Action';
$defaultController = 'index';
$defaultAction = 'index';
$controller = trim($controllerMap['controller']);
$action = trim($controllerMap['action']);
if (!$controller) { $controller = $defaultController; }
if (!$action) { $action = $defaultAction; }
$context = new stdClass();
$context->_request = $request;
$context->_response = $response;
$context->_app = $app;
$args = array();
foreach($request->params() as $key => $val) {
if (is_int($key) && $key > 0) { $args[] = $val; }
}
if( '' === $controller )
throw new classNotSpecifiedException('Class Name not specified');
if( '' === $action )
throw new methodNotSpecifiedException('Method Name not specified');
//Because the class could have been matched as a dynamic element,
// it would mean that the value in $class is untrusted. Therefore,
// it may only contain alphanumeric characters. Anything not matching
// the regexp is considered potentially harmful.
$controller = str_replace('\\', '', $controller);
preg_match('/^[a-zA-Z0-9_]+$/', $controller, $matches);
if( count($matches) !== 1 )
throw new badClassNameException('Disallowed characters in class name ' . $controller);
//Apply the suffix
$file_name = $controllerPath . $controller . $controllerSuffix . $controllerFileExt;
$class = $controller . $controllerSuffix;
$method = $action . $actionSuffix;
//At this point, we are relatively assured that the file name is safe
// to check for it's existence and require in.
if (FALSE === file_exists($file_name)) {
throw new classFileNotFoundException('Class file not found');
} else {
require_once($controllerPath . 'baseController.php');
require_once($file_name);
}
//Check for the class class
if( FALSE === class_exists($class) )
throw new classNameNotFoundException('class not found ' . $class);
//Check for the method
if( FALSE === method_exists($class, $method))
throw new classMethodNotFoundException('method not found ' . $method);
$obj = new $class($context);
return call_user_func_array(array($obj, $method), $args);
};
// no collection so do record
respond($method, $route, $controllerCallback);
}
}
/* Examples
* Can use an array to specify sub routes using a single controller
*
* Example #1:
addControllerMap(
array(), # Optional: an array of sub controller maps using the options below: array(METHOD, PATH, CONTROLLER#ACTION)
array('GET', 'POST'), # Optional: array of HTTP methods, can be a string for 1 method only: 'GET'
'/?', # Optional: the path for this route is / or no / , the index path basically
'index#index' # Required: the default controller and action default, will call indexController->indexAction() , can also be an array: array('controller' => 'index', 'action' => 'action') or array('c' => 'index', 'a' => 'action')
);
* Example #2:
addControllerMap(
array(
array('/?', ''), # GET /path/ => controllerNameController->defaultActionAction()
array(array('GET', 'POST'), '/register/[:action]?', 'members#register'), # GET|POST /path/register/actionName/ => membersController->registerAction() with 'action' param set to 'actionName'
array('/forgot-password/?', 'members#forgot_password'), # GET /path/forgot-password/ => membersController->forgot_passwordAction()
array(array('GET', 'POST'), '/login/?', 'members#login'), # GET|POST /path/login/ => membersController->loginAction()
),
array('GET'), # the default methods for this route and sub routes
'/path', # the base path for this route
'controllerName#defaultAction' # set default Controller Name (controllerName) and Default Action Name (defaultAction)
);
* Example #3:
* /test/ => testController()->indexAction()
* no action was specified, so uses Default Action Name (index)
addControllerMap(
'/test/',
array('c' => 'test'),
);
* Example #4:
* / => indexController()->indexAction()
* no controller/action was specified, so uses Default Controller Name (index) and Default Action Name (index)
addControllerMap(
'/',
'',
);
*/
<?php
# Extend your controllers using this base class
class baseController {
public function __construct($context) {
foreach ($context as $key => $value) {
$this->$key = $value;
}
}
protected function indexAction() {
echo 'This is the default action';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment