generated url by paginator is not right in ZF2 - pagination

I come across an issue with ZF2 Paginating. The generate url by paginator is not correct. Could anyone help point wrong place in my configuration? I just made small change for example in page:
http://framework.zend.com/manual/2.2/en/modules/zend.paginator.usage.html
Below is my change: module.config.php:
'routes' => array(
'shop' => array(
'type' => 'Literal',
'options' => array(
'route' => '/shop',
'defaults' => array(
'__NAMESPACE__' => 'Shop\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'paginator' => array(
'type' => 'segment',
'options' => array(
'route' => '/index/list[/page/:page]',
'defaults' => array(
'page' => 1,
),
),
),
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action][/:id]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
'view_manager' => array(
....
'template_map' => array(
...
'index/page' => __DIR__ . '/../view/shop/index/page.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
In the IndexController:
public function listAction(){
$array = array(
0 => array('id'=>1, 'name'=>'samsonasik'),
.......
);
$paginator = new \Zend\Paginator\Paginator(new \Zend\Paginator\Adapter\ArrayAdapter($array));
$paginator->setCurrentPageNumber($this->params()->fromRoute('page'));
$paginator->setItemCountPerPage(1);
$vm = new ViewModel();
$vm->setVariable('paginator', $paginator);
return $vm;
}
For the list.phtml:
<?php echo $this->paginationControl($this->paginator,
'Sliding',
'index/page', array('route' => 'shop/paginator')); ?>
The script type index/pgae is mapped to page.phtml. I tried all three example controls in:
http://framework.zend.com/manual/2.2/en/modules/zend.paginator.usage.html#example-pagination-controls and changes arguments of $this->url() but all fail. For example, for search pagination, I change all:
$this->url($this->route, array('page' => $this->previous));
to
$this->url($this->route, array('controller'=>'index','action'=>'list','page' => $page));
For page:HOST/shop/index/list, all href of 2,3..and next in pagination control point to
HOST/shop/index/list/page/2 HOST/shop/index/list/page/3
This is what I expected, but this url matches shop/default instead of shop/paginator
Now the problem become simple:
how to write shop/paginator router so that url HOST/shop/index/list/page/2 can be matched:
'paginator' => array(
'type' => 'segment',
'options' => array(
'route' => '/index/list[/page/:page]',
'defaults' => array(
'page' => 1,
),
),
),
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action][/:id]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),

Related

TYPO3 - indexed_search generates wrong URL's in result

I am using indexed_search for the frontend, so users can search on my page, e.g. search for news.
But the URLs in the result of the search is wrong!
E.g.
Expected URL:
http://my-page.com/de/neuigkeiten/produktneuheiten/detail/neue-nachricht.html
Result URL:
http://my-page.com/de/neuigkeiten/produktneuheiten/detail/detail/News/neue-nachricht.html
You can see from the Result URL that /detail/News is rendered into the URL.
The structure of the pages looks like this:
Questions:
Why does /detail/News appear in the URL?
How can I fix it?
Please let me know if you need any informations from me.
typo3conf/realurl_conf.php
<?php
$GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields'] .= ',tx_realurl_pathsegment';
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl'] = array (
'_DEFAULT' => array (
'init' => array (
'enableCHashCache' => '1',
'appendMissingSlash' => 'ifNotFile,redirect',
'enableUrlDecodeCache' => '1',
'enableUrlEncodeCache' => '1',
'emptyUrlReturnValue' => '/',
'postVarSet_failureMode' => ''
//'postVarSet_failureMode' => 'redirect_goodUpperDir'
),
'redirects' => array(
'de.html'=>'de/',
'en.html'=>'en/',
'fr.html'=>'fr/',
'es.html'=>'es/',
),
'preVars' => array (
array (
'GETvar' => 'no_cache',
'valueMap' => array (
'nc' => '1',
),
'noMatch' => 'bypass'
),
array(
'GETvar' => 'L',
'valueMap' => array(
'de' => '0',
'en' => '1',
'fr' => '2',
'es' => '3',
),
'valueDefault' => 'de',
),
array (
'GETvar' => 'lang',
'valueMap' => array (
'de' => 'de',
'en' => 'en',
'fr' => 'fr',
),
'noMatch' => 'bypass',
),
),
'pagePath' => array (
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => '7',
'firstHitPathCache' => 1,
'rootpage_id' => '1',
),
'fixedPostVars' => array (
'newsDetailConfiguration' => array(
array(
'GETvar' => 'tx_news_pi1[action]',
'valueMap' => array(
'detail' => '',
),
'noMatch' => 'bypass'
),
array(
'GETvar' => 'tx_news_pi1[controller]',
'valueMap' => array(
'News' => '',
),
'noMatch' => 'bypass'
),
array(
'GETvar' => 'tx_news_pi1[news]',
'lookUpTable' => array(
'table' => 'tx_news_domain_model_news',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-'
),
'languageGetVar' => 'L',
'languageExceptionUids' => '',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'autoUpdate' => 1,
'expireDays' => 180,
)
)
),
'newsCategoryConfiguration' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][categories]',
'lookUpTable' => array(
'table' => 'sys_category',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-'
)
)
)
),
'newsTagConfiguration' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][tags]',
'lookUpTable' => array(
'table' => 'tx_news_domain_model_tag',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-'
)
)
)
),
'154' => 'newsDetailConfiguration', // For additional detail pages, add their uid as well
'155' => 'newsDetailConfiguration',
'156' => 'newsDetailConfiguration',
'157' => 'newsDetailConfiguration',
'399' => 'newsDetailConfiguration',
'71' => 'newsTagConfiguration',
'72' => 'newsCategoryConfiguration',
),
'postVarSets' => array (
'_DEFAULT' => array(
'productfinder' => array(
array(
'GETvar' => 'tx_mbclpdb_mbclproductfinder[controller]',
'noMatch' => 'bypass'
)
),
'filelist' => array(
array(
'GETvar' => 'tx_mbdownloads_mbfilelist[controller]',
'GETvar' => 'tx_mbdownloads_mbfilelistmarginal[controller]',
),
array(
'GETvar' => 'tx_mbdownloads_mbfilelist[action]',
'GETvar' => 'tx_mbdownloads_mbfilelistmarginal[action]',
'noMatch' => 'bypass'
),
),
'controller' => array(
array(
'GETvar' => 'tx_news_pi1[action]',
'noMatch' => 'bypass'
),
array(
'GETvar' => 'tx_news_pi1[controller]',
'noMatch' => 'bypass'
)
),
'dateFilter' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][year]',
),
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][month]',
),
),
'page' => array(
array(
'GETvar' => 'tx_news_pi1[#widget_0][currentPage]',
),
),
),
),
'fileName' => array (
//
// if you don't want .html-URLs set the following to "false" (e.g. 'defaultToHTMLsuffixOnPrev' => false,)
// then you get http://www.yourdomain.com/imprint/ instead of http://www.yourdomain.com/imprint.html
//
'defaultToHTMLsuffixOnPrev' => true,
'index' => array (
'sitemap.xml' => array (
'keyValues' => array(
'type' => 776,
)
),
'rss.xml' => array (
'keyValues' => array (
'type' => '100',
),
),
'rss091.xml' => array (
'keyValues' => array (
'type' => '101',
),
),
'rdf.xml' => array (
'keyValues' => array (
'type' => '102',
),
),
'atom.xml' => array (
'keyValues' => array (
'type' => '103',
),
),
'news.rss' => array (
'keyValues' => array (
'type' => '9818',
),
),
'products.rss' => array (
'keyValues' => array (
'type' => '9819',
),
),
'events.rss' => array (
'keyValues' => array (
'type' => '9820',
),
),
'workshops.rss' => array (
'keyValues' => array (
'type' => '9821',
),
),
'news.json' => array (
'keyValues' => array (
'type' => '9898',
),
),
),
),
),
);
?>
I was able to solve it by deleting these two arrays from the filetypo3conf/realurl_conf.php:
array(
'GETvar' => 'tx_news_pi1[action]',
'valueMap' => array(
'detail' => '',
),
'noMatch' => 'bypass'
),
array(
'GETvar' => 'tx_news_pi1[controller]',
'valueMap' => array(
'News' => '',
),
'noMatch' => 'bypass'
),

i want use and/or connectors in cakedc search :its not working when i search" php+sql,java" the request dont change '+' to AND the same for',' to OR

im my model User.php
public $hasAndBelongsToMany = array(
'Competence' => array(
'with' => 'CompetencesUser',
'className' => 'Competence',
'joinTable' => 'competences_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'competence_id',
'unique' => 'keepExisting',
my $filterArgs () in my model User.php i use before to modifie my request in $query
'competences' => array(
'type' => 'subquery',
'method' => 'findByCompetences',
'field' => 'User.id',
'before'=>true)
im my function findByCompetences($data=array()) i want have cometence1 and competence2 and competence 3 or competence4
$this->CompetencesUser->Behaviors->attach('Containable', array(
'autoFields' => false
)
);
$this->CompetencesUser->Behaviors->attach('Search.Searchable');
$query = $this->CompetencesUser->getQuery('all', array(
'conditions' =>
array(
'Competence.competence' => $data['competences'],
'fields' => array(
'foreign_key'
),
'contain' => array(
'Competence'
),
'search_with_connectors' => array(
'type' => 'like',
'field' => 'Competence.competence',
'connectorAnd' => '+', 'connectorOr' => ','
)
)));
return $query;
}

ZF2 paginator with query string

I'm newby in PHP and ZF2.
I have a paginator, which I need to keep the sorting, search and filters from query string like this:
http://localhost:90/admin/analyses/list?page=1&filter_analyses_categories=1&orderBy=analyses_name&orderDirection=DESC
I read about routing, but I'm not understand how to use in my situation.
In module.config.php I have:
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Admin\Controller',
'action' => 'index',
),
),
), //end home
'admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => 'Admin\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action][/page/:page]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
), //end admin
'paginator' => array(
'type' => 'segment',
'options' => array(
'route' => '',
'defaults' => array(
'page' => 1,
),
'may_terminate' => true,
'child_routes' => array(
'query' => array(
'type' => 'Query',
),
),
),
),//end paginator
),//end routes
),
);
The paginator partial view look like below:
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
<li>
<a href="<?php echo $this->url($this->route);?>?page=<?php echo $page; ?>">
<?php echo $page; ?>
</a>
</li>
<?php else: ?>
<li class="active">
<?php echo $page; ?>
</li>
<?php endif; ?>
<?php endforeach; ?>
The link created for each page is like this:
http://localhost:90/admin/analyses/list?page=3
without the others query string parmaeters.
How can achieve the right url for each page keeping the others query string parameters?
Do not pass your page parameter as query string. use your defined route parameter instead:
$this->url('admin/default', ['page' => $page], true);
The third parameter keeps your already matching route parameters

RealURL extension not working for typo3 v6.2.x when domain given as IP Address

I have a webpage tree structure given below
In this tree when I access like http://localhost/mysite its redirect to "Root Local" and accessed like http://192.168.1.20/mysite/ its redirect to "Root IP" by setting it in domain.
I implemented realURL extension. and it working fine for localhost and URL become http://localhost/mysite/en/home/ .
But when I tried to access it by 192.168.1.20 as domain, the URL shows like http://192.168.1.20/mysite/en/home/.
Bur it shows the blank web page with error "This webpage has a redirect loop" .
My realurl_conf.php looks like
<?php
$TYPO3_CONF_VARS['EXTCONF']['realurl'] = array(
// sitename
'_DEFAULT' => array(
// initialization
'init' => array(
'useCHashCache' => '0', // für tt_news
'enableCHashCache' => true,
'appendMissingSlash' => 'ifNotFile',
'enableUrlDecodeCache' => true,
'enableUrlEncodeCache' => true,
'emptyUrlReturnValue' => '/'
),
// first url rewriting segment
'preVars' => array(
array(
'GETvar' => 'L',
'valueMap' => array(
'de' => 3,
'en' => 1,
),
'valueDefault' => 1,
),
),
// second url rewriting segment
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => 30,
'rootpage_id' => 1
),
// third url rewriting segment
'fixedPostVars' => array(
),
// forth url rewriting segment
'postVarSets' => array(
'_DEFAULT' => array(
/*
no_cache setting should not be used in preVars
#see http://dmitry-dulepov.com/article/do-not-use-no-cache-as-prevar.html
*/
'nc' => array(
'type' => 'single',
'GETvar' => 'no_cache',
),
)
),
)
);
$byPassLVar = array(
array(
'GETvar' => 'L',
'valueMap' => array(),
'noMatch' => 'bypass'
)
);
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['_DEFAULT'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local']['pagePath']['rootpage_id'] = 1;
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local']['preVars'] = $byPassLVar;
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['192.168.1.20'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP']['pagePath']['rootpage_id'] = 3;
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP']['preVars'] = $byPassLVar;
switch (t3lib_div::getIndpEnv('HTTP_HOST')) {
case 'Root_Local':
$_GET['L'] = 1;
break;
case 'Root_IP':
$_GET['L'] = 1;
break;
default:
$_GET['L'] = 1;
break;
}
?>
And I added in the main Template
config.simulateStaticDocuments = 0
config.baseURL = http://192.168.1.20/mysite/
config.tx_realurl_enable = 1
for the IP Address and
config.simulateStaticDocuments = 0
config.baseURL = http://localhost/mysite/
config.tx_realurl_enable = 1
for local host
Why it not working for the IP address as domain.??
How can I make it work ?
Thanks in advance
Finally I found an answer myself. I am not fully known how it works. If anyone can help me please be free to add it.
I edited my realurl_conf.php like this and work like a charm..
<?php
$TYPO3_CONF_VARS['EXTCONF']['realurl'] = array(
// sitename
'_DEFAULT' => array(
// initialization
'init' => array(
'useCHashCache' => '0',
'enableCHashCache' => true,
'appendMissingSlash' => 'ifNotFile',
'enableUrlDecodeCache' => true,
'enableUrlEncodeCache' => true,
'emptyUrlReturnValue' => '/'
),
// first url rewriting segment
'preVars' => array(
array(
'GETvar' => 'L',
'valueMap' => array(
'de' => 3,
'en' => 1,
),
'valueDefault' => 'en',
),
),
// second url rewriting segment
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => 30,
'rootpage_id' => 1
),
// third url rewriting segment
'fixedPostVars' => array(
),
// forth url rewriting segment
'postVarSets' => array(
'_DEFAULT' => array(
/*
no_cache setting should not be used in preVars
#see http://dmitry-dulepov.com/article/do-not-use-no-cache-as-prevar.html
*/
'nc' => array(
'type' => 'single',
'GETvar' => 'no_cache',
),
)
),
)
);
$TYPO3_CONF_VARS['EXTCONF']['realurl']['192.168.1.20'] = array(
// sitename
// initialization
'init' => array(
'useCHashCache' => '0',
'enableCHashCache' => true,
'appendMissingSlash' => 'ifNotFile',
'enableUrlDecodeCache' => true,
'enableUrlEncodeCache' => true,
'emptyUrlReturnValue' => '/'
),
// first url rewriting segment
'preVars' => array(
array(
'GETvar' => 'L',
'valueMap' => array(
'de' => 3,
'en' => 1,
),
'valueDefault' => 'en',
),
),
// second url rewriting segment
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => 30,
'rootpage_id' => 3
),
// third url rewriting segment
'fixedPostVars' => array(
),
// forth url rewriting segment
'postVarSets' => array(
'192.168.1.20' => array(
/*
no_cache setting should not be used in preVars
#see http://dmitry-dulepov.com/article/do-not-use-no-cache-as-prevar.html
*/
'nc' => array(
'type' => 'single',
'GETvar' => 'no_cache',
),
)
),
);
$byPassLVar = array(
array(
'GETvar' => 'L',
'valueMap' => array(),
'noMatch' => 'bypass'
)
);
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['_DEFAULT'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local']['pagePath']['rootpage_id'] = 1;
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_Local']['preVars'] = $byPassLVar;
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP'] = $TYPO3_CONF_VARS['EXTCONF']['realurl']['192.168.1.20'];
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP']['pagePath']['rootpage_id'] = 3; //overwrite root page ID with the one for this specific domain
$TYPO3_CONF_VARS['EXTCONF']['realurl']['Root_IP']['preVars'] = $byPassLVar;
switch (t3lib_div::getIndpEnv('HTTP_HOST')) {
case 'Root_Local':
case 'Root_Local':
$_GET['L'] = 1;
break;
case 'Root_IP':
case 'Root_IP':
$_GET['L'] = 1;
break;
default:
$_GET['L'] = 1;
break;
}
?>
Thank you.

Zf2 Locale in URL and $this->url

I am developing a web app on ZF2 Skeleton App base. I have played with lot of options but failed to get final headway.
I need to route the url as under:
http://myapp/
http://myapp/en/album
to AlbumController/indexAction. Also, links need to work as:
http://myapp/en/album/edit/1
http://myapp/en/album/delete/1
The code generates correct URLs but on clicking returns "404" error
My Application/module.config.php is as under:
return array (
'router' => array (
'routes' => array (
'home' => array (
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array (
'route' => '/',
'defaults' => array (
'controller' => 'Album\Controller\Album',
'action' => 'index',
'lang' => 'en',
)
)
),
'application' => array (
'type' => 'Literal',
'options' => array (
'route' => '/application',
'defaults' => array (
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array (
'default' => array (
'type' => 'Segment',
'options' => array (
'route' => '[:lang[/album[/:action[/:id]]]]',
'constraints' => array (
'lang' => '[a-z]{2}',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+'
),
'defaults' => array (
'controller' => 'Album\Controller\Album',
'action' => 'index',
'lang' => 'en',
)
)
)
)
)
)
),
'service_manager' => array (
'factories' => array (
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory'
)
),
'translator' => array (
'locale' => 'en_US',
'translation_file_patterns' => array (
array (
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo'
)
)
),
'controllers' => array (
'invokables' => array (
'Application\Controller\Index' => 'Application\Controller\IndexController'
)
),
'view_manager' => array (
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array (
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml'
),
'template_path_stack' => array (
__DIR__ . '/../view'
)
)
);
My Album/module.config.php has the following router:
'router' => array (
'routes' => array (
'album' => array (
'type' => 'segment',
'options' => array (
'route' => '[:lang[/album[/:action[/:id]]]]',
'constraints' => array (
'lang' => '[a-z]{2}',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+'
),
'defaults' => array (
'controller' => 'Album\Controller\Album',
'action' => 'index',
'lang' => 'en',
)
),
)
)
),
////////////////////////////////////////////////////////////////////////////////////////
// Now this works fine.
Also, when I do call the $this->url('album',array('action'=>'edit', 'id' => $album->id)); in view file (.phtml), it does'nt return proper url as expected:
http://www.myapp.com/en/edit/id/1
////////////////////////////////////////////////////////////////////////////////////////
//Corrected code works for URL
$this->url('album', array('action'=>'edit', 'id' => $album->id))
///////////////////////////////////////////////////////////////////////////////////////
Appreciate your help in advance.
The issue was missing '/' in Album/module.config.php:
'route' => '[:lang[/album[/:action[/:id]]]
should have been:
'route' => '/[:lang[/album[/:action[/:id]]]
Thanks again to all for help.

Resources