Какой самый элегантный способ обработки пользовательских пользовательских доменов? - PullRequest
5 голосов
/ 20 января 2012

На моем сайте пользователи имеют публичные профили, к которым можно получить доступ через http://mysite.com/vanity_url. Я хочу разрешить пользователям указывать свои домены на странице своего профиля на моем сайте. Точно так же, как в Bandcamp .

Моя 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, чтобы указать голый домен на другой. Главный вопрос все еще открыт.

Ответы [ 2 ]

1 голос
/ 13 июля 2012

Полагаю, лучшего способа нет: P

1 голос
/ 28 марта 2012

Я сделал нечто подобное, используя торт 1.3 год назад

В этом решении есть 4 основных шага:

  1. Имейте модель Домена и данные о доменах, которые записывают все возможные пользовательскиедомены и представления для ваших пользователей, чтобы ввести свои собственные домены
  2. создать код проверки домена в beforeFilter в AppController и сохранить данные пользователя в сеансе
  3. действие контроллера, отвечающее за просмотр общедоступного профиля, должноссылаются на те же пользовательские данные, которые сохраняются в сеансе
  4. ваши пользователи должны правильно настроить записи CNAME и A со своими регистраторами доменов

Шаг 1 Модель домена и данные

Что я сделал, так это то, что у меня была таблица, называемая доменами

. Каждый домен содержит веб-адрес, который, как я предполагал, был просто http: //....

Домен принадлежит пользователю

Пользователь имеет много доменов

domains
==========
id    web_address    user_id    main

основной - это tinyint, который указывает, является ли это основным URL-адресом, который будет использоваться после насУ него есть много доменов.

, поэтому пользователь должен создать новую запись или более для домена.

Шаг 2 Код в beforeFilter AppController, чтобы выяснить, какой общедоступный профильdisplay Далее ваш код должен иметь возможность извлекать идентификатор пользователя на основе URL-адреса, отправляемого при каждом запросе http.

Пользователь с этого момента ссылается на пользователя, чей общедоступный профильрассматривается.НЕ путайте это с зарегистрированным пользователем, если он у вас есть.

Я предлагаю сделать это в вашем beforeFilter из AppController.

Что-то вроде этого

  $currentUser = $this->User->getByDomain(FULL_BASE_URL);
  $this->Session->write('CurrentUser', $currentUser);

Код для модели getByDomain for User также является для вас упражнением.Должно быть достаточно легко, учитывая, что я объяснил схему для доменов

Возможно, вам придется проверить текущее значение UserUser внутри ваших данных Session перед записью currentUser, потому что вы не хотите писать данные Session все время, особенно когдапосетитель посещает одну и ту же веб-страницу снова и снова.

Вам может потребоваться изменить приведенный выше фрагмент кода на что-то вроде этого:

  $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 Введите код beforeFilter в AppController, чтобы выяснить, какой общедоступный профиль отображать Вы будете использовать данные CurrentUser, сохраненные в сеансе, для определения общедоступной страницы пользователя, которую вы хотите отобразить.

Я оставляю это как упражнение для вас, чтобы выяснить в вашем UsersController под видом действия

Шаг 4, ваши пользователи должны ввести следующее в регистраторах своих доменов Тогда ваши пользователи должныпойти к своим регистраторам доменов и сделать то же самое, что иПользователи BandCamp в часто задаваемых вопросах, с которыми вы связались.

  • Пользовательский поддомен "www" должен указывать с помощью CNAME на example.Lucho.com

  • User'sКорневой домен (без www) должен иметь запись A, указывающую на IP-адрес вашего сервера, т.е. где ваш Lucho.com находится в

  • Пользователь должен добавить обе эти страницы управления доменами.как объяснено ранее на вершине.Для полного обновления домена может потребоваться до 48 часов.

...