Improved Routes

The addition of Packages in CodeIgniter 2.x branch was a welcome improvement, but did not go far enough. It only allowed for shared code, not Routing support. True support of modules is necessary to help developers with code sharing and to help build up the community once again. In addition, CodeIgniter's Router is showing it's age against the powerful solutions found in other PHP frameworks like Laravel. Bonfire's Routing is meant to help bring CodeIgniter into the modern age, or at least help it take a step in that direction.

CodeIgniter Mods

This is one area where we have decided that modifying the core of CodeIgniter is allowed. We've completely overridden the core Loader and Router classes with our own strange combination of WireDesignz' HMVC code and jenssegers' HMVC code and tweaked it to allow loading core files from the bonfire folder and more.

Route Library

The Route library is the core of the new flexibility. It is inspired by Jamie Rumbelow's excellent Pigeon class, as well as Laravel's routing system.

HTTP Verb Routing

To make building REST-based routing simpler and more consistent, you can use the

Route::resources('controller_name');

This function will automatically create RESTful resources for the common HTTP verbs. In this example, controller_name is the name of the controller you want to map the resources to. If you controller is named photos, you would call it like:

Route::resources('photos');

If the photos controller is part of the Gallery module, then you would route it like:

Route::resources('gallery/photos');

This would map the resources to the Photos controller, like:

HTTP Verb Path action used_for
GET /photos index display a list of photos
GET /photos/new create_new return an HTML form for creating a new photo
POST /photos create create a new photo
GET /photos/{id} show display a specific photo
GET /photos/{id}/edit edit return the HTML for editing a single photo
PUT /photos/{id} update update a specific photo
DELETE /photos/{id} destroy delete a specific photo

You can also set a single verb-based routes with any of the route methods:

Route::get('from', 'to');
Route::post('from', 'to');
Route::put('from', 'to');
Route::delete('from', 'to');
Route::head('from', 'to');
Route::patch('from', 'to');
Route::options('from', 'to');

These routes will then only be available when the corresponding HTTP verb is used to initiate the call.

Customizing Resourceful Routes

While the standard naming convention provided by the resources Route method will often serve you well, you may find that you need to customize the route to easily control where your URL's route to.

Specifying a controller to use

You can pass an array of options into the resources method as the second parameter. By specifying a controller key, you will tell the router to replace all instances of the original route with the defined controller, like:

Route::resources('photos', array('controller' => 'images'));

Will recognize incoming paths beginning with /photos but will route to the images controller:

Specifying the module to use

You can also specify a module to use in the options array by passing a module key. This is helpful when the module and controller share different names.

Route::resources('photos', array('module' => 'gallery', 'controller' => 'images'));

Will recognize incoming paths beginning with /photos but will route to the gallery/images module and controller.

Constraining the {id} format

By default, the {id} used in the routing allows any letter, lower- or upper-case, any digit (0-9), a dash (-) and an underscore(_). If you need to restrict the {id} to another format, you may use the constraint option to pass a new, valid, format string:

Route::resources('photos', array('constraint' => '(:num)'));

Would restrict the {id} to be only numerals, while:

Route:resources('photos', array('constraint' => '([A-Z][A-Z][0-9]+)'));

would restrict the {id} to be something like RR27.

Offsetting Parameters

By default, the resulting parameters in the $to portion of the route will start at $1. In most cases this is what you want. However, there may be times where you need to change that and offset the value in some form or another. This is most often see when dealing with an API version number in the URL that you're fixing manually later in the routes config file, or when taking out a language string from the URL. In these cases, you would be removing $1 from the routes and would need the parameters to start at $2 instead. You can do this by passing 'offset' in the options array with a value matching the number you need to offset.

Route::resources('photos', array('offset' => 1));

Blocking Routes

You might find times where you need to block access to one or more routes. For example, you might have relocated the default user login page so that script-kiddies couldn't find your page by assuming it's a Bonfire site and would be at a normal location. In this case, you would want to block any access to /users/login, which would normally work just fine. In this case you can use the block() method to block as many routes as you'd like.

Route::block('users/login', 'photos/(:num)');

// The same as:
$route['users/login']    = '';
$route['photos/(:num)']  = '';

Route Prefixing

There are times when you'll want to group a disparate set of routes under a single section. You can use route prefixing for this.

Route::prefix('api', function() {
    Route::all('users', 'users/index');
    Route::get('photos', 'photos/show');
});

Would be equivalent to the following routes:

$route['api/users'] = 'users/index';
$route['api/photos'] = 'photos/show';

Named Routes

You can save routes with a name associated with them that makes it much easier and safer to call routes within your application. The provides a single name that you can always count on being the same that maps to the $from portion of the route. If you need to restructure your site, simply change the routing while keeping the name the same. Any place in your application that called that route will still work. This works with prefixing and all of the other flexbile routing the class provides.

Route::prefix('area', function(){
    Route::any('posts', 'posts/index', array('as' => 'blog'));
});

redirect( Route::named('blog') );

Routing Contexts

Contexts provide a way for modules to assign controllers to an area of the site based on the name of the controller. This can be used for making a /developer area of the site that all modules can create functionality into.

This can be better explained with an example. We want to provide a collection of tools available under the /developer URL of our site. We have a number of modules, like a database manager, a code builder, etc, that all need to have easy access to that area. Instead of creating routes for each module, we'll just create a general set of routes that will take any controller named 'developer.php' in any of our modules, and route it to developer/{module_name}/{method}.

Route::context('developer');

If, we change our mind down the road and want to rename all of the URL's to /tools instead of /developer, we can do that by passing in two parameters instead. The first is the name of route (tools in this case), and the second is the controller to map to.

Route::context('tools', 'developer');

This creates a series of routes that map the parameters into the module. It's a little hacky but works well for up to 5 parameters. If you need more than that, you might examine your application to see if you could use the routes differently or restructure your application. The equivalent CI routes would be:

$route['tools/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)']   = '$1/developer/$2/$3/$4/$5/$6';
$route['tools/(:any)/(:any)/(:any)/(:any)/(:any)']          = '$1/developer/$2/$3/$4/$5';
$route['tools/(:any)/(:any)/(:any)/(:any)']                 = '$1/developer/$2/$3/$4';
$route['tools/(:any)/(:any)/(:any)']                        = '$1/developer/$2/$3';
$route['tools/(:any)/(:any)']                               = '$1/developer/$2';
$route['tools/(:any)']                                      = '$1/developer';

If you need to offset your parameter numbers for the above routes, you can pass on 'offset' key/value in your options array as the last parameter.

Context Homes

You can also have it create a 'home' controller that would handle the calls to '/developer' all by itself. This will map to a controller outside of any modules, but in your application/controllers folder, under a new folder named after the context. The controller can be any name you wish, but can be made to match the name of the default_controller by using a {default_controller} tag.

Route::context('developer', array('home' => 'some_controller'));
// Creates...
$route['developer'] = 'developer/some_controller';
// Maps to...
application/controllers/developer/some_controller.php

Route::context('developer', array('home' => '{default_controller}'));
// Creates
$route['developer'] = 'developer/welcome';
// Maps to
application/controllers/developer/welcome.php
Profiler
Profiler Console 0 Load Time 13.5ms Memory Used 1.07 MB Database 4 Queries vars & Config Files 87

Console

Memory Usage

Benchmarks

1 ms Loading Time: Base Classes
10 ms Controller Execution Time ( Docs / Index )
14 ms Total Execution Time

Queries

0.0002 SELECT GET_LOCK('669d96c08781a4ea53ffb96426a5ce42d5896eb1', 300) AS ci_session_lockSpeed: 0.0002 - Possible keys: - Key Used: - Type: - Rows: - Extra: No tables used
0.0003 SELECT `data` FROM `bf_ci3_sessions` WHERE `id` = '669d96c08781a4ea53ffb96426a5ce42d5896eb1'Speed: 0.0003 - Possible keys: - Key Used: - Type: - Rows: - Extra: no matching row IN const table
0.0003 SHOW TABLES FROM `remytek`
0.0003 SELECT * FROM `bf_settings`Speed: 0.0003 - Possible keys: - Key Used: - Type: ALL - Rows: 37 - Extra:
0.0010 Total Query Execution Time

Session User Data

__ci_last_regenerate 1532013459
requested_page http://remytek.com/index.php/docs/developer/routes
previous_page http://remytek.com/index.php/docs/developer/routes

GET DATA

No GET data exists

POST DATA

No POST data exists

URI STRING

docs/developer/routes

CLASS/METHOD

docs/index

HTTP HEADERS

HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_USER_AGENT CCBot/2.0 (http://commoncrawl.org/faq/)
HTTP_CONNECTION close
SERVER_PORT 80
SERVER_NAME remytek.com
REMOTE_ADDR 54.225.32.164
SERVER_SOFTWARE Apache/2.4.18 (Ubuntu)
HTTP_ACCEPT_LANGUAGE
SCRIPT_NAME /index.php
REQUEST_METHOD GET
HTTP_HOST
REMOTE_HOST
CONTENT_TYPE
SERVER_PROTOCOL HTTP/1.1
QUERY_STRING
HTTP_ACCEPT_ENCODING x-gzip, gzip, deflate
HTTP_X_FORWARDED_FOR

CONFIG VARIABLES

base_url http://remytek.com/
index_page index.php
uri_protocol AUTO
url_suffix
language english
charset UTF-8
enable_hooks true
subclass_prefix MY_
composer_autoload false
permitted_uri_chars a-z 0-9~%.:_-
allow_get_array true
enable_query_strings false
controller_trigger c
function_trigger m
directory_trigger d
log_threshold 0
log_path /var/www/clients/client2/web2/bonfire/application/logs/
log_file_extension
log_file_permissions 420
log_date_format Y-m-d H:i:s
error_views_path
cache_path /var/www/clients/client2/web2/bonfire/application/cache/
cache_query_string false
encryption_key a9ff89765e5fc8a4ee203140cfff9400
sess_cookie_name bf_session
sess_expiration 7200
sess_time_to_update 300
sess_match_ip false
sess_expire_on_close false
sess_encrypt_cookie false
sess_use_database false
sess_table_name sessions
sess_match_useragent true
sess_driver database
sess_regenerate_destroy false
sess_save_path ci3_sessions
cookie_prefix
cookie_domain
cookie_path /
cookie_secure false
cookie_httponly false
standardize_newlines false
global_xss_filtering false
csrf_protection true
csrf_token_name ci_csrf_token
csrf_cookie_name ci_csrf_token
csrf_expire 7200
csrf_regenerate true
csrf_exclude_uris Array ( )
compress_output false
time_reference utc
rewrite_short_tags false
proxy_ips
bonfire.installed 1
site.default_user_timezone UM8
modules_locations Array ( [/var/www/clients/client2/web2/bonfire/application/modules/] => ../../application/modules/ [/var/www/clients/client2/web2/bonfire/bonfire/modules/] => ../../bonfire/modules/ )
site.backup_folder archives/
contexts Array ( [0] => content [1] => reports [2] => settings [3] => developer )
enable_activity_logging true
sparks_path ../sparks/
template.site_path /var/www/clients/client2/web2/web/
template.theme_paths Array ( [0] => themes )
template.default_layout index
template.ajax_layout ajax
template.use_mobile_themes false
template.default_theme default/
template.admin_theme admin
template.message_template <div class="alert alert-{type} alert-dismissable"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <div>{message}</div> </div>
template.breadcrumb_symbol :
template.parse_views false
assets.directories Array ( [base] => assets [cache] => cache [css] => css [image] => images [js] => js [module] => module )
assets.js_opener $(document).ready(function() {
assets.js_closer });
assets.css_combine false
assets.js_combine false
assets.css_minify true
assets.js_minify true
assets.encrypt_name false
assets.encode false
assets.base_folder assets
assets.asset_folders Array ( [css] => css [js] => js [image] => images )
ui.current_shortcuts Array ( [form_save] => Array ( [description] => Save any form in the admin area. [action] => $("input[name=save]").click();return false; ) [create_new] => Array ( [description] => Create a new record in the module. [action] => window.location.href=$("a#create_new").attr("href"); ) [select_all] => Array ( [description] => Select all records in an index page. [action] => $("table input[type=checkbox]").click();return false; ) [delete] => Array ( [description] => Delete the record(s). [action] => $("#delete-me.btn-danger").click(); ) [module_index] => Array ( [description] => Return to the index of the current module. [action] => window.location.href=$("a#list").attr("href"); ) [goto_content] => Array ( [description] => Jump to the Content context. [action] => window.location.href=$("#tb_content").attr("href") ) [goto_reports] => Array ( [description] => Jump to the Reports context. [action] => window.location.href=$("#tb_reports").attr("href") ) [goto_settings] => Array ( [description] => Jump to the Settings context. [action] => window.location.href=$("#tb_settings").attr("href") ) [goto_developer] => Array ( [description] => Jump to the Developer context. [action] => window.location.href=$("#tb_developer").attr("href") ) )
emailer.write_to_file false
migrate.auto_core false
migrate.auto_app false
commonmark.valid_drivers Array ( [0] => Parsedown [1] => Markdown [2] => MarkdownExtra [3] => LeagueCommonMark )
commonmark.driver MarkdownExtended
docs.theme docs
docs.default_group developer
docs.show_dev_docs true
docs.show_app_docs true
docs.toc_file _toc.ini
docs.permitted_environments Array ( [0] => development [1] => testing [2] => production )

Files

application.php
/var/www/clients/client2/web2/bonfire/application/config/application.php
autoload.php
/var/www/clients/client2/web2/bonfire/application/config/autoload.php
config.php
/var/www/clients/client2/web2/bonfire/application/config/config.php
constants.php
/var/www/clients/client2/web2/bonfire/application/config/constants.php
database.php
/var/www/clients/client2/web2/bonfire/application/config/database.php
events.php
/var/www/clients/client2/web2/bonfire/application/config/events.php
hooks.php
/var/www/clients/client2/web2/bonfire/application/config/hooks.php
mimes.php
/var/www/clients/client2/web2/bonfire/application/config/mimes.php
profiler.php
/var/www/clients/client2/web2/bonfire/application/config/profiler.php
routes.php
/var/www/clients/client2/web2/bonfire/application/config/routes.php
Base_Controller.php
/var/www/clients/client2/web2/bonfire/application/core/Base_Controller.php
MY_Model.php
/var/www/clients/client2/web2/bonfire/application/core/MY_Model.php
App_hooks.php
/var/www/clients/client2/web2/bonfire/application/hooks/App_hooks.php
application_lang.php
/var/www/clients/client2/web2/bonfire/application/language/english/application_lang.php
Profiler.php
/var/www/clients/client2/web2/bonfire/application/libraries/Profiler.php
Base.php
/var/www/clients/client2/web2/bonfire/application/third_party/MX/Base.php
Config.php
/var/www/clients/client2/web2/bonfire/application/third_party/MX/Config.php
Controller.php
/var/www/clients/client2/web2/bonfire/application/third_party/MX/Controller.php
Lang.php
/var/www/clients/client2/web2/bonfire/application/third_party/MX/Lang.php
Loader.php
/var/www/clients/client2/web2/bonfire/application/third_party/MX/Loader.php
Benchmark.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Benchmark.php
CodeIgniter.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/CodeIgniter.php
Common.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Common.php
Config.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Config.php
Controller.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Controller.php
Hooks.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Hooks.php
Input.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Input.php
Lang.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Lang.php
Loader.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Loader.php
Log.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Log.php
Model.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Model.php
Output.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Output.php
Router.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Router.php
Security.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Security.php
URI.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/URI.php
Utf8.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/Utf8.php
hash.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/compat/hash.php
mbstring.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/compat/mbstring.php
password.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/compat/password.php
standard.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/core/compat/standard.php
DB.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/DB.php
DB_driver.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/DB_driver.php
DB_query_builder.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/DB_query_builder.php
DB_result.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/DB_result.php
mysqli_driver.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/drivers/mysqli/mysqli_driver.php
mysqli_result.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/database/drivers/mysqli/mysqli_result.php
directory_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/helpers/directory_helper.php
form_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/helpers/form_helper.php
language_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/helpers/language_helper.php
url_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/helpers/url_helper.php
profiler_lang.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/language/english/profiler_lang.php
Cache.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Cache/Cache.php
Cache_dummy.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Cache/drivers/Cache_dummy.php
Driver.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Driver.php
Session.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Session/Session.php
Session_driver.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Session/Session_driver.php
Session_database_driver.php
/var/www/clients/client2/web2/bonfire/bonfire/ci3/libraries/Session/drivers/Session_database_driver.php
BF_Lang.php
/var/www/clients/client2/web2/bonfire/bonfire/core/BF_Lang.php
BF_Loader.php
/var/www/clients/client2/web2/bonfire/bonfire/core/BF_Loader.php
BF_Model.php
/var/www/clients/client2/web2/bonfire/bonfire/core/BF_Model.php
BF_Router.php
/var/www/clients/client2/web2/bonfire/bonfire/core/BF_Router.php
BF_Security.php
/var/www/clients/client2/web2/bonfire/bonfire/core/BF_Security.php
BF_directory_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/BF_directory_helper.php
BF_form_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/BF_form_helper.php
application_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/application_helper.php
config_file_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/config_file_helper.php
markdown_extended_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/markdown_extended_helper.php
markdown_helper.php
/var/www/clients/client2/web2/bonfire/bonfire/helpers/markdown_helper.php
Assets.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Assets.php
CommonMark.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/CommonMark.php
CommonMarkDriver.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/CommonMark/CommonMarkDriver.php
CommonMark_MarkdownExtended.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/CommonMark/drivers/CommonMark_MarkdownExtended.php
Console.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Console.php
Events.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Events.php
Modules.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Modules.php
Route.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Route.php
Template.php
/var/www/clients/client2/web2/bonfire/bonfire/libraries/Template.php
docs.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/config/docs.php
routes.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/config/routes.php
Docs.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/controllers/Docs.php
docs_lang.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/language/english/docs_lang.php
_sidebar.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/views/_sidebar.php
index.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/docs/views/index.php
Settings_lib.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/settings/libraries/Settings_lib.php
Settings_model.php
/var/www/clients/client2/web2/bonfire/bonfire/modules/settings/models/Settings_model.php
index.php
index.php
index.php
themes/docs/index.php