I am currently developing a custom module.
What I want is to have a nice URL, because right now it looks like this:
domain.com/flower-deliveries?city=Hamburg&id_country=1&country=Germany
I already added a new page to link to the custom module, the page name is flower-deliveries, but still I have the parameters that I have to "hide".
Instead, of that link above I would like a URL like this:
domain.com/flower-deliveries-1-Hamburg-Germany.html
I tried 2 methods, but none of them worked..
The first one, was to add a hookModuleRoutes in my controller, just like below:
public function hookModuleRoutes($params)
{
return array(
'module-vpages-dpage' => array(
'controller' => 'dpage',
'rule' => 'flower-deliveries{-:id_country}{-:country}{-:city}.html',
'keywords' => array(
'id_country' => array('regexp' => '[_a-zA-Z0-9_-]+', 'param' => 'id_country'),
'city' => array('regexp' => '[\w]+', 'param' => 'city'),
'country' => array('regexp' => '[\w]+', 'param' => 'country')
),
'params' => array(
'fc' => 'module',
'module' => 'vpages',
'controller' => 'dpage'
)
)
);
}
And then, in the controllers install:
$this->registerHook('moduleRoutes');
That didn't worked, so I tried to override the Dispatcher class, by adding a custom module route:
'module-vpages-dpage' => array(
'controller' => 'dpage',
'rule' => 'flower-deliveries{-:id_country}{-:country}{-:city}.html',
'keywords' => array(
'id_country' => array('regexp' => '[0-9]+', 'param' => 'id_country'),
'city' => array('regexp' => '[\w]+', 'param' => 'city'),
'country' => array('regexp' => '[\w]+', 'param' => 'country'),
),
'params' => array(
'fc' => 'module',
'module' => 'vpages',
'controller' => 'dpage'
)
),
When using that custom rule, the link http://domain.com/flower-deliveries?city=Hamburg&id_country=1&country=Germany was tranformed in http://domain.com/flower-deliveries?module_action=list and it didn't worked and was redirecting me to the first page.
Could some one tell me what am I doing wrong?
I've spent hours of reading how it should be done and it should be just like the ones above..
Thank you!
Revert all edits that you have done :).
Try this way:
For example, this is core module file rootofps/modules/vpages/vpages.php
class VPages extends Module {
public function __construct(){
$this->name = 'vpages';
$this->author = 'you';
$this->tab = 'front_office_features';
$this->version = '1.0.0';
$this->controllers = array('dpage');
parent::__construct();
}
// This is the function in your core module file (not in controller)
public function install(){
return parent::install() && $this->registerHook('moduleRoutes')
}
public function hookModuleRoutes($params){
$my_link = array(
'vpages' => array(
'controller' => 'dpage',
'rule' => 'flower-deliveries{-:id_country}{-:country}{-:city}.html',
'keywords' => array(
'id_country' => array('regexp' => '[0-9]+', 'param' => 'id_country'),
'country' => array('regexp' => '[\w]+', 'param' => 'country'),
'city' => array('regexp' => '[\w]+', 'param' => 'city'),
),
'params' => array(
'fc' => 'module',
'module' => 'vpages'
)
)
);
return $my_link;
}
}
Now the controller rootofps/modules/vpages/controllers/front/dpage.php
class VpagesDpageModuleFrontController extends ModuleFrontController {
public function init(){
parent::init();
$this->setTemplate('dapage.tpl');
}
}
And now the view rootofps/modules/vpages/views/templates/front/dpage.tpl
id_country = {$smarty.get.id_country}<br>
country = {$smarty.get.country}<br>
city={$smarty.get.city}<br>
This 'skeleton' works at 100% :), by the way, notice that if you give an url like this mydomain.com/flower-deliveries?id_country=1&country=italy&city=rome PrestaShop will not transform your url in a clearly url as you want.
But an url like this mydomain.com/flower-deliveries-2-italy-rome.html will be routes properly :)
Related
I'm thinking about the best way of implementing ACL. So - I need to protect certain routes. Some routes would be accessible only to users, some to guests and some to admins.
It seems like the best way of doing it would be by adding a $role variable in the routing config. So then I'd attach to post-route event, fetch the routeMatch and I would see if this user can enter this route.
How can I do that? Can I simply inject extra varibles like this:
'router' => array(
'routes' => array(
'route1' => array(
'type' => 'Zend\Mvc\Router\Http\Regex',
'options' => array(
'regex' => '/some/route/1',
'defaults' => array(
'controller' => 'Subscriber\Controller\View',
'action' => 'route1',
'role' => 'user', //extra
),
'spec' => '/some/route/1',
),
),
'route2' => array(
'type' => 'Zend\Mvc\Router\Http\Regex',
'options' => array(
'regex' => '/some/route/2',
'defaults' => array(
'controller' => 'Subscriber\Controller\View',
'action' => 'route2',
'role' => 'guest', //extra
),
'spec' => '/some/route/2',
),
),
//other routes....
),
),
Yes you can just add the router key like you have
'defaults' => array(
'controller' => 'Subscriber\Controller\View',
'action' => 'route1',
'role' => 'user', //extra
),
And then you can checkit like this
public function onBootstrap(MvcEvent $e) {
$application = $e->getApplication();
$eventManager = $application->getEventManager();
$eventManager->attach(MvcEvent::EVENT_ROUTE, function(MvcEvent $e) {
$e->getRouteMatch()->getParam('role');
});
}
There are however modules made for this
For example bjyoungblood/BjyAuthorize which works with ZfcUser
You should take a look at : ZfcRbac. It's well documented.
I follow this tutorial: http://ivangospodinow.com/zend-framework-2-acl-setup-in-5-minutes-tutorial/
But, I want to grant permission by custom URLs, so I had some changes in my code.
In module.acl.roles.php
return array(
'guest'=> array(
'/home.html',
'/login.html',
'/register.html'
),
'admin'=> array(
'/user/add.html',
'/user/edit.html',
'/user/list.html',
),
);
In module.config.php
return array(
'router' => array(
'routes' => array(
'/home.html' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
'/user/add.html' => array(
'type' => 'Zend\Mvc\Router\Http\Regex',
'options' => array(
'regex' => '/user/add.html',
'defaults' => array(
'controller' => 'Application\Controller\User',
'action' => 'add',
'format' => 'html',
),
'spec' => '/user/add.%format%',
),
),
...
),
),
);
But I received this error: Route with name "" not found. Please give me some advices and solutions to grant permission by URLs
Thank you!
I really really recommend the BjyAuthorize module (https://packagist.org/packages/bjyoungblood/bjy-authorize).
But if you really want to do this by yourselft you need to add a listener to the \Zend\Mvc\MvcEvent::EVENT_ROUTE.
You can attach your listener with
$events->attach(MvcEvent::EVENT_ROUTE, array($this, 'myOnRoute'), -1000);
and in your myOnRoute method you can handle the route
public function myOnRoute(MvcEvent $event) {
$match = $event->getRouteMatch();
$routeName = $match->getMatchedRouteName();
// do stuff here (compare to config or whatever)
}
im developing small app and I decided that i will use CakePhp as a framework, i was doint tutorial to make "posts". But when i wanted to use funcionality Simple Authentication and Authorization Application from here i was doing copy and paste and encountered 2 issues
first my User model doesn't see SimplePasswordHasher
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
class User extends AppModel {
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('admin', 'author')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
)
);
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new SimplePasswordHasher(); <---- here
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}}
maybe App::uses('SimplePasswordHasher', 'Controller/Component/Auth'); doesn't point in right place but i didn't found a way to check it.
second issue is when i try to enter at login page i got Authentication adapter "Form" was not found. Where i can init that adapter. any help would be great.
You must specify the same SimplePasswordHasher in controller as well as follows:
public $components = array(
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login'
),
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => array(
'Form' => array(
'passwordHasher' => array(
'className' => 'Simple',
'hashType' => 'sha256'
)
)
),
'loginRedirect' => array(
'controller' => 'users',
'action' => 'index'
)
)
);
Hope it helps
This is my navigation in global.php
'navigation' => array(
'default' => array(
'loja' => array(
'label' => 'Loja',
'route' => 'loja',
'params' => array('action'=>'index'),
'pages' => array(
'estoque' => array(
'label' => 'Estoque',
'params' => array('action'=>'index'),
'action'=>'index',
'id' => 'estoque',
'route' => 'estoque',
)),
),
'suport'=> array(
'test' => array(
'label' => 'Loja',
'route' => 'loja',
'params' => array('action'=>'index'),
'pages' => array(
'estoque' => array(
'label' => 'Estoque',
'params' => array('action'=>'index'),
'action'=>'index',
'id' => 'estoque',
'route' => 'estoque',
)),
),),
when I call navigation the 'default' comes, I want to call the navigation 'suport', how I can do it?
My code in layout.phtml ..
echo $this->navigation('Navigation')->menu()->setUlClass('nav dropdown-submenu')->renderMenu();
Thanks :)
First create a container:
<?php $container = $this->navigation()->findOneByLabel('support');?>
Read more about finding nodes here: http://framework.zend.com/manual/2.2/en/modules/zend.navigation.containers.html
Than use it:
<?php echo $this->navigation()->menu()->renderMenu($container);?>
(Put this in your view script.)
Read more about this in the docs: http://framework.zend.com/manual/2.2/en/modules/zend.navigation.view.helper.menu.html
Can You Try This in view script:
Create Container Like this
<?php $container = $this->navigation('support')->getContainer(); ?>
Echo the Container to use this one:
<?php echo $this->navigation($container); ?>
Create your own navigation factory by extending Zend\Navigation\Service\DefaultFactory
namespace Application\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class MyNavigation extends DefaultNavigationFactory
{
public function getName() {
return 'suport';
}
}
and in Module.php
public function getServiceConfig()
{
return array(
'invokables' => array(
'my_navigation' => 'Application\Navigation\Service\MyNavigation'
}
}
}
Now you can use your navigation echo $this->navigation('my_navigation')->menu()
I have the following routing definition:
'admin_default' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:lang]/administrator[/:module][/:action]',
'constraints' => array(
'lang' => '[a-zA-Z]{2}',
'module' => '[a-zA-Z0-9_-]*',
'action' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
'module' => 'Application',
'controller' => 'Admin',
'action' => 'index',
'lang' => 'ru'
),
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'wildcard',
'may_terminate' => true,
'options' => array(
'key_value_delimiter' => '/',
'param_delimiter' => '/'
),
),
),
),
So, I can't get rid of segment [/:lang] in URL string
For example:
URL view helper $this->url('admin_default', array('module' => 'albums')) returns the following URL string:
/administrator/albums
while $this->url('admin_default/wildcard', array('module' => 'albums', 'action' => 'edit', 'id' => album_id_here)) returns:
/ru/administrator/albums/edit/id/album_id_here
How can I remove [/:lang] segment from URL string in second case?
so whats the matter with that "ru" ?
you have to extend the zend view helper URL to inject your current locale to the URL
look what i made for my current project :
<?php
namespace PatrickCore\View\Helper;
use Doctrine\ORM\EntityManager;
use Zend\View\Helper\Url;
class I18nUrl extends Url {
/**
* #var String
*/
protected $lang;
protected $router;
public function __construct($locale,$router) {
$arraylanguagemapping = array(
'en_US' => 'en',
'fa_IR' => 'fa'
);
$this->lang = $arraylanguagemapping[$locale];
$this->router = $router;
}
public function __invoke($name = null, array $params = array(), $options = array(), $reuseMatchedParams = false) {
$this->setRouter($this->router);
if (!array_key_exists('lang', $params)) {
$params['lang'] = $this->lang;
}
return parent::__invoke($name,$params,$options,$reuseMatchedParams);
}
}
?>