summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--system/core/Router.php44
-rw-r--r--user_guide_src/source/changelog.rst1
-rw-r--r--user_guide_src/source/general/routing.rst11
3 files changed, 53 insertions, 3 deletions
diff --git a/system/core/Router.php b/system/core/Router.php
index a5e29f1a3..529cbb7c8 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -371,10 +371,48 @@ class CI_Router {
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
- if (preg_match('#^'.$key.'$#', $uri))
+ if (preg_match('#^'.$key.'$#', $uri, $matches))
{
- // Do we have a back-reference?
- if (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
+ // Are we using callbacks to process back-references?
+ if ( ! is_string($val) && is_callable($val))
+ {
+ // Remove the original string from the matches array.
+ array_shift($matches);
+
+ // Get the match count.
+ $match_count = count($matches);
+
+ // Determine how many parameters the callback has.
+ $reflection = new ReflectionFunction($val);
+ $param_count = $reflection->getNumberOfParameters();
+
+ // Are there more parameters than matches?
+ if ($param_count > $match_count)
+ {
+ // Any params without matches will be set to an empty string.
+ $matches = array_merge($matches, array_fill($match_count, $param_count - $match_count, ''));
+
+ $match_count = $param_count;
+ }
+
+ // Get the parameters so we can use their default values.
+ $params = $reflection->getParameters();
+
+ for ($m = 0; $m < $match_count; $m++)
+ {
+ // Is the match empty and does a default value exist?
+ if (empty($matches[$m]) && $params[$m]->isDefaultValueAvailable())
+ {
+ // Substitute the empty match for the default value.
+ $matches[$m] = $params[$m]->getDefaultValue();
+ }
+ }
+
+ // Execute the callback using the values in matches as its parameters.
+ $val = call_user_func_array($val, $matches);
+ }
+ // Are we using the default routing method for back-references?
+ elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 4fda2903a..2df8ca7c1 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -269,6 +269,7 @@ Release Date: Not Released
- Added method ``strip_image_tags()``.
- Added ``$config['csrf_regeneration']``, which makes token regeneration optional.
- Added ``$config['csrf_exclude_uris']``, which allows you list URIs which will not have the CSRF validation methods run.
+ - Added possibility to route requests using callbacks.
Bug fixes for 3.0
------------------
diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst
index a6332c90c..43c181669 100644
--- a/user_guide_src/source/general/routing.rst
+++ b/user_guide_src/source/general/routing.rst
@@ -131,6 +131,17 @@ might be a good starting point.
..note:: You can also mix and match wildcards with regular expressions.
+Callbacks
+=========
+
+If you are using PHP >= 5.3 you can use callbacks in place of the normal routing
+rules to process the back-references. Example::
+
+ $route['products/([a-z]+)/edit/(\d+)'] = function ($product_type, $id)
+ {
+ return "catalog/product_edit/" . strtolower($product_type) . "/" . $id;
+ };
+
Reserved Routes
===============