Reputation: 315
I have following regex route, which allows me to use pagination - to parse URL and also build it:
; route "product-{brand}"
product.type = "Zend_Controller_Router_Route_Regex"
product.route = "product-([a-z\-]+)(?:/page/(\d+)/?)?"
product.defaults.module = "default"
product.defaults.controller = "products"
product.defaults.action = "product"
product.defaults.page = "1"
product.map.1 = "brand"
product.map.2 = "page"
product.reverse = "product-%s/page/%d"
Everything is working fine, however, I need to get the rid of default page. Currently we are migrating old web to the Zend and we need to preserve old links because of current google positions, etc.
With default "page", I'm getting always /page/1, without it Zend "cannot assemble" URL. How to not display page 1 in URL ?
Upvotes: 0
Views: 1001
Reputation: 315
Finally, I've managed to achieve this, but only by rewriting Regex assemble method. I'm simply overriding two methods.
Class extension:
class Utils_Router_Regex extends Zend_Controller_Router_Route_Regex
{
// instantiate
public static function getInstance(Zend_Config $config)
{
$defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
$map = ($config->map instanceof Zend_Config) ? $config->map->toArray() : array();
$reverse = (isset($config->reverse)) ? $config->reverse : null;
return new self($config->route, $defs, $map, $reverse);
}
// in this case, we are using $this->_reverse as array from config
public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
{
//// EXTENSION PART !!!
if( !isset( $data[(string) $this->_reverse->pagemap]) ) { // if not set url helper
$reverse = $this->_reverse->base;
} else { // if set in url helper
$reverse = $this->_reverse->paginator;
}
/// end of extension part
if ($reverse === null) {
require_once 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception('Cannot assemble. Reversed route is not specified.');
}
$defaultValuesMapped = $this->_getMappedValues($this->_defaults, true, false);
$matchedValuesMapped = $this->_getMappedValues($this->_values, true, false);
$dataValuesMapped = $this->_getMappedValues($data, true, false);
// handle resets, if so requested (By null value) to do so
if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) {
foreach ((array) $resetKeys as $resetKey) {
if (isset($matchedValuesMapped[$resetKey])) {
unset($matchedValuesMapped[$resetKey]);
unset($dataValuesMapped[$resetKey]);
}
}
}
// merge all the data together, first defaults, then values matched, then supplied
$mergedData = $defaultValuesMapped;
$mergedData = $this->_arrayMergeNumericKeys($mergedData, $matchedValuesMapped);
$mergedData = $this->_arrayMergeNumericKeys($mergedData, $dataValuesMapped);
if ($encode) {
foreach ($mergedData as $key => &$value) {
$value = urlencode($value);
}
}
ksort($mergedData);
$return = @vsprintf($reverse, $mergedData);
if ($return === false) {
require_once 'Zend/Controller/Router/Exception.php';
throw new Zend_Controller_Router_Exception('Cannot assemble. Too few arguments?');
}
return $return;
}
}
Then you can define which sprintf string to use:
hodinky.type = "Utils_Router_Regex"
hodinky.route = "hodinky-([a-z\-]+)(?:/page/(\d+)/?)?"
hodinky.defaults.module = "default"
hodinky.defaults.controller = "products"
hodinky.defaults.action = "hodinky"
hodinky.map.1 = "znacka"
hodinky.map.2 = "page"
hodinky.reverse.paginator = "hodinky-%s/page/%d" ; assebmly with paginator
hodinky.reverse.base = "hodinky-%s/" ; assebmly without paginator
hodinky.reverse.pagemap = "page" ; "page" map key
If you have better solution, please let me know.
Upvotes: 0