2 votes

CakePHP Routage de sous-domaines & divers

Contexte : Construire une application web (comme introduction à CakePHP) qui permet aux utilisateurs de gérer un salon. Un salon est composé d'un blog, de contacts, d'un calendrier, etc. Chaque salon est associé à un sous-domaine (ainsi jcotton.lounger.local vous amènerait à mon salon). La racine du site, utilisée pour créer de nouveaux salons, enregistrer des utilisateurs, etc. est hébergée sur lounger.local. J'utilise Cake 2.0.

Questions :

  1. Je voulais pouvoir séparer les actions et les vues associées au site racine (lounger.local) des salons individuels (sous-domaines de lounger.local). Après de nombreuses recherches, j'ai opté pour la solution suivante. J'ai créé une route préfixe "lounge" et j'ai ajouté le code suivant dans routes.php. Les actions (et les vues) associées à un salon contiennent toutes le préfixe lounge (ex : lounge_index()). Comment gérer cela ?

         if(preg_match('/^([^.]+)\.lounger\.local$/',env("HTTP_HOST"),$matches)){
               $prefix = "lounge";
               Router::connect('/', array('controller' => 'loungememberships','action' => 'index', 'prefix' => $prefix, $prefix => true));
               /* Not currently using plugins
               Router::connect("/:plugin/:controller", array('action' => 'index', 'prefix' => $prefix, $prefix => true));
               Router::connect("/:plugin/:controller/:action/*", array('prefix' => $prefix, $prefix => true));
               */
               Router::connect("/:controller", array('action' => 'index', 'prefix' => $prefix, $prefix => true));
               Router::connect("/:controller/:action/*", array('prefix' => $prefix, $prefix => true));
               unset($prefix);
          }
  2. Chaque fois qu'un utilisateur effectue une action dans un salon, comme poster un commentaire dans le blog, ajouter un contact, etc, il est nécessaire de rechercher le lounge_id (basé sur le sous-domaine) ; ceci est nécessaire pour vérifier que l'utilisateur est autorisé à effectuer cette action et pour associer les données correspondantes avec le bon salon. J'ai implémenté cela via la fonction beforeFilter dans AppController. Chaque fois qu'une requête est reçue avec un sous-domaine, une recherche est effectuée et le lounge_id est écrit dans une variable de session. Chaque contrôleur charge ensuite CakeSession et lit le lounge_id correspondant. Est-ce mieux que d'appeler ClassRegistry::Init('Lounge') et de faire la recherche dans chaque contrôleur ? Existe-t-il une meilleure solution ?

Merci d'avance pour votre aide

5voto

Predominant Points 1385

La façon dont j'ai abordé ce problème a été avec une route personnalisée, et quelques astuces avec la configuration de la route similaire à votre exemple.

Tout d'abord, j'ai un "Master domain" qui est redirigé et utilisé comme domaine principal pour le site multi-tenant. Je stocke également une action par défaut que je veux qu'ils prennent. Je les stocke dans des variables de configuration :

Configure::write('Domain.Master', 'mastersite.local');
Configure::write('Domain.DefaultRoute', array('controller' => 'sites', 'action' => 'add'));

Ensuite, j'ai créé un DomainRoute classe de route dans /Lib/Route/DomainRoute.php :

<?php
App::uses('CakeRoute', 'Routing/Route');
App::uses('CakeResponse', 'Network');
App::uses('Cause', 'Model');

/**
 * Domain Route class will ensure a domain has been setup before allowing
 * users to continue on routes for that domain. Instead, it redirects them
 * to a default route if the domain name is not in the system, allowing
 * creation of accounts, or whatever.
 *
 * @package default
 * @author Graham Weldon (http://grahamweldon.com)
 */
class DomainRoute extends CakeRoute {

/**
 * A CakeResponse object
 *
 * @var CakeResponse
 */
    public $response = null;

/**
 * Flag for disabling exit() when this route parses a url.
 *
 * @var boolean
 */
    public $stop = true;

/**
 * Parses a string url into an array. Parsed urls will result in an automatic
 * redirection
 *
 * @param string $url The url to parse
 * @return boolean False on failure
 */
    public function parse($url) {
        $params = parent::parse($url);
        if ($params === false) {
            return false;
        }

        $domain = env('HTTP_HOST');
        $masterDomain = Configure::read('Domain.Master');

        if ($domain !== $masterDomain) {
            $defaultRoute = Configure::read('Domain.DefaultRoute');
            $Cause = new Cause();
            if (!($Cause->domainExists($domain)) && $params != $defaultRoute) {
                if (!$this->response) {
                    $this->response = new CakeResponse();
                }

                $status = 307;
                $redirect = $defaultRoute;
                $this->response->header(array('Location' => Router::url($redirect, true)));
                $this->response->statusCode($status);
                $this->response->send();
                $this->_stop();
            }
            $params['domain'] = $domain;
        }

        return $params;
    }

/**
 * Stop execution of the current script.  Wraps exit() making
 * testing easier.
 *
 * @param integer|string $status see http://php.net/exit for values
 * @return void
 */ 
    protected function _stop($code = 0) {
        if ($this->stop) {
            exit($code);
        }
    }

}

Cette classe de route personnalisée est utilisée dans le cadre de la /Config/routes.php pour configurer le multi-tenant.

if (env('HTTP_HOST') === Configure::read('Domain.Master')) {
    // Master domain shows the home page.
    $rootRoute = array('controller' => 'pages', 'action' => 'display', 'home');
} else {
    // Subdomains show  the cause view page.
    $rootRoute = array('controller' => 'causes', 'action' => 'view', env('HTTP_HOST'));
}
Router::connect('/', $rootRoute, array('routeClass' => 'DomainRoute'));

En inspectant le routeur personnalisé, vous verrez que je récupère le domaine actuel auquel on accède et que je l'ajoute à la balise $params de la gamme.

Bien que cela ne permette pas d'obtenir directement ce que vous recherchez, des modifications mineures vous mettront sur la bonne voie. Il n'y a pas beaucoup d'informations sur les itinéraires personnalisés, mais voici la liste de ces itinéraires. Lien vers la documentation CakePHP pour les classes d'itinéraires personnalisés.

J'espère que cela vous aidera !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X