+7 495 008 8452 пн.-пт. 10:00 – 17:00
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


Разные города, но один сайт, сайт с разделениями по городам

Необходимо было разработать федеральный сайт для фирмы имеющей офисы в разных городах. Для каждого города должны были быть свои новости, статьи, и тд. Не имея опыта в подобных задачах я обратился на форум. http://dev.1c-bitrix.ru/community/for...sage198298

Наиболее подходящим решением задачи мне понравилось предложение Дениса Клокова :
На одном из проектов было. Города - эл-ы инфоблоков, довольно удобно туда вбивать контакты, координаты на картах, счетчики статистики и т.д.

Всякие новости, модели товара и т.п имеют свойство типа "привязка к эл-м ИБ" по которому и фильтруем динамический контент, остальные считаются общими для всего сайта вне зависимости от города.
Только я решил сделать города не элементами, а разделами инфоблока "города", но это не важно.
Каждый раздел инфоблока "города" должен обязательно иметь символьный код, который и будет являться доменом 3го уровня.

Встал вопрос какую организацию адресов выбрать:
  1. по папкам вида mysite.ru/city_name/bla-bla/
  2. мультидоменную вида city_name.mysite.ru/bla-bla/
Мне больше по душе оказался второй вариант, скорее всего больше из-за эстетичской точки зрения, а не желанием возиться с mod_rewrite) Какой вариант выгодней для сео я не знаю. Если знаете — напишите пожалуйтса в комментариях.

Еще одно требование - пользователь при перезаходе на сайт должен попадать сразу на тот город, который он выбрал в прошлый раз.

Итак, первое что нужно это настройка днс служб. Чтобы днсы адресовали http запрос с адресом типа city_name.mysite.ru веб-серверу, нужно, чтобы присутствовала запись А -типа с названием каждого возможного города. То есть мне можно было добавлять для каждого нового города записи moscow, samara etc. но у администратора сайта должна была быть возможность добавить новый город всего лишь добавлением раздела инфоблока в админке. Поэтому, чтобы любые запросы, где домен второго уровня - "mysite.ru" передавались веб серверу, нужно включить в днс записи такую строку:

*          IN     A    IPадресСервера

Аналогично с веб-сервером. В настройках virtualhost апача я включил такие строки:

ServerName mysite.ru
ServerAlias *.mysite.ru
.htaccess мы не трогаем, никаких танцов с бубнами вокруг mod_rewrite нам не нужно.

Далее осталась программная часть. Думаю тут уже ничего объяснять не нужно, все видно по комментариям. Привожу код из /bitrix/php_interface/ID сайта/init.php

<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
<?php
   // посмотрим какой город был выбран этим юзером в прошлый раз
   $sUserCity = $APPLICATION->get_cookie('USER_CITY');
   // установим глобальную переменную cur_city = код города (из сабдомена) 
   $GLOBALS['sCurCity'] = preg_replace('/^(?:([^\.]+)\.)?mysite\.ru$/', '\1', $_SERVER['SERVER_NAME']);
   // символьные коды возможных городов и полные описания возможных городов
   $arCityCodes = $arCities = array();
   
   // кэшируем подключение модуля инфоблоков и выборку возможных городов
   $obCache = new CPHPCache; 
   $iLifeTime = 60*60*3;
   $sCacheID = SITE_ID.'City';
   // если кеш есть и он ещё не истек, то
   if($obCache->InitCache($iLifeTime, $sCacheID, '/')) {
      // получаем закешированные переменные
      $arVars = $obCache->GetVars();
      $arCityCodes = $arVars['arCityCodes'];
      $arCities = $arVars['arCities'];
   }
   else {
      // иначе обращаемся к базе
      // получим список всех возможных городов на сайте
      if (CModule::IncludeModule('iblock')) {
         // без этой переменной ругается на вызов метода _CIBlockElement::GetGroups()
         global $USER; 
         $USER = new CUser;
         // узнаем все города на сайте с непустым кодом
         $arFilter = Array('IBLOCK_ID'=>1, 'GLOBAL_ACTIVE'=>'Y', '!code'=>false);
         $dbCities = CIBlockSection::GetList(array('SORT'=>'ASC'), $arFilter);
         // заполняем ими массивы $arCityCodes и $arCities
         while ($arCity = $dbCities->GetNext(false,false)) {
            $arCityCodes[] = $arCity['CODE'];
            $arCities[] = $arCity;
         }
         if (empty($arCityCodes)) ShowError('Нет городов');
      } else ShowError('Не получилось подключить модуль «iblock»');
   }
   if($obCache->StartDataCache()) $obCache->EndDataCache(array('arCityCodes' => $arCityCodes, 'arCities' => $arCities));
   // конец кэширования
   
   foreach ($arCities as $arCity) {
      if ($arCity['CODE'] == $sCurCity) {
         // запишем название города (позже пригодится где-нибудь)
         $GLOBALS['sCurCityName'] = $arCity['NAME'];
         // это самое главное, id нам нужен будет для фильтров
         $GLOBALS['iCurCityID'] = $arCity['ID'];
      }
   }
   // если запрошен сайт с пустым или неверным сабдоменом
   if (!in_array($sCurCity,$arCityCodes)) {
      // то если существует валидная кука
      if (in_array($sUserCity,$arCityCodes)) {
         // редирект на город записанный в куках
         header("Location: http://{$sUserCity}.mysite.ru/");
      } else {
         // если кука не валидная или ее не существует
         // Устанавливаем ее и редиректим на 1й город по сортировке городов
         $APPLICATION->set_cookie('USER_CITY', $arCityCodes[0]);
         header("Location: http://{$arCityCodes[0]}.mysite.ru/");
      }
   }
   // после всех редиректов устанавливаем куку на текущий город
   if (strlen($sCurCity)) $APPLICATION->set_cookie('USER_CITY', $sCurCity);
   // установим фильтр, который будем повсеместно применять 
   // для списков элементов на сайте, где предполагается зависимость от города
   if (intval($iCurCityID) > 0) $GLOBALS['arrFilter'] = array('PROPERTY_CITY'=>$iCurCityID);
?>
Если будет интересно, могу рассказать как я делал саму "переключалку городов" для визуальной части сайта.

UPD: Изменил код согласно рекомендациям Рыжонина Николая, еще раз ему спасибо за дельный совет!

Назад в раздел

Подписаться на новые материалы раздела:












CAPTCHA