Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 09-09-2015 17:32:39

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

[Résolu]Préfixer toutes les routes

Bonjour

J'aimerais préfixé toutes mes routes. Au lieu d'avoir : monsite.fr/maroute  --> avoir monsite.fr/prefix/maroute

Pour l'instance dans mes routes j'ajoute toujours le préfixe--->
route => /prefix/maroute

Y a t'il un moyen de faire cela + globalement ?

Merci

Dernière modification par Nirzol (03-11-2015 10:40:01)

Hors ligne

 

#2 10-09-2015 10:12:18

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Préfixer toutes les routes

Salut oui tu fais une route parente qui contient se préfix et toutes tes autres routes sont des routes filles (child_routes) de celle-ci.

Hors ligne

 

#3 15-09-2015 09:29:44

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: [Résolu]Préfixer toutes les routes

Bonjour,

Est-ce un préfixe pour un module seulement ou pour toute ton application ? J'ai déjà eu une demande similaire et voici une solution qui peut marcher :

Il te faut créer un nouveau module, qui aura deux listeners, un qui sera lancé a ton event route, et l'autre avant une 404.

Dans ton module.php

Code:

[lang=php]
// Module.php
    public function onBootstrap(EventInterface $event)
    {
        $eventManager        = $event->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();

        // Trigger after matched route & before authorization modules.
        $eventManager->attach(
            MvcEvent::EVENT_ROUTE,
            array($this, 'setBaseUrl'),
            -100
        );

        // Trigger before 404s are rendered.
        $eventManager->attach(
            MvcEvent::EVENT_RENDER,
            array($this, 'setBaseUrl'),
            -1000
        );

        $moduleRouteListener->attach($eventManager);
    }

Ensuite comme ce code le montre, tu as une méthode setBaseUrl a créer (a mettre aussi dans le Module.php) :

Code:

[lang=php]
    public function setBaseUrl(MvcEvent $e)
    {
        $request = $e->getRequest();
        $baseUrl = $e->getApplication()->getServiceManager()->get('ReverseProxy\ModuleOptions');
        if (php_sapi_name() !== 'cli' && !empty($baseUrl) && $request->getServer('HTTP_X_FORWARDED_FOR', false)) {
            $router = $e->getApplication()->getServiceManager()->get('Router');
            $router->setBaseUrl($baseUrl->getPrefixUrl());
            $request->setBaseUrl($baseUrl->getPrefixUrl());
        }
    }

ReverseProxy\ModuleOptions est configuré comme suit :

Code:

[lang=php]
// module.config.php
return array(
    'service_manager' => array(
        'factories' => array(
            'ReverseProxy\ModuleOptions' => 'ReverseProxy\Factory\ModuleOptionsFactory',
        ),
    ),
    'config_prefix' => array(
        'prefix_url' => '/v2/',
    ),
);

Note que config_prefix est le préfix de tes routes, géré dans la config donc de ce module (et uniquement ici).

Ma factory :

Code:

[lang=php]

class ModuleOptionsFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $options = $serviceLocator->get('Config')['config_prefix'];
        return new ModuleOptions($options);
    }
}

et ma classe ModuleOptions :

Code:

[lang=php]
class ModuleOptions extends AbstractOptions
{
    private $prefixUrl;

    public function setPrefixUrl($prefixUrl)
    {
        $this->prefixUrl = (string) $prefixUrl;
    }

    public function getPrefixUrl()
    {
        return $this->prefixUrl;
    }
}

Si tu n'est pas a l'aise avec les options sache que le constructeur de cette classe n'a pas besoin d'être déclaré, car le Constructeur de la classe AbstractOptions est comme suit :

Code:

[lang=php]
    public function __construct($options = null)
    {
        if (null !== $options) {
            $this->setFromArray($options);
        }
    }

Donc ta factory a juste besoin de récupérer tes options (ton préfixe) et tes accesseurs pourrons y accéder sans problèmes.

De la, tous le module est fini, et toutes tes routes avec le préfixe marcheront.
Ce module n'est pas parfait, les routes sans le préfixe continuerons d’être disponible, mais si tu as des optimisations à proposer je suis preneur smile

Edit: Je t'ai livré un module ou les nom des méthodes et des clés de config sont personnelles, libre a toi d'utiliser tes propres mot wink pour coller a ton besoin.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#4 15-09-2015 10:06:57

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

Re: [Résolu]Préfixer toutes les routes

Bonjour
Désolé pour le retard de la réponse . Pas mal de boulot en ce moment.
Merci de vos réponses.

@Orkin, j'avais pensé à cela, de refaire tout ma branche de route pour les passer en child.
Mais la question que je me suis posé après c'est concernant un module. Dans ce cas il faudrait aussi que je réécrive les routes des modules dans mon appli?

@JGreco merci. J'avais vu quelques articles qui parlaient de cela.
Mais personnellement je trouve cela assez lourd juste pour ajouter un préfixe hmm .
Je pensais que Zend y avait pensé quand même soit avec une option du routeur ou un $router->setPrefix... un truc dans le genre.
Mais s'il n'y a pas d'autre alternative je vais faire suivant ton exemple. merci en tout cas !!!


En fait j'en arrive à la car je développe une appli angularjs en front et zf2 en back mode rest.
Du coup, j'ai modifier mon VHOST pour que toutes les requêtes à partir de la racine renvoie sur index.html (pour lancer les routines d'angularjs)
Sauf quand il trouve "/api" il me renvoie sur index.php/api/etc... Mais dans ce cas il faut je préfixe mes routes avec /api. Et ainsi angularjs lui peut appeler mes contrôler rest via ce slug ~/api/moncontrollerRest

Et dans le même cas les modules annexes que j'utilises ou que j'ai créé je dois aussi les préfixé ?...

Voila une peu la petite histoire de ma question smile

Dernière modification par Nirzol (15-09-2015 10:09:39)

Hors ligne

 

#5 15-09-2015 10:43:55

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Préfixer toutes les routes

Hello, alors non tu le met dans ton module principale et ensuite dans tes autres modules tu rajoutes juste le nom de la route parente comme ceci :

Code:

[lang=php]
'parent' => array('child_routes' => array( xxxxxx ));

En gros dans ton module principale tu vas définir correctement ta route parent avec son url etc ... Et dans tous les autres tu lui indiques juste que les nouvelles routes sont enfant de celle-ci et il fera le merge tout seul.

Pour ton cas tu as une solution très simple. Ton application AngularJS tu la fais pointer sur ton domaine principal : www.mondomaine.com
Et ton backend sur www.api.mondomaine.com de cette manière les 2 sont vraiment indépendant puisqu'au final ton application AngularJS c'est une application à part ça n'a rien à faire dans le code de ton backend c'est vraiment 2 projets distinct.

Ensuite tu vas te retrouver confronté à un problème : les requêtes cross domain (CORS) puisque pour que ton application AngularJS puisse interroger ton backend elle va devoir faire des requêtes sur www.api.mondomaine.com qui n'est pas le même que www.mondomaine.com (un sous domaine ou un passage de http à https pose des problèmes de CORS). Donc tu as 2 solutions soit dans ton backend tu le gères en rajoutant les headers qui vont bien (je te laisse chercher sur internet) et en gros c'est ton navigateur qui fera pour toi une requête de type options à ton backend pour savoir s'il a le droit ou non. C'est un peu chiant comme solution mais ça fonctionne.
Je trouve que la deuxième solution est plus propre. La voici :
On va partir du principe que tu as un endpoint sur ton backend qui est http://api.mondomaine.com/users/1 qui te permet de récupérer le user avec l'id 1.
Côté AngularJS ce que tu vas faire c'est une requête du genre http://mondomaine.com/api/users/1. Logiquement dans ton application AngularJS tu n'es pas censé avoir de route avec le mot clé api. Donc dans ton VHOST ce que tu vas faire c'est intercepter toutes les requêtes avec /api et rediriger via le mode proxy (pour apache pour nginx faut que tu regardes l'équivalent) vers http://api.mondomaine.com/users/1. En gros tu interceptes à partir de /api tu le retire de l'url et tu gardes ce qu'il y a après.
Sur apache ça donne ça :

Code:

ProxyPass /api http://api.mondomaine.com
ProxyPassReverse /api http://api.mondomaine.com

Avec cette solution tu n'as pas de problème de CORS puisque c'est apache qui fait la requête vers api.mondomaine.com et c'est lui qui récupère la réponse et qui la forward derrière à ton application AngularJS.

C'est la méthode que j'utilise et ça fonctionne très bien smile.

Hors ligne

 

#6 15-09-2015 12:11:12

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

Re: [Résolu]Préfixer toutes les routes

@orkin Merci !
C'est la config que j'ai en local, ou je suis TRES libre de faire des vhost et des sous domaine etc... big_smile
Avec les header acceptant les GET PUT etc...
J'avais pas penser au ProxyPass. Je le retiens ça !

Par contre, sur le serveur de prod c'est autre chose . On a un domaine (qui est deja un sous domaine) et rien de plus on doit se debrouiller avec des rewriteRules que l'admin réseaux retransforme en rewriterule nginx.
Bref un peu complexe.... Je fais avec ...

Mais ton idée est excellente.

Sinon pour la route je vais tester avec parent !

Merci

Hors ligne

 

#7 22-09-2015 18:39:23

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

Re: [Résolu]Préfixer toutes les routes

Bonjour

En fait le parent ca va rendre mon module bcp trop dépendant de la route.

Alors j'ai regardé un peu , si dans le onBoostrap de mon module tiers je construisais ma route pour ensuite récupérer ma route dans le fichier config.? Ca le fait ou pas ? en terme de best practice.
Comme ca mon module reste toujours indépendant, et celui qui l'utilise n'aura cas modifier le fichier config si la route par default ne lui plait pas?

Par exemple : un truc dans le genre

Code:

[lang=php]
$config = $e->getApplication()->getServiceManager()->get('Config');
        $router = $e->getRouter();
        $router->addRoutes(array(
            'login' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route' => $config['my_config']['login_route'],
                    'defaults' => array(
                        '__NAMESPACE__' => 'My\Controller',
                        'controller' => 'Login',
                        'action' => 'login',
                    ),
                ),
            ),
            'logout' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route' => $config['my_config']['logout_route'],
                    'defaults' => array(
                        '__NAMESPACE__' => 'My\Controller',
                        'controller' => 'Logout',
                        'action' => 'index',
                    ),
                ),
            )));

Qu'en pensez vous ? Est ce bien de créer sa route ici ?

Dernière modification par Nirzol (22-09-2015 18:41:49)

Hors ligne

 

#8 23-09-2015 10:19:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Préfixer toutes les routes

Salut j'ai pas vraiment compris ce que tu voulais faire :s

Hors ligne

 

#9 23-09-2015 12:38:29

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

Re: [Résolu]Préfixer toutes les routes

Ahah désolé
Après relecture je ne suis pas très clair > _ <

Dans le fichier module.php on a :

Code:

[lang=php]
public function onBootstrap(MvcEvent $e) {...}

Si dans cette fonction je déclare ma route comme dis dans le message précédent. et au lieu d'avoir en dure ma route genre :

Code:

[lang=php]
...
'route' => 'api/maroute',
...

J'utilise le fichier config :

Code:

[lang=php]
...
$config = $e->getApplication()->getServiceManager()->get('Config');
...

Dans lequel j'aurais stocker 'api/maroute', je me retrouve avec :

Code:

[lang=php]
...
'route' => $config['my_config']['login_route'],
...

Je construit ma route dans la fonction onBoostrapp du fichier module.php.

Est ce une bonne practice? ou c'est pas trop top de faire ces routes ici ?

Hors ligne

 

#10 23-09-2015 15:29:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: [Résolu]Préfixer toutes les routes

Non ça me semble un peu dégueulasse.

Hors ligne

 

#11 24-09-2015 11:04:26

Nirzol
Membre
Date d'inscription: 11-01-2013
Messages: 65

Re: [Résolu]Préfixer toutes les routes

Ahah oui je me disais aussi big_smile

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages