2012-03-20 108 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