How to route requests in web applications?
Posted: Sun Jun 07, 2009 9:16 am
What is a good way to route requests in php applications?
I keep my code/modules nested in my applications.
I use something like:
and
router code:
all urls look like this: index.php?r=products/edit/attachments/add&product_id=123&attachment_id=456
urls are generated with code: <?php echo $route->url('edit', 'product_id='.$product->id);?>
All this has few problems and I feel that I need to change it.
For example when my current location is 'products/edit/pictures' , I can't use just $route->url('..') anymore. I need to add 'product_id' everywhere. $route->url('..', 'product_id='.$product->id);
Also if($action == 'edit')if($product_record){$action = $route->next();/*another level of action switch*/}else{header('');/*go back*/} isn't very good idea when 'products/edit/pictures' is a tiny popup window. This kind of nesting doesn't work well. 'products/edit/pictures' should control what happens when the product_id is invalid(close the popup window and redirect main window using javascript).
I thought about giving each request an unique id and puting them into a file based database or into an array.
What are your ideas?
I keep my code/modules nested in my applications.
I use something like:
Code: Select all
$route = new RequestRoute('admin.php', 'r', @$_GET['r']);
$action = $route->next(array('menu', 'contents', 'galleries'));
if($action == 'menu') {
require('admin/modules/menu.php');
} elseif($action == 'contents') {
require('admin/modules/contents.php');
} elseif($action == 'galleries') {
require('admin/modules/galleries.php');
} else {
require('admin/modules/home.php');
}
Code: Select all
$action = $route->next();
if($action == 'insert') {
if(isset($_POST['save'])) {
//do some stuff
header('Location: '.$route->url('..'));
} else {
//insert form
}
} elseif($action == 'edit') {
$product_id = (int)@$_GET['product_id'];
if($product_record = $mysql->query('SELECT * FROM products WHERE id = "'.$product_id.'"')->fetch_assoc()) {
$action = $route->next();
if($action == 'pictures') {
//edit, insert, sort, delete
} elseif($action == 'details') {
//form, saving
} elseif($action == 'attachments') {
//form, saving
} else {
if(isset($_POST['save']) {
//save
} else {
//edit form
}
}
} else {
header('Location: '.$route->url('..'));
}
} elseif($action == 'sort_order_up') {
} elseif($action == 'sort_order_down') {
} elseif($action == 'delete') {
} else {
//list products
}
Code: Select all
class RequestRoute {
var $_script;
var $_key;
var $_route;
var $_pointer = 0;
function __construct($script, $key, $route) {
$this->_script = (string)$script;
$this->_key = (string)$key;
$route = (string)$route;
if(!empty($route)) $route = explode('/', $route);else $route = array();
$this->_route = array();
foreach($route as $level) {
if($level == '..') {
array_pop($this->_route);
} else {
array_push($this->_route, $level);
}
}
}
function next($actions = array()) {
if($this->_pointer < count($this->_route)) {
$action = $this->_route[$this->_pointer];
if(empty($actions) || in_array($action, $actions)) {
$this->_pointer++;
return $action;
}
}
}
function url($route = '', $params = '') {
$url = $this->_script;
$get = '';
$this_route = array();
for($i = 0;$i < $this->_pointer;$i++) {
array_push($this_route, $this->_route[$i]);
}
$route = (string)$route;
if(!empty($route)) $route = explode('/', $route);else $route = array();
foreach($route as $level) {
if($level == '..') {
array_pop($this_route);
} else {
array_push($this_route, $level);
}
}
$this_route = implode('/', $this_route);
if(!empty($this_route)) $get .= $this->_key.'='.$this_route;
$params = (string)$params;
if(!empty($params)) {
if(!empty($get)) $get .= '&'.$params;
else $get .= $params;
}
if(!empty($get)) $url .= '?'.$get;
return $url;
}
}
urls are generated with code: <?php echo $route->url('edit', 'product_id='.$product->id);?>
All this has few problems and I feel that I need to change it.
For example when my current location is 'products/edit/pictures' , I can't use just $route->url('..') anymore. I need to add 'product_id' everywhere. $route->url('..', 'product_id='.$product->id);
Also if($action == 'edit')if($product_record){$action = $route->next();/*another level of action switch*/}else{header('');/*go back*/} isn't very good idea when 'products/edit/pictures' is a tiny popup window. This kind of nesting doesn't work well. 'products/edit/pictures' should control what happens when the product_id is invalid(close the popup window and redirect main window using javascript).
I thought about giving each request an unique id and puting them into a file based database or into an array.
What are your ideas?