在我的网站上,用户可以通过http://mysite.com/vanity_url
访问公开个人资料。我想允许用户将自己的域指向我网站上的个人资料页面。 Just like Bandcamp does。
我的Profile
模型有以下两个字段来处理:vanity_url
,这是普通的用户名字段类型;以及一个新的custom_domain
,这是他们自己的域名,例如example.com
。
这是我到目前为止所做的,但我担心它可能不是最优雅,最安全,最有效的方式。
首先,我确保Apache的DocumentRoot
设置为我应用的webroot
目录,因此我可以告诉用户将他们的DNS指向我网站的IP。
现在,我的routes.php
上的路由规则就是这样的:
if (preg_match('/mysite\.com\.?$/', $_SERVER['SERVER_NAME'])){
// Normal routes when visitors go to my domain
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/**', array('controller' => 'pages', 'action' => 'display'));
// Move all other actions to a separate '/app/' area
Router::connect('/app/:controller/:action/**');
Router::connect('/app/:controller/**');
// Handle profile URLs
Router::connect('/:profile/**',
array('controller' => 'profiles', 'action' => 'view'),
array('pass' => array('profile'), 'profile' => '[0-9a-zA-Z\-\_]+')
);
}
else{
// If visitors come via a URL different to mysite.com, I let
// the ProfilesController deal with it passing the current SERVER_NAME
// as a param to the 'view' action
Router::connect('/', array(
'controller' => 'profiles',
'action' => 'view',
$_SERVER['SERVER_NAME'], // 'url' param
true // 'customDomain' param
));
Router::redirect('/*', 'http://mysite.com');
}
这就是view
上的ProfilesController
操作的样子:
public function view($url = null, $customDomain = false) {
if ($url){
// Find the profile by its vanity_url or its custom_domain
$findOptions = array(
'conditions' => $customDomain?
array('custom_domain' => $url) :
array('vanity_url' => $url)
);
if ($profile = $this->Profile->find('first', $findOptions)) {
$this->set('profile', $profile);
}
}
else throw new NotFoundException(__('Invalid profile'));
}
这种方法可能会遇到什么问题?
此外,有没有人知道为什么Bandcamp会要求用户创建 CNAME 而不是 A 记录来设置子域名?我错过了我应该考虑的事情吗?
编辑有人帮我弄清楚最后一点:似乎你不能轻易使用CNAME记录将裸域指向另一个。主要问题仍然是开放的。
答案 0 :(得分:1)
我在一年前使用蛋糕1.3做了类似的事情
此解决方案有4个主要步骤:
步骤1域模型和数据表
我做的是我有一个名为域
的表每个域都包含我认为只是http:// ....
的网址域名属于用户
用户拥有多个域名
domains
==========
id web_address user_id main
main是一个tinyint,表示这是否是因为User hasMany Domain而使用的主要URL。
所以会发生什么是用户需要为Domain创建一个或多个新记录。
步骤2 AppController的beforeFilter中的代码,以确定要显示的公开个人资料 接下来,您的代码需要能够根据每个http请求提交的URL检索用户ID。
此时用户指的是查看其公开个人资料的用户。如果你有一个,请不要将它与loggedIn用户混淆。
我建议您在之前的AppController过滤器中执行此操作。
像这样的东西
$currentUser = $this->User->getByDomain(FULL_BASE_URL);
$this->Session->write('CurrentUser', $currentUser);
用户模型的getByDomain代码也是一项练习。鉴于我已经解释了域的架构
,应该很容易在编写currentUser之前,您可能需要检查Session数据中的currentUser,因为您不希望一直写会话数据,尤其是当访问者一次又一次访问同一网页时。
您可能需要将上面的代码段更改为以下内容:
$currentUser = $this->Session->read('CurrentUser');
if(empty($currentUser) OR (!$this->checkUrlAgainstDomain(FULL_BASE_URL, $currentUser['Domain']['domain']))) {
$currentUser = $this->User->getByDomain(FULL_BASE_URL);
$this->Session->write('CurrentUser', $currentUser);
}
函数checkUrlAgainstDomain再次为你练习。
步骤3 AppController的beforeFilter中的代码,以确定要显示的公开个人资料 您将使用会话中保存的CurrentUser数据来确定要显示的用户的公共页面。
我将此作为练习留给您在行动视图下的UsersController中找出
第4步,您的用户需要在其域名注册商中输入以下内容 然后,您的用户需要访问他们的域名注册商,并在您链接到的常见问题解答中执行与BandCamp用户类似的操作。
用户的“www”子域名应使用CNAME指向example.Lucho.com
用户的根域(没有www)应该有一个指向服务器IP地址的A记录,即Lucho.com所在的位置
用户必须同时添加这两个域管理页面,如前面所述。域名最多可能需要48小时才能完全更新。
答案 1 :(得分:1)
我想没有更好的方法:P