bcen / ci-dispatcher
A CodeIgniter plugin for more restful controller
Requires
- php: >=5.3.0
Requires (Dev)
- ellislab/codeigniter: 2.1.0
- phpunit/phpunit: 3.7.*
This package is not auto-updated.
Last update: 2020-01-24 16:42:50 UTC
README
Introduction
CodeIgniter-Dispatcher uses CodeIgniter's _remap function to do an extra routing to a class-based controller instead of function-based.
Example
CodeIgniter's function-based controller
<?php class Welcome extends CI_Controller { public function index() { $this->load->view('welcome_message'); } }
With CodeIgniter-Dispatcher's class-based controller
<?php class Index extends \Dispatcher\DispatchableController { protected $views = 'welcome_message'; }
Installtion
-
Download the
composer.phar
executable or use the installercurl -s http://getcomposer.org/installer | php
-
Add this to composer.json
{ "require": { "bcen/ci-dispatcher": "*" } }
-
Run composer
php composer.phar install
-
Include
autoload.php
in your project and add this toroutes.php
\Dispatcher\Common\BootstrapInstaller::run($route);
Dispatcher\BootstrapInstaller::run($route)
will create 3 files inside of CodeIgniter'sAPPPATH
, if you want to skip the file creation, addtrue
to to skip the file check.\Dispatcher\Common\BootstrapInstaller::run($route, true);
Features
Poor man's dependency injection
Middlewares, DispatchableController and DispatchableResource will be injected by default.
// config/dependencies.php $config['container']['userDao'] = function($container) { return new UserDao(); }; $config['container']['dsn'] = 'mydsn_string'; // sharedContainer will return the same instance throughout the request/response cycle $config['sharedContainer']['pdo'] = function($container) { return new PDO($container['dsn']); }; // user_status.php <?php class User_Status extends \Dispatcher\DispatchableController { // CI-Dispatcher will inject $userDao from config/dependencies.php // for you. public function __construct($userDao) { $userDao->findUserById(1); } }
Middlewares
<?php class DebugFilter { public function processRequest(Dispatcher\Http\HttpRequestInterface $req) { // do something } public function processResponse(Dispatcher\Http\HttpResponseInterface $res) { // do something } }
processRequest
and processResponse
are optional, middleware can implement either one or both
to alter the request/response cycle.
CodeIgniter Awareness
Any class that is created by the Dispatcher can implement CodeIgniterAware
to have CI
injection.
E.g.
<?php // Controller class User_Status extends \Dispatcher\DispatchableController implements \Dispatcher\Common\CodeIgniterAware { public function __construct($userDao) { $userDao->findUserById(1); } public function setCI($ci) { $this->CI = $ci; } } // Middleware class DebugFilter implements \Dispatcher\Common\CodeIgniterAware { public function processRequest(Dispatcher\Http\HttpRequestInterface $req) { $cipher = $this->CI->encrypt->encode('plaintext', 'key'); } public function processResponse(Dispatcher\Http\HttpResponseInterface $res) { // do something } public function setCI($ci) { $this->CI = $ci; } }
Configurations
There are two configuration files, config/dispatcher.php
and config/dependencies.php
.
dispatcher.php
<?php $config['middlewares'] = array( 'MyProject\\Namespace\\Middlewares\\SomeFilter', 'debug_filter' ); $config['debug'] = true;
debug
:
Whether to show or hide debug information.
Set true
to show exception, false
to return error 404 response when stuff gone wrong.
middlewares
:
An array of middleware class(es) to be processed before/after dispatch.
When specifying the middlewares, it can be a fully qualified class name if it is autoloaded, otherwise
the class must live under application/middlewares/
in order for CI-Dispatcher to load it (Note: naming convention applies).
dependencies.php
This configuration file is used for DIContainer
to load dependencies and inject them
into Middlewares, DispatchableController and DispatchableResource's constructor.
Note: DIContainer
is a copy cat of Pimple
.
<?php $config['container'] = array(); $config['sharedContainer'] = array(); $config['container']['dsnString'] = 'dsn:user@192.168.1.100'; $config['container']['userDao'] = function($c) { return new UserDao($c['dsnString']); };
Note:
container
can have anonymous function or simple value like string, array, etc...
sharedContainer
must contian only anonymous function.
Conventions
URL to Controller mappings
URL mapping convention follows almost excatly like CodeIgniter's default strategy.
E.g.
http://domain.com/
maps to application/controllers/index.php
with the class name Index
http://domain.com/about_me
maps to application/controllers/about_me.php
with the class name About_Me
Directory nesting:
http://domain.com/blog
and http://domain.com/blog/ajax/fetch_all_posts
can be mapped to:
controllers
|
+-- blog
|-- index.php
+-- ajax
|
+-- fetch_all_posts.php
Mapping strategy:
CI-Dispatcher will search through each URI segments for the exact file name under application/controllers
.
If it doesn't exists, it will search index.php
under that URI segments.
E.g.
http://domain.com/blog
has the URI segment: blog
.
First CI-Dispatcher will search for application/controllers/blog.php
.
If it doesn't exists, then it will try for application/controllers/blog/index.php
.
URI variable:
Sometime URI segments are not fixed, thus we cannot mapped to a directory or class. However, we can mapp it to the function arguments of the request handler.
E.g.
http://domain.com/blog/posts/this-is-a-crayz-blog-post-about-my-blog/
can be mapped to
application/controllers/blog/posts.php
with the follow class:
<?php class Posts extends \Dispatcher\DispatchableController { protected $views = array('header', 'post_body', 'footer'); // request handler for GET public function get($request, $slug) { $post = $posts->find($slug); return $this->renderView(array('post' => $post); } // request handler for POST // providing a default value means that that URI segment is optional. // e.g. POST http://domain.com/blog/posts/some-slug // or POST http://domain.com/blog/posts public function post($request, $slug = null) { // do something and return response } }
Note: The request handler must accept at least one argument for the Request
object.
Middlewares
If middlewares are not autoloaded by class loader like composer
, they must live under
application/middlewares
.
E.g.
$config['middlewares'] => array('debug_filter', 'auth_filter');
debug_filter
will be mapped to application/middlewares/debug_filter.php
with the class name Debug_Filter
.
auth_filter
will be mapped to application/middlewares/auth_filter.php
with the class name Auth_Filter
.
Controller Explained
Any class lives under application/controllers/
and extends Dispatcher\DispatchableController
will be created
and injected by the CI-Dispatcher
.
E.g.
Assumes we are sending a GET
request to http://domain.com/blog/posts/special-post
.
CI-Dispatcher
will map the URI toapplication/blog/posts.php
- Creates a new instance of
Posts
- Invokes the method
get
with arguments:Dispatcher\Http\HttpRequestInterface
and'special-post'
- After getting the response object from
get
, thenCI-Dispatcher
will run through all the middlewares to process the response - Finally, send it to browser by invoking
send
on theresponse
object
At minimal
<?php class Posts extends \Dispatcher\DispatchableController { protected $views = 'post_view'; }
By default, a GET
request handler is provided, when get
got invoked, it will load the views and data.
So when extending the DispatchableController
, you only need to provide where the view files are by
declaring $views = 'post_view'
or as an array $views = array('header', 'post_view', 'footer')
Overrides getContextData
to send data to the view layer:
<?php class Posts extends \Dispatcher\DispatchableController { protected $views = 'post_view'; public function getContextData($request) { $posts = array(); return array('posts' => $posts); } }
Overrides/implements get
, post
, delete
, put
and etc to take complete
control of the request/response handling.
<?php class Posts extends \Dispatcher\DispatchableController { protected $views = 'post_view'; public function get($request) { // returns a ViewTemplateResponse return $this->renderView(array('post' => $posts)); } }
Tests
$ composer.phar install --dev
$ vendor/bin/phpunit
License
CI-Dispatcher is released under the MIT public license.