Search code examples
phpsymfonyconcrete5

Concrete5: optional parameters for Route::register


I'm attempting to create a class extended from Controller in Concrete5 (php) with optional parameters. I've attempted to scour both the Concrete5 and Symfony documentation, but either the answer is not there, or I'm daft when it comes to oop in php. So, I'm looking for a little hand-holding to get me through this process.

the tail of my application\bootstrap\app.php

Route::register(
     '/plotdata/{start}/{end}' //1 below
   , 'Application\Controller\SinglePage\getplotdata::getData' //2
   , NULL //3
   , array() //4
   , array('var1' <= NULL, 'var2' <= NULL, 'var3' <= NULL, 'var4' <= NULL) //5 
//1 rtPath | path - start and end are required params /{var1}/{var2}/{var3}/{var4} are optional,
//2 callback
//3 rtHandle
//4 requirements = array() see e.g. line below
//      array('start' => '[0-9]{4}(-[0-9]{2}){2} [ 0-2][0-9](:[0-5][0-9]){2}(.[0-9]{3})?'
//5 options | additionalAttributes
);

results in any URI with parameters beyond end producing an error. e.g.

plotdata/2015-02-01 00%3A00%3A00/2016-02-09 23%3A59%3A00/blah

produces a 404 error. It will load if I leave off the /blah at the end (albeit without setting $var1=blah), assuming getplotdata.php exists in the appropriate directory and has these lines near the head.

namespace Application\Controller\SinglePage;
class getplotdata extends Controller {

If line "1" (in the first block) is modified to read

     '/plotdata/{start}/{end}/{var1}/{var2}/{var3}/{var4}'

leaving the other lines (including 5) the same, I need to parameterize each. e.g. neither plotdata/2015-02-01 00%3A00%3A00/2016-02-09 23%3A59%3A00/blah

nor plotdata/2015-02-01 00%3A00%3A00/2016-02-09 23%3A59%3A00 work,

but plotdata/2015-02-01 00%3A00%3A00/2016-02-09 23%3A59%3A00/1/2/3/4 does

so, how do I specify optional parameters (with or without default values [by exposing $defaults from Symfony?]), or is there a way to produce an "overloaded" class definition in Concrete5? Do I do something like

$bob = Route::register(
    '/plotdata/{start}/{end}'
  , 'Application\Controller\SinglePage\getplotdata::getData'
); //end $bob
$bob->addDefaults(array('var1' <= NULL, 'var2' <= NULL, 'var3' <= NULL, 'var4' <= NULL));

Solution

  • It seems I have it working now. This is the relevant app.php code:

    Route::register(
        '/plotdata/{start}/{end}{optparams}'
       , 'Application\Controller\SinglePage\getplotdata::getData'
     )->addRequirements(
        array('optparams' => '.*')
     )->addDefaults(
        array('optparams' => '/')
     );
    

    of note

    1. No / between {end} and {optparams}, otherwise a / is required after {end} AND you need at least one additional value in the URI (newline or space+newline after the URI doesn't seem to work)*.
    2. The '.*' "RegEx" should match even 0-length strings, so you can get away with no trailing slash and/or other values.
    3. The addDefaults bit makes it so both terminating the URI after the end value or adding a trailing / on the URL results in the same value passed on. Incidentally, leaving it as addDefaults(array('optparams' => '')) also seems to work given my implementation in the controller file below.

    then in the registered controller file (getplotdata.php):

    $in_ar = explode('/',Request::getInstance()->get('optparams'));
    array_shift($in_ar);    //get rid of "empty" parameter at start
    

    This will fill the array variable $in_ar with each of the values between any subsequent /s. Terminating with a / after some optional parameters will result in an empty string for the final array element. You'd probably experience something similar if you had consecutive /s in the URI somewhere.

    Alternatively, you could probably transition to the ?var1=val&var2=value form by altering the explode to split on both ? and &, shift to get rid of the empty first element, then re-explode each array element into key+value pairs on the = character

    *at least on Firefox with my Concrete5 installation...YMMV

    ref: Symfony "cookbook" doc that helped me to break through this problem.