У нас портал зарубежной недвижимости, поэтому принадлежность объекта к какой-то стране - это главное его свойство. Мы серьезно подошли к задаче организации каталога стран, искали оптимальные варианты технической реализации. [spoiler]Рассмотрим ниже следующие проблемы: 1. Организация каталога с точки зрения seo 2. Организация каталога с точки зрения производительности 3. Организация каталога с точки зрения конечного пользователя (в другом посте будет)
Теоретическая и seo часть Изначально было решено, что объекты на сайте будут расположены в отдельных "папках", каждая из которых является страной. Адрес каждой страны имеет вид site.ru/Australia/. К тому же у нас есть еще и учет городов. Для города адреса страниц имеют вид site.ru/Australia/Darwin/. А объекты мы выводим по короткому адресу вида site.ru/12345/. Я думаю, что для seo - это оптимальное решение, ну оптимальней уже некуда.
Когда мы наполняли каталог стран, возник вопрос - а что, собственно, считать страной? Всего в мире официально существует 192 страны (члены ООН) + Ватикан. Но существуют такие "страны", которые вроде как и страны, но на деле являются заморскими территориями какой-то державы. Например, у Великобритании есть 12 Заморских земель, среди которых знаменитые Бермудские острова. Мы пошли на поводу у логики пользователей, которые не так строги к географии и при поиске недвижимости на Бермудских островах вряд ли будут учитывать, что это территория Великобритании. Мы выделили заморские территории как отдельные страны. Таких оказалось около 30. Французская Гвиана, Французская Полинезия, Новая Каледония, Сен-Мартен, Мартиника, Бермудские острова, Гонконг, Макао, Азорские острова, Аруба, Гибралтар, Острова Кука, Пуэрто-Рико и т.д. Это всё чьи-то заморские владения. Кому интересно о заморских территориях расширять свои познания, подробнее в википедии. В общем, сейчас у нас 210 стран.
Мы намеренно отказались от использования регионов (штатов), у нас есть только страна и город. Использование регионов не оправдано в плане навигации. 98% пользователей всё равно не знают, что, например, город Марбелья находится в автономном сообществе Андалусия и провинции Малага. Но вот относительно США, применение штатов было бы целесообразно, их больше знают, да и названия городов постоянно повторяются в разных штатах. Возможность оставили, но на будущее. В любой момент можно будет сделать адреса вида /Spain/Andalucia/Marbella/ или /USA/FL/Miami/
Техническая часть Для хранения данных о странах был организован отдельный инфоблок по типу справочника. Раздел первого уровня - страна, элемент инфоблока - город. Если бы мы использовали регионы (штаты) стран, то они логично были бы разделами второго уровня. Каждая страна описывается в настройках раздела, а каждый город в полях и свойствах элемента. Страшно подумать, но у нас порядка 50 тысяч населенных пунктов в базе, больше всего городов собрано в США (12000), Франция (6200), Германия (5900), Италия (5400), Великобритания (2900). В свойствах элементов (городах) мы часто указываем сортировку (SORT) так как при поиске городов только по названию без указания страны могут быть нежелательные нахождения одинаково названных городов. Например, город Венеция есть и в Италии и в США. Но если человек ищет "Венеция", то явно это не в США. Поэтому итальянскую Венецию мы должны поднимать в результатах поиска. То же самое касается и городов внутри одной страны. Я на досуге даже посчитал, у каких стран наибольшее пересечение (повторение друг у друга) названий городов, оказалось, что в паре Швейцарии и Германии.
Каталог объектов реализован без каких-либо разделов. Привязка к стране и городу создана в виде двух полей: city (привязка к элементам инфоблока) и country (привязка к разделам инфоблока). Разделение их сделано специально, чтобы в дальнейшем было проще делать выборку. Например, выбрать элементы только по стране или только по городу. Разумеется, у объектов еще есть куча дополнительных свойств с описанием всего и вся.
Для вывода каталога мы не использовали стандартный комплексный компонент bitrix:news или bitrix:catalog, а создавали свой наподобие. Это связано с тем, что на этапе анализа URL запросы необходимо было определять, запрос страны или запрос объекта. Если вы помните, то запрос страны у нас вида /Australia/, а запрос объекта вида /12345/, стандартные компоненты не позволяют таких махинаций. Ну а дальше всё просто. Запрос анализировался, если встречался код страны, то на выборку объектов накладывался фильтр PROPERTY_country=$country_id. Если указан еще и город, то добавлялся фильтр PROPERTY_city=$city_id. А если в адресе указано число, то подключается шаблон detail.php и в него передается ID указанного в адресе объекта.
Важное замечание. Мы не для всех городов знаем его англоязычное написание, которое используется в поле CODE, поэтому для большинства городов адреса имеют вид /Spain/12345/, где 12345 - это ID элемента с городом. По мере работы проекта они постепенно конвертируются в нормальные коды, обычно если город используется, для него находится код. А как конвертируются автоматом - это в другой раз
Еще на стадии проектирования мы поняли, что запросов к справочнику стран будет очень много. На любой странице их могло быть десятки, при этом в разных компонентах, могут быть запросы одной и той же страны десятки раз. Мы решили сделать нестандартное решение - сделали справочник стран глобальным. В файле /bitrix/php_interface/init.php мы предопределяем глобальную переменную $GLOBALS['countries'], в нее грузим все разделы со всеми полями из инфоблока стран. Разумеется, всё это хозяйство мы закэшировали на сутки. А вызов стран везде происходит только через функцию get_country($country), где $country - это может быть ID страны, ее символьный код (англоязычное название) или русскоязычное название. Если ID, то просто возвращаем $GLOBALS['countries'][$id], иначе перебором делаем поиск. Функция возвращает массив с полями раздела инфоблока. Таким образом обращений к БД для выборки страны по сути вообще нет. Если надо перебрать страны по порядку, то просто работаем с $GLOBALS['countries'] как с обычным массивом.
Очень руки чесались сделать подобное кэширование и с городами, но сами понимаете, хранить в памяти и кэше 50 тысяч записей в виде больших массивов не вариант, да и смысла особого нет, далеко не все города задействованы. Было найдено промежуточное решение. Мы храним в переменной $GLOBALS['cities'] только используемые на сайте города, а их из 50 тысяч всего лишь несколько сотен. Пересчитываются и кэшируются они также раз в сутки. Доступ через функцию get_city($city, $country=false), где $city - ID, код или название на русском города, а $country - необязательный параметр для ограничения поиска внутри нужной страны, которая обычно известна. Но если через функцию get_city() нужный город не найден в переменной, то есть в кэше, функция только в этом случае обращается к БД.
Не хочется даже думать о том количестве запросов к БД, которое мы бы генерировали, если бы не было этого кэширования на уровне одного инфоблока.
В качестве анонса Я очень много времени потратил на разработку механизма поиска недвижимости по странам, городам и карте. В следующем посте я расскажу об этом.
По поводу "Если вы помните, то запрос страны у нас вида /Australia/, а запрос объекта вида /12345/, стандартные компоненты не позволяют таких махинаций." На самом деле на стандартном уровне это реализуемо на уровне urlrewrite.php.
Т.е. сначала регистрируете рерайт #^/catalog/([0-9]+)/# и направляете его на детальную страницу. А потом обычный рерайт #^/catalog/# на обычный ньюс. И вполне себе стандартным механизмом реализуем то, что вам надо.
Другое дело, что в вашем случае я бы тоже делал свой компонент, потому как его потом проще дорабатывать
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».