Jump to content

PS 1.5 / Dispatcher hook fantome


DevNet

Recommended Posts

Salut,

 

Sur PrestaShop 1.5.0.17, dans la ./classes/Dispatcher.php , lignes 343 :

  // Execute hook dispatcher
  if (isset($params_hook_action_dispatcher))
   Hook::exec('actionDispatcher', $params_hook_action_dispatcher);

 

Est-ce que ce hook est encore en cours de développement ?

Car il n'existe nul part ailleurs que dans le code de cette classe.

 

Aucun enregistrement dans ps_hook, et de ce fait, aucune accroche possible dans l'AdminModule + classe Module.

 

Ce hook semble pourtant stratégiquement intéressant pour éviter de créer un override sur la cette classe, et ainsi traiter les rewritecond / rule personnalisées.

 

De plus pourquoi le dispatcher ne fait pas partie du context ?

 

A+

Link to comment
Share on other sites

Et j'ai répondu dessus, ce n'est nullement un bug. :)

 

Il suffit qu'un module enregistre le hook (via sa méthode install) et c'est ok. C'est le principe de l'ajout dynamique des hooks.

 

Ce n'est pas un bug, la réponse de Jonathan est très claire dans le post proposé en lien.

 

Ou mieux, un article qu'il à écrit pour PHPSolution :

http://www.prestasho...836#entry921836

 

 

A aucun moment j'ai dit que c'était un bug :blink:

 

La forge ne sert pas qu'à référencer des bugs

 

Le statut du ticket est


  • Type: improvement.gif Amélioration

...

Link to comment
Share on other sites

Soit, là n'est pas le problème. Mais le ticket peut être clos, quoi...

 

Oui et non.

 

Oui, j'ai effectivement pris connaissance de cet article http://www.prestashop.com/forums/index.php?app=core&module=attach&section=attach&attach_id=57323 , il me donne 50% de la réponse à une demande initiale sur le dispatcher.

 

Non, il me manque 50% sur l'utilisation du dispatcher depuis le context.

 

Ton article annonce en 1ère page "le dispatcher et le gestionnaire d'URL", qu'entends-tu par "gestionnaire d'URL" ?

Link to comment
Share on other sites

Je ne parlais pas du sujet, il n'a pas besoin d'être clos. Je parlais du ticket, sur la forge (il me semble que la réponse est donnée, puisqu'il est possible d'utiliser le dit hook).

 

Le gestionnaire d'URL se situe dans l'AdminMeta (SEO & URLs) et permet, par exemple, d'éviter un chemin de type /index.php?fc=module&module=annuaire&controller=all en indiquant le rewriting pour la page en tant que /annuaire

Link to comment
Share on other sites

Le gestionnaire d'URL se situe dans l'AdminMeta (SEO & URLs) et permet, par exemple, d'éviter un chemin de type /index.php?fc=module&module=annuaire&controller=all en indiquant le rewriting pour la page en tant que /annuaire

 

Ok, je pensais que tu parlais de quelque chose de nouveau. Notamment sur la gestion des urls sous rewritecond personnalisées depuis un module.

 

Pour l'instant j'arrive à faire fonctionner mes propres rewritecond / rule en override du Dispatcher.php. Malheureusement la solution de l'override ne me plaît pas trop dans l'usage "automatique" du principe modulaire de prestashop.

 

C'est pour ça que je me suis dirrigé vers ce hook actionDispatcher qui se traite avant le traitement du controller en cours.

J'ai donc besoin, sauf erreur de ma part :

  1. de récupérer l'instance du dispatcher depuis le hook actionDispatcher dans la classe module
  2. d'en modifier les Dispatch->$default_routes
  3. et certainement de recharger les Dispatch->loadRules() afin que ces dernière modifs soient bien pris dans l'instance en cours du dispatcher pour ensuite traiter le controller

De coup je n'avais pas encore testé ça puisque j'étais resté sur le fait que ce hook actionDispatcher était orphelin. Mais comme la 1.5 prévoit quelque chose de dynamique au niveau des hooks, reste plus qu'à tester.

Seul hic, le dispatcher n'est pas accessible depuis le context.

Est-ce qu'une interaction est possible avec Dispatch::getInstance()->default_routes et aussi Dispatch::getInstance()->loadRules() afin de le traitement dans la classe module ?

Link to comment
Share on other sites

Pour accéder au controller du module en front on peut imaginer cette url :

  • accès principal au controller default : domain.tld/module/momodule/default, cette url est obligé d'être construite ainsi car domain.tld/module/momodule ne fonctionne pas en natif (ni même domain.tld/module/momodule/default/ avec le "/" à la fin)
  • accès secondaire aux autres controllers : domain.tld/module/momodule/moncontrollerlambda

La traduction par rewritecond fonctionne ainsi : domain.tld/?fc=module&module=momodule&controller=default

 

Je souhaite la personnalisation des rewritecond pour finaliser ceci : domain.tld/?fc=module&module=momodule&controller=default&mavariableperso=mavaleur

Ce qui en url rewrite devrait être attendu (pour exemple) : domain.tld/module/momodule/default/mavariable-mavaleur ou domain.tld/module/momodule/default/mavariable/mavaleur; etc ... libre à son créateur ;)

 

Ce que j'arrive à faire fonctionne bien par l'override du dispatcher, en intégrant de nouvelles entrées rewritecond, comme par exemple :

 

public $mes_routes = array(
 'ma-route-default' => array(
  'controller' => null,
  'rule' =>  '{module}-{a}-b{b}{/:controller}',
  'keywords' => array(
   'a'  => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
   'b'    => array('regexp' => '[0-9]+', 'param' => 'b'),
   'module'  => array('regexp' => 'monmodule', 'param' => 'module'),
   'controller' => array('regexp' => 'default', 'param' => 'controller')
  ),
  'params' => array(
   'fc' => 'module'
  )
 )
);

etc., je vais pas toutes les citer.

 

Ceci fonctionne parfaitement depuis l'override. Mais en revanche, je souhaiterai injecter ces $mes_routes directement dans

le Dispatch::getInstance()->default_routes sans passer par l'override de la classe Dispatcher, mais plutôt par respect de l’esprit modulaire, utilise le hook actionDispatcher depuis la classe du module.

Link to comment
Share on other sites

Le but, et le soucis donc, c'est d'avoir quelque chose du style: /monmodule/[id]-[name] , c'est bien ça ? J'avoue, il est possible d'obtenir la première demande mais peut-être pas pour la suite (afin d'amener [id] sur une variable, par exemple.

 

Je vais tester, voir si on ne sait pas récupérer les "paramètres" éventuels.

Link to comment
Share on other sites

L'intention de départ de ma demande ne se situe pas sur la récupération des variables perso, car ça fonctionne déjà depuis des routes persos, cf le bout de code sur $mes_routes

 

Mon intention est d'injecter cette gestion de rewritecond directement dans le traitement du module uniquement, sans passé par un override.

 

Je vais tester ce que j'ai présenté précédemment avec le hook.

Link to comment
Share on other sites

Justement, ma tentative est de ne rien injecter ou d'overrider, là...

 

C'est d'avoir, par exemple en lieu et place de: /annuaire-details?commercant=3851 (qui équivaut en réalité à /index.php?fc=module&module=annuaire&controller=details&commercant=3851)

 

Ceci: /annuaire-details/3851-nom-du-commercant

 

C'est, me semble-t-il, un peu l'objet de ta demande, non ?

  • Like 1
Link to comment
Share on other sites

Oui, ceci en fait partie. Maintenant peut importe la construction de l'url rewrite, le principal est de connaître le module et le controller souhaité et le reste n'est que variables personnalisées supplémentaires.

 

Je viens de faire l'essai depuis le module par le hook actionDispatcher

 

Mais malheureusement la portée de la méthode loadRoutes() est private, on peut donc pas l'utiliser en dehors. Et même en la passant en public, ça ne fonctionne pas dans le module :

 

public $mes_routes = array(
'ma-route-default' => array(
 'controller' => null,
 'rule' =>  '{module}-{a}-b{b}{/:controller}',
 'keywords' => array(
  'a'  => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
  'b'	=> array('regexp' => '[0-9]+', 'param' => 'b'),
  'module'  => array('regexp' => 'monmodule', 'param' => 'module'),
  'controller' => array('regexp' => 'default', 'param' => 'controller')
 ),
 'params' => array(
  'fc' => 'module'
 )
)
);
public function hookActionDispatcher()
{
foreach($this->mes_routes As $Routes)
 array_push(Dispatcher::getInstance()->default_routes, $Routes);

Dispatcher::getInstance()->loadRoutes(); // méthode passée en public pour test
}
public function install()
{
if (
!parent::install()
  || !$this->registerHook('actionDispatcher')


  [...]

 

Sachant que ce traitement équivalent, fonctionne bien dans l'override du Dispatcher.php

Link to comment
Share on other sites

Mais ce que je veux dire, et c'est là que je comprends pas, c'est pourquoi ne pas utiliser ce qui est nativement possible comme je le décris au-dessus...

 

Parce que, justement, le truc te dit: voici le module, voici le controller. Et tu dois même rien écrire de plus, c'est juste un ajout de URL's (dans l'onglet SEO & URL's).

 

Un truc m'échappe ?!

Link to comment
Share on other sites

Un truc m'échappe ?!

 

Bah en gros, au départ je suis partie de ton constat. Mais j'ai pas mal avancé dans ma quête (dois-je faire demi-tour ?), et utiliser le rewritecond en natif revient à utiliser ni plus ni moins celui qui est connu du noyau pour le controller de module : module/{module}{/:controller}

 

Dans tous les cas, nous sommes obligé de passer par de nouvelles rewritecond.

D'où mon état d'avancement actuel, et la méthode de l'override (qui n'est pas une finalité pour moi, je souhaite du 100% modulaire)

Link to comment
Share on other sites

Mais non... on ne passe pas par module/{...}/{...}

 

Nativement, on peut dire que /toto/ renvoie vers le controller "manger" du module "pomme", par exemple...

 

C'est là, le truc, que je comprends pas je pense... C'est, si comme je le comprends, on s'en fout un peu que /toto?parqui=filleduconcierge soit ajouté à /toto/ c'est, pourquoi faire tout ça ?

Link to comment
Share on other sites

Peu importe si on passe par /toto/ ou /tata/ ou /module/monmodule/default/toto

toto n'est pas connu à la base.

 

On peut souhaiter avoir à faire en rewrite ceci :

  • /?fc=module&module=monmodule&controller=default&variable=valeur
  • /?fc=module&module=monmodule&controller=default&id=123
  • /?fc=module&module=monmodule&controller=default&tata=1&var=truc

Dans mon avancement, j'en conclu que pour créer les rewrite de ces url, on doit passer par l'ajout de nouvelles routes dynamiques dans la classe dispatch.

 

L'utilisation des entrées SEO & URLs personnalisées depuis le tab AdminMeta n'est valable que lorsque l'ont connaît l'url comme "fixe" et non dynamique.

Link to comment
Share on other sites

Donc, tu souhaites bien avoir quelque chose comme:

/annuaire-details/3851-nom-du-commercant

 

Qui serait en réalité équivalent à:

/annuaire-details?commercant=3851

 

Qui lui même serait en réalité:

/index.php?fc=module&module=annuaire&controller=details&commercant=3851

 

C'est bien cela ?

 

Il s'agit donc du premier niveau (3851-nom) qui n'est actuellement pas possible de faire, que tu souhaites implémenter. On est d'accord sur ce point ?

  • Like 1
Link to comment
Share on other sites

Exactement cela. Si on part du principe où 3851 est un {id} attendant toutes les valeurs de [0-9]+

et que nom-du-commercant est un texte supplémentaire {nom} attendant toutes les valeurs de [_a-zA-Z0-9-\pL]*

 

Et on peut partir sur ton exemple de /annuaire-details/3851-nom-du-commercant qui donnerait en rewritecond : {module}-{controller}/{id}{-:nom}

 

Ceci donnerai comme route à traiter dans le dispatcher :

public $mes_routes = array(
'maroute' => array(
 'controller' => null,
 'rule' =>  '{module}-{controller}/{id}{-:nom}',
 'keywords' => array(
  'nom'  => array('regexp' => '[_a-zA-Z0-9-\pL]*'),
  'id'	=> array('regexp' => '[0-9]+', 'param' => 'id'),
  'module'  => array('regexp' => 'annuaire', 'param' => 'module'),
  'controller' => array('regexp' => 'details', 'param' => 'controller')
 ),
 'params' => array(
  'fc' => 'module'
 )
)
);

Link to comment
Share on other sites

Et donc, à ma connaissance, la technique des routes personnalisés semble exister, mais n'est pas finalisée à mon sens.

En effet, si l'on parcours la classe Dispatcher.php, on observe cette portion :

 

/**
 * Load default routes group by languages
 */
protected function loadRoutes()
{
[...]
  // Load custom routes
  foreach ($this->default_routes as $route_id => $route_data) // parcours uniquement dans le contenu des routes déjà connus
if ($custom_route = Configuration::get('PS_ROUTE_'.$route_id)) // si le route est connu dans une config "perso"
 foreach (Language::getLanguages() as $lang) // alors pour toutes les langues
  $this->addRoute( // ajoute le route de la config "perso", [PLUS D'INFOS]
   $route_id,
   $custom_route,
   $route_data['controller'],
   $lang['id_lang'],
   $route_data['keywords'],
   isset($route_data['params']) ? $route_data['params'] : array()
  );
 }
}

[PLUS D'INFOS] : ça me semble bizarre de ne pas avoir été jusqu'au bout sur l'injection des données persos, car dans cet algo, on ne prend que le $custom_route, et dans tous les cas il faut créer un array d'une route personnalisée accessible depuis le Dispatcher.php . Soit cet algo est inutile, soit il n'est pas achevé.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...