We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Create or define custom routing placeholders

Hi all,

I wonder if is possible to create or define custom routing placeholders for my app, as described by default in routing documentation. http://docs.phalcon.io/en/latest/reference/routing.html#defining-routes

Is it possible to define a custom placeholder with a regular expression and use it as default placeholders (ex: /:params, /;int) in my app, without repeat in each route definition?

Thank you for your attention.



98.8k

Could you please post the approximate code you are expecting?



1.5k

Route declaration traditional way:

//Define a route (traditional way)
$router->add(
    '/faq/{country:[a-z]{2}}',
    array(          
        'controller' => 'main',
        'action' => 'faq'
    )
);

Is posible create a custom placeholder called country to use as well?:

//Define a route using country custom placeholder
router->add('/faq/:country',
    array(          
        'controller' => 'main',
        'action' => 'faq'
    )
);

Thank you so much for your attention and sorry for the inconvenience.



98.8k

You can define a route without the regular expression:

$router->add(
    '/faq/{country}',
    array(          
        'controller' => 'main',
        'action' => 'faq'
    )
);


1.5k
Accepted
answer
edited Jul '14

First of all thanks for your attention and quick response.

Sorry, I think I have not explained well, my question is if there is any way to create a placeholder to which you attach a regular expression for later use in the definition of the routes, being well defined regular expression in a single point of the code.

After review cphalcon extension source code, I found the function where default routing placeholders are defined (ext/mvc/router/route.c):

/**
 * Replaces placeholders from pattern returning a valid PCRE regular expression
 *
 * @param string $pattern
 * @return string
 */
PHP_METHOD(Phalcon_Mvc_Router_Route, compilePattern){

    zval *pattern, *compiled_pattern = NULL, *id_pattern;
    zval wildcard, *pattern_copy = NULL, *params_pattern;
    zval *int_pattern;

    PHALCON_MM_GROW();

    phalcon_fetch_params(1, 1, 0, &pattern);

    PHALCON_CPY_WRT(compiled_pattern, pattern);

    /** 
     * If a pattern contains ':', maybe there are placeholders to replace
     */
    if (phalcon_memnstr_str(pattern, SL(":"))) {

        /** 
         * This is a pattern for valid identifiers
         */
        PHALCON_INIT_VAR(id_pattern);
        ZVAL_STRING(id_pattern, "/([a-zA-Z0-9_-]++)", 1);

        /** 
         * Replace the module part
         */
        if (phalcon_memnstr_str(pattern, SL("/:module"))) {
            INIT_ZVAL(wildcard);
            ZVAL_STRING(&wildcard, "/:module", 0);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, id_pattern, pattern_copy);
        }

        /** 
         * Replace the controller placeholder
         */
        if (phalcon_memnstr_str(pattern, SL("/:controller"))) {
            INIT_ZVAL(wildcard);
            ZVAL_STRING(&wildcard, "/:controller", 0);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, id_pattern, pattern_copy);
        }

        /** 
         * Replace the namespace placeholder
         */
        if (phalcon_memnstr_str(pattern, SL("/:namespace"))) {
            INIT_ZVAL(wildcard)
            ZVAL_STRING(&wildcard, "/:namespace", 0);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, id_pattern, pattern_copy);
        }

        /** 
         * Replace the action placeholder
         */
        if (phalcon_memnstr_str(pattern, SL("/:action"))) {
            INIT_ZVAL(wildcard);
            ZVAL_STRING(&wildcard, "/:action", 0);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, id_pattern, pattern_copy);
        }

        /** 
         * Replace the params placeholder
         */
        if (phalcon_memnstr_str(pattern, SL("/:params"))) {
            INIT_ZVAL(wildcard);
            ZVAL_STRING(&wildcard, "/:params", 0);

            PHALCON_INIT_VAR(params_pattern);
            ZVAL_STRING(params_pattern, "(/.*+)?+", 1);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, params_pattern, pattern_copy);
        }

        /** 
         * Replace the int placeholder
         */
        if (phalcon_memnstr_str(pattern, SL("/:int"))) {
            INIT_ZVAL(wildcard);
            ZVAL_STRING(&wildcard, "/:int", 0);

            PHALCON_INIT_VAR(int_pattern);
            ZVAL_STRING(int_pattern, "/([0-9]++)", 1);
            PHALCON_CPY_WRT(pattern_copy, compiled_pattern);

            PHALCON_INIT_NVAR(compiled_pattern);
            phalcon_fast_str_replace(compiled_pattern, &wildcard, int_pattern, pattern_copy);
        }
    }

    /** 
     * Check if the pattern has parantheses in order to add the regex delimiters
     */
    if (phalcon_memnstr_str(compiled_pattern, SL("("))) {
        PHALCON_CONCAT_SVS(return_value, "#^", compiled_pattern, "$#");
        RETURN_MM();
    }

    /** 
     * Square brackets are also checked
     */
    if (phalcon_memnstr_str(compiled_pattern, SL("["))) {
        PHALCON_CONCAT_SVS(return_value, "#^", compiled_pattern, "$#");
        RETURN_MM();
    }

    RETURN_CCTOR(compiled_pattern);
}

After review this code I think that creating a class CustomRoute that inherits from \Phalcon\Mvc\Router\Route class, overriding the method compilePattern to replace custom placeholders for its associated regular expressions, and using this class for routing, could answer my question:


class CustomRoute extends \Phalcon\Mvc\Router\Route
{

    /**
     * Replaces placeholders from pattern returning a valid PCRE regular expression
     *
     * @param string $pattern
     * @return string
     */
    public function compilePattern($pattern) 
    {
        // Compile default placeholders
        $result = parent::compilePattern($pattern);

        // Compile custom placeholders          
        $result = str_replace('/:country', '{country:[a-z]{2}}', $result);          
        $result = str_replace('/:year', '{year:[0-9]{4}}', $result);            

        return $result;
    }

}   

Again, thanks for all and sorry for the inconvenience.

Regards.