Fork me on GitHub

Routing & Pretty URLs

Default Routing

Default routing is based on typical MVC structure in which URI corresponds to class/method.

        
            http://example.com/blog/list/param1/param2
        
    

In this example the request will be routed to public list method of blogController with param1 & param2 as method arguments. A sample controller would look something like this.

        
            namespace sampleSite\controller
            {
                use hathoora\controller\controller;

                /**
                 * Blog controller
                 */
                class blogController extends controller
                {
                    /**
                     * List action
                     */
                    public function list($param1, $param2, $param3 = null)
                    {
                        //
                    }
                }
            }
        
    

Default Controller

Index page or homepage of an application is routed to defaultController.

        
            http://example.com/
        
    

In this example the request will be routed to public index method of defaultController. A sample controller would look something like the following.

        
            namespace sampleSite\controller
            {
                use hathoora\controller\controller;

                /**
                 * Homepage controller
                 */
                class defaultController extends controller
                {
                    /**
                     * homepage action
                     */
                    public function index()
                    {
                        //
                    }
                }
            }
        
    

Default Action

If you don't specity an action for a controller, then public index method of that controller is called.

        
            http://example.com/blog/
        
    

In this example the request will be routed to public index method of blogController as shown below.

        
            namespace sampleSite\controller
            {
                use hathoora\controller\controller;

                /**
                 * Blog controller
                 */
                class blogController extends controller
                {
                    /**
                     * home action of blog
                     */
                    public function index()
                    {
                        //
                    }
                }
            }
        
    

Camel Case Action Names

Camel case method names are seperated by a dash (-). Consider the following URLs which are both pointing to the same action.

        
            http://example.com/blog/orderBy/name
            http://example.com/blog/order-by/name
        
    

In this example both requests will be routed to public orderBy method of blogController with name as method argument. The code would look like this.

        
            namespace sampleSite\controller
            {
                use hathoora\controller\controller;

                /**
                 * Blog controller
                 */
                class blogController extends controller
                {
                    /**
                     * home action of blog
                     */
                    public function orderBy($type = 'name')
                    {
                        //
                    }
                }
            }
        
    

Note About URI

In above examples routing was based on URI, the part after the domain.

However Hathoora PHP Frameworks allows you to change the domain identifier (using regex patterns) which would change the meaning of URI.

To iterate over this point consider the following application specific configuration.

        
            # File HATHOORA_ROOTPATH/boot/config/app.yml

            app:
                admin:
                    pattern: '^www.example.com/panel/admin(|/)'

                site:
                    pattern: '^www.example.com(|/)'
                    default: true # will be used as default
        
    

Now consider the following URLs to understand the concept and the controller to which they would be routed to:

  • http://www.example.com/blog/list will be handled by app/site/controller/blogController::list
  • http://www.example.com/panel/admin/list will be handled by app/admin/controller/listController::index

Advanced Routing

If default routing is not what you are looking for, then you have two more options for complex routing.

Custom Dispatcher

Custom dispatcher is a PHP class defined per application configuration. To enable it, you need to define dispatcher parameter in configuration as shown below.

        
            # File HATHOORA_ROOTPATH/boot/config/app.yml

            app:
                admin:
                    pattern: '^www.example.com/panel/admin(|/)'
                    # custom routing to be handled by this class
                    dispatcher:
                        class: appDispatcher
                        method: dispatch

                site:
                    pattern: '^www.example.com(|/)'
                    default: true # will be used as default
        
    

In this example requests for site would be handled normally, however requests for admin would be sent to app/admin/appDispatcher::dispatch which must return an array containing:

  • controller e.g. listController
  • action e.g. view
  • array of params e.g. ['title', 'id']

To see advanced routing in action, consider the following sample code:

        
            # File app/admin/appDispatcher

            namespace admin
            {
                /**
                 * Custom request dispatcher
                 */
                class appDispatcher
                {
                    /**
                     * Custom dispatcher for route request
                     *
                     * This function returns array containing:
                     *      - controller class name
                     *      - action name
                     *      - array of params
                     */
                    public function dispatch(\hathoora\container $container)
                    {
                        $arrDispatch = null;

                        $request = $container->getRequest();
                        $routeRequest = $container->getRouteRequest();
                        $uri = $request->serverParam('REQUEST_URI');

                        // URL: /panel/admin/list/12
                        if (preg_match('~admin/list/(\d+)~i', $uri, $arrMatches)
                        {
                            $arrDispatch = array(
                                'controller' => 'listController',
                                'action' => 'view',
                                'params' => array(array_pop($arrMatches));
                        }
                        else
                        {
                            // following is the same as default routing
                            $arrUriParts = explode('/', $uri);
                            array_shift($arrUriParts);
                            $firstPart = array_shift($arrUriParts);

                            $arrDispatch = array(
                                'controller' => 'questionsController',
                                'action' => $firstPart,
                                'params' => $arrUriParts);
                        }

                        return $arrDispatch;
                    }
                }
            }
        
    

Apache (or other web servers) Rewrites

You can also use Apache rewrite for routing URLs. You would need to set the following params in Apache:

  • REDIRECT_HTRO
  • REDIRECT_HTRO_CONTROLLER
  • REDIRECT_HTRO_ACTION
  • REDIRECT_HTRO_PARAMS

The following example routes a URL http://mysite.com/posts/1-hello-world to postsController::view($id, $slug).

        
            # File: docroot/.htaccess

            RewriteEngine On

            # Fancy URL for viewing a post on domains
            RewriteCond %{HTTP_HOST} ^mysite.com [NC]
            RewriteCond %{REQUEST_URI} ((.+?)|)/posts/(\d+)(-\/?(.+?))$ [NC]
            RewriteRule .* index.php  [E=HTRO:1,E=HTRO_CONTROLLER:postsController,E=HTRO_ACTION:view,E=HTRO_PARAMS[0]:%3,E=HTRO_PARAMS[1]:%5,E=HTRO_PARAMS[2]:%2,L,QSA]
        
    

At this moment, it is not possible to set appname using this method.

Page Took:         5.21 msec
Page Memory:   534.08k
docs / viewController / view (200)
Request UUID: 59e9070cad48a8.12002793
Get
Post
Cookies
Files
Session
Server
Response
No data.
No data.
No data.
No data.
No data.
REDIRECT_HATHOORA_ENV
prod
REDIRECT_STATUS
200
HATHOORA_ENV
prod
HTTP_HOST
www.hathoora.org
HTTP_X_FORWARDED_FOR
54.198.143.210
HTTP_X_REAL_IP
54.198.143.210
HTTP_CONNECTION
close
HTTP_ACCEPT_ENCODING
x-gzip, gzip, deflate
HTTP_USER_AGENT
CCBot/2.0 (http://commoncrawl.org/faq/)
HTTP_ACCEPT
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_IF_MODIFIED_SINCE
Wed, 23 Aug 2017 00:38:22 GMT
PATH
/sbin:/usr/sbin:/bin:/usr/bin
SERVER_SIGNATURE
Apache/2.2.15 (CentOS) Server at www.hathoora.org Port 80
SERVER_SOFTWARE
Apache/2.2.15 (CentOS)
SERVER_NAME
www.hathoora.org
SERVER_ADDR
192.168.1.11
SERVER_PORT
80
REMOTE_ADDR
207.126.164.119
DOCUMENT_ROOT
/var/websites/hathoora.org/docroot
SERVER_ADMIN
webmaster@hathoora.org
SCRIPT_FILENAME
/var/websites/hathoora.org/docroot/index.php
REMOTE_PORT
34458
REDIRECT_URL
/docs/v1/routing
GATEWAY_INTERFACE
CGI/1.1
SERVER_PROTOCOL
HTTP/1.0
REQUEST_METHOD
GET
QUERY_STRING
REQUEST_URI
/docs/v1/routing
SCRIPT_NAME
/index.php
PHP_SELF
/index.php
REQUEST_TIME_FLOAT
1508443916.709
REQUEST_TIME
1508443916
Status: 200
Headers:
Content-Type
text/html; charset=UTF-8
Configutation
Key Value
app.admin
Array
(
    [pattern] => /admin(|/)
    [directory] => hathoora
    [namespace] => hathoora\admin
)
app.docs
Array
(
    [pattern] => /docs(|/)
    [directory] => hathoora
    [dispatcher] => Array
        (
            [class] => customDispatcher
            [method] => dispatch
        )

)
app.site
Array
(
    [default] => 1
)
hathoora.logger
Array
(
    [profiling] => Array
        (
            [enabled] => 1
        )

    [logging] => Array
        (
            [enabled] => 1
            [level] => DEBUG
        )

    [webprofiler] => Array
        (
            [enabled] => 1
            [system] => 
            [show_redirects] => 
        )

)
hathoora.template
Array
(
    [engine] => Array
        (
            [name] => Stuob
        )

)
hathoora.database
Array
(
    [default] => mysql://dbuser:dbpassword@dbhost:3306/dbname
)
services.container
Array
(
    [class] => \hathoora\container
    [method] => getContainer
)
Logging (14)
hathoora.logger.logging.enabled: 1
# Time (msec) Level Memory (KB) Message
1 2.364 DEBUG 309.77 Configuration loaded:
Array
(
    [0] => app_prod.yml
    [1] => config_prod.yml
)
2 2.657 DEBUG 323.38 Listener "kernel.terminate[webprofiler]" has been added because of hathoora.logger.webprofiler.enabled
3 2.809 DEBUG 326.77 Event kernel.ready has been registered.
4 3.016 DEBUG 335.13 Calling App dispatcher (Array ( [class] => customDispatcher [method] => dispatch ) )...
5 3.174 DEBUG 349.55 Event kernel.route has been registered.
6 3.441 DEBUG 378.91 Event kernel.controller has been registered.
7 3.492 DEBUG 379.85 Calling controller (\docs\controller\viewController::view) with following params
Array
(
    [0] => v1
    [1] => routing
)
8 4.080 INFO 467.20 Template (docs/v1/routing.tpl.php) loaded
9 4.262 INFO 495.12 Template (/var/websites/hathoora.org/app/hathoora/docs//resources/templates/components/htmlMeta.tpl.php) loaded
10 4.385 INFO 496.37 Template (/var/websites/hathoora.org/app/hathoora/docs//resources/templates/components/flashMessages.tpl.php) loaded
11 5.039 INFO 444.71 Template (docs.tpl.php) fetched.
12 5.065 DEBUG 444.30 Event kernel.response has been registered.
13 5.083 DEBUG 445.49 Event kernel.terminate has been registered.
14 5.130 DEBUG 448.71 Event kernel.terminate->webprofiler has been notified.
Profiling
template
# Time (msec) Name Cached Took (msec)
1 3.596 docs.tpl.php 0 1.391