2012-03-20 107 views
2

背景:构建一个允许用户管理休息室的Web应用程序(作为CakePHP的简介)。休息室由博客,联系人,日历等组成。每个休息室都与一个子域相关联(所以jcotton.lounger.local会带你到我的休息室)。用于创建新休息室,注册用户等的网站的根目录位于lounger.local上。我正在使用Cake 2.0。CakePHP子域路由和其他

问题:

  1. 我希望能够分离与独立休息室(的lounger.local子域)根网站(lounger.local)相关联的操作和看法。经过大量的研究,我决定采用以下soln。我设置了一个前缀路由“休息室”,并在routes.php中添加了以下代码。与休息室相关的操作(和视图)都包含前缀休息室(例如:lounge_index())。你将如何处理?

     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. 用户每次执行休息室诸如张贴博客内的评论,添加联系人等内的动作,有必要来查找lounge_id(基于子域);这对验证用户是否有权执行该操作并将相应的数据与正确的休息室相关联是必要的。我通过AppController中的beforeFilter函数实现了这个功能。每次接收到子域的请求时,都会执行搜索,并将lounge_id写入会话变量。然后每个控制器加载CakeSession并读取相应的lounge_id。这比调用ClassRegistry :: Init('Lounge')并在每个控制器中执行查找更好吗?有更好的soln吗?

在此先感谢您的帮助

+0

这感觉就像是一个滥用框架。 – 2012-08-02 14:22:03

回答

5

我走近这是一个自定义路由的方式,而一些挂羊头卖狗肉与路由的配置相似,你的榜样。

首先,我有一个“主域”,它被重定向到并用作多租户站点的主域。我还存储了我希望他们采取的默认操作。我存储在这些配置变量:

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

接下来,我在/Lib/Route/DomainRoute.php创建DomainRoute路由类:

<?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); 
     } 
    } 

} 

此自定义路由类是/Config/routes.php文件来设置多租户内使用。

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')); 

在自定义路由器的检查,你会看到,我拉着当前域名被访问,并补充说,到$params阵列。

虽然这并不能直接达到您的要求,但稍加修改会使您的要求走上正确的轨道。关于自定义路线的信息不多,但这里是自定义路线类别的CakePHP documentation link

我希望有帮助!

+0

对于那些想知道为什么它不起作用的用户,自定义路由路径已经改为'app/Lib/Routing/Route',并且你需要做一个明确的include App :: uses('DomainRoute','路由/路由');'在执行Router :: connect()之前。按照文章中的文档链接了解更多信息。 – 2013-09-02 02:37:28