Автоопределение города пользователя при оформлении заказа (на основе GeoIP)
Ну и вдогонку - забавный скриншот, который не лучшим образом характеризует базу стран и городов на ip2city.ru - 

Заказов не беру. Консультирую редко.
Закрыт порт на новом хостинге 8090
надо выделенный ip брать.
в связи с чем выскакивает ошибка.
заменил
на
так корректно делать?
пока порт закрыт, можно попытку подключения совсем убрать, но если проблема в чем-то другом будет, то уж слишком длительная попытка идет. можно как-то сократить время настройками?
И нет ли у кого шлюза с порта 80 или 443 на 8090? для этого сервиса?
надо выделенный ip брать.в связи с чем выскакивает ошибка.
заменил
if (!$socket = fsockopen(IPGEO_SERVER, IPGEO_SERVER_PORT))
return false;
return false;
на
$socket = @fsockopen(IPGEO_SERVER, IPGEO_SERVER_PORT)
if (!$socket)
return false;
if (!$socket)
return false;
так корректно делать?
пока порт закрыт, можно попытку подключения совсем убрать, но если проблема в чем-то другом будет, то уж слишком длительная попытка идет. можно как-то сократить время настройками?
И нет ли у кого шлюза с порта 80 или 443 на 8090? для этого сервиса?
VAshot, по коду - синтаксически корректно. Логически использовать @ вообще-то не рекомендуется (ну это примерно как давние холивары про оператор Goto
) но в данном случае в прицнипе резонно.
По остальным же вопросам вам скорее вот сюда и вот сюда т.к. исходный код класса не мой, я лишь чуть-чуть подработал его напильничком, чтобы мне было удобнее взаимодействовать с этим классом из HostCMS.
) но в данном случае в прицнипе резонно.По остальным же вопросам вам скорее вот сюда и вот сюда т.к. исходный код класса не мой, я лишь чуть-чуть подработал его напильничком, чтобы мне было удобнее взаимодействовать с этим классом из HostCMS.
Заказов не беру. Консультирую редко.
В связи с тем, что люди интересуются и спрашивают, выкладываю обновленную версию, для работы с utf-8 версиями HostCMS. В ней есть небольшие, но все же изменения.
Не забываем, что создавая файл с классом geoip.class.php сохранять его надо в кодировке utf-8!
Итак, коды:
geoip.class.php (сохранять в папку modules)
В ТДС «Интернет-магазин корзина» находим следующий фрагмент:
и меняем его на следующий фрагмент:
После этого меняем код xsl-шаблона «МагазинАдресДоставки» на следующий:
Также, весь вышеприведенный код можно скачать одним rar-архивом .
Во1х, в коде класса исключен перевод результирующего значения из utf-8 в win1251 с помощью iconv - теперь результат отдается непосредственно в utf-8. Код класса предназначен только для работы под php5.
Во2х, в ТДС метод strtolower() заменен на mb_strtolower().
В3х, в ТДС исключен последовательный перебор городов в поисках совпадения. Вместо этого используется прямой запрос к БД. В некотором плане это чуть менее кошерно, но зато в ряде случаев заметно быстрее.
В4х, обновлен xsl-шаблон (исправлена кодировка с win-1251 на utf-8).
Не забываем, что создавая файл с классом geoip.class.php сохранять его надо в кодировке utf-8!
Итак, коды:
geoip.class.php (сохранять в папку modules)
// файл /modules/geoip.class.php
<?php
/*
This program is free software. You can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
Home:
Author: Egor N. Zuskin
Adapted for HostCMS by James V. Kotoff
Simple for php:
$ipList = new IPGeo("xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx");
print $ipList->ip("xxx.xxx.xxx.xxx"); // city: xxxx
or
$ipList = new IPGeo(array("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"));
print $ipList->ip("xxx.xxx.xxx.xxx","region"); // region: xxxx
or
$ipList = new IPGeo("xxx.xxx.xxx.xxx");
print $ipList->ip("xxx.xxx.xxx.xxx", "district"); // district: xxxx
*/
DEFINE("IPGEO_SERVER", "194.85.91.253"); // сервер ip geo
DEFINE("IPGEO_SERVER_PORT", 8090); // порт
DEFINE("IPGEO_DEFAULT_PARAM", "city"); // поле возвращаемое поумолчанию
DEFINE("IPGEO_DEBUG", false); // признак отладки (не обращается к серверу)
/**
* @author ice
* Класс для получения ip адресов с сервиса ipgeobase.ru
*/
class IPGeo
{
var $xml = ""; // текст возвращаемого xml
var $ip_arr = array(); // массив ip адресов
var $fields_arr = array("all"); // список запрашиваемых полей
var $cache = array(); // кешь ответа
/**
* Создание класса и запрос к серверу
* @param $AIpList список ip адресов, строкой либо строкой через запятую либо массивом
* @return bool
*/
function IPGeo($AIpList)
{
if (IPGEO_DEBUG) {
return true;
}
if (is_array($AIpList)) {
$ip_arr = $AIpList;
} else {
if (strpos($AIpList, ",") === false) {
$ip_arr = array(trim($AIpList));
} else {
$ip_arr = explode(",", trim($AIpList));
}
}
$ip_arr = array_unique($ip_arr);
$ip_arr = $this->check_ip_list_valid($ip_arr);
if (count($ip_arr) == 0)
return false;
$ips = "<ip>" . implode("</ip><ip>", $ip_arr) . "</ip>";
$fields = "<" . implode("/><", $this->fields_arr) . "/>";
$post_string = "<ipquery><fields>" . $fields . "</fields><ip-list>" . $ips .
"</ip-list></ipquery>";
if (!$socket = fsockopen(IPGEO_SERVER, IPGEO_SERVER_PORT))
return false;
$query = "POST /geo/geo.html HTTP/1.1\r\n";
$query .= "Content-Length: " . strlen($post_string) . "\r\n";
$query .= "\r\n";
$query .= $post_string;
$query .= "\r\n\r\n";
$response = "";
fwrite($socket, $query);
while (!feof($socket)) {
$response .= fgets($socket, 2048);
}
fclose($socket);
$this->xml = trim(substr($response, strpos($response, "\r\n\r\n")));
return true;
}
/**
* Возвращает запрошенное поле для ip адреса
* @param $AIp IP адрес
* @param $AFieldName Поле
* @return string
*/
function ip($AIp, $AFieldName = IPGEO_DEFAULT_PARAM)
{
if (IPGEO_DEBUG) {
return false;
}
if (isset($this->cache[$AIp][$AFieldName])) {
return $this->cache[$AIp][$AFieldName];
} else {
if ($this->xml) {
$doc = new DOMDocument;
$doc->loadXML($this->xml);
$xmlpath = new domxpath($doc);
$ip_ansver = $doc->getElementsByTagName("ip-answer")->item(0);
$items = $xmlpath->query("ip", $ip_ansver);
foreach ($items as $it) {
$ip = $it->getAttribute('value');
if ($ip == $AIp) {
$message = @$xmlpath->query("message", $it)->item(0)->nodeValue;
$field_value = ($message <> "") ? false : $xmlpath->query($AFieldName, $it)->item(0)->nodeValue;
$this->cache[$AIp][$AFieldName] = $field_value;
return $field_value;
}
}
}
}
return false;
}
/**
* Возвращает список правильных ip адресов проверенных по маске xxx.xxx.xxx.xxx < 256
* @param $AIpList масив ip адресов
* @return array
*/
function check_ip_list_valid($AIpList)
{
$return = array();
foreach ($AIpList as $ip) {
if (ereg("([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}).([0-9]{1,3})", $ip, $par)) {
if ($par[1] < 256 && $par[2] < 256 && $par[3] < 256 && $par[4] < 256) {
$return[] = $ip;
}
}
}
return $return;
}
}
?>
<?php
/*
This program is free software. You can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
Home:
Author: Egor N. Zuskin
Adapted for HostCMS by James V. Kotoff
Simple for php:
$ipList = new IPGeo("xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx");
print $ipList->ip("xxx.xxx.xxx.xxx"); // city: xxxx
or
$ipList = new IPGeo(array("xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx"));
print $ipList->ip("xxx.xxx.xxx.xxx","region"); // region: xxxx
or
$ipList = new IPGeo("xxx.xxx.xxx.xxx");
print $ipList->ip("xxx.xxx.xxx.xxx", "district"); // district: xxxx
*/
DEFINE("IPGEO_SERVER", "194.85.91.253"); // сервер ip geo
DEFINE("IPGEO_SERVER_PORT", 8090); // порт
DEFINE("IPGEO_DEFAULT_PARAM", "city"); // поле возвращаемое поумолчанию
DEFINE("IPGEO_DEBUG", false); // признак отладки (не обращается к серверу)
/**
* @author ice
* Класс для получения ip адресов с сервиса ipgeobase.ru
*/
class IPGeo
{
var $xml = ""; // текст возвращаемого xml
var $ip_arr = array(); // массив ip адресов
var $fields_arr = array("all"); // список запрашиваемых полей
var $cache = array(); // кешь ответа
/**
* Создание класса и запрос к серверу
* @param $AIpList список ip адресов, строкой либо строкой через запятую либо массивом
* @return bool
*/
function IPGeo($AIpList)
{
if (IPGEO_DEBUG) {
return true;
}
if (is_array($AIpList)) {
$ip_arr = $AIpList;
} else {
if (strpos($AIpList, ",") === false) {
$ip_arr = array(trim($AIpList));
} else {
$ip_arr = explode(",", trim($AIpList));
}
}
$ip_arr = array_unique($ip_arr);
$ip_arr = $this->check_ip_list_valid($ip_arr);
if (count($ip_arr) == 0)
return false;
$ips = "<ip>" . implode("</ip><ip>", $ip_arr) . "</ip>";
$fields = "<" . implode("/><", $this->fields_arr) . "/>";
$post_string = "<ipquery><fields>" . $fields . "</fields><ip-list>" . $ips .
"</ip-list></ipquery>";
if (!$socket = fsockopen(IPGEO_SERVER, IPGEO_SERVER_PORT))
return false;
$query = "POST /geo/geo.html HTTP/1.1\r\n";
$query .= "Content-Length: " . strlen($post_string) . "\r\n";
$query .= "\r\n";
$query .= $post_string;
$query .= "\r\n\r\n";
$response = "";
fwrite($socket, $query);
while (!feof($socket)) {
$response .= fgets($socket, 2048);
}
fclose($socket);
$this->xml = trim(substr($response, strpos($response, "\r\n\r\n")));
return true;
}
/**
* Возвращает запрошенное поле для ip адреса
* @param $AIp IP адрес
* @param $AFieldName Поле
* @return string
*/
function ip($AIp, $AFieldName = IPGEO_DEFAULT_PARAM)
{
if (IPGEO_DEBUG) {
return false;
}
if (isset($this->cache[$AIp][$AFieldName])) {
return $this->cache[$AIp][$AFieldName];
} else {
if ($this->xml) {
$doc = new DOMDocument;
$doc->loadXML($this->xml);
$xmlpath = new domxpath($doc);
$ip_ansver = $doc->getElementsByTagName("ip-answer")->item(0);
$items = $xmlpath->query("ip", $ip_ansver);
foreach ($items as $it) {
$ip = $it->getAttribute('value');
if ($ip == $AIp) {
$message = @$xmlpath->query("message", $it)->item(0)->nodeValue;
$field_value = ($message <> "") ? false : $xmlpath->query($AFieldName, $it)->item(0)->nodeValue;
$this->cache[$AIp][$AFieldName] = $field_value;
return $field_value;
}
}
}
}
return false;
}
/**
* Возвращает список правильных ip адресов проверенных по маске xxx.xxx.xxx.xxx < 256
* @param $AIpList масив ip адресов
* @return array
*/
function check_ip_list_valid($AIpList)
{
$return = array();
foreach ($AIpList as $ip) {
if (ereg("([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3}).([0-9]{1,3})", $ip, $par)) {
if ($par[1] < 256 && $par[2] < 256 && $par[3] < 256 && $par[4] < 256) {
$return[] = $ip;
}
}
}
return $return;
}
}
?>
В ТДС «Интернет-магазин корзина» находим следующий фрагмент:
...
}
/* Запоминаем купон */
$_SESSION['shop_coupon_text'] = to_str($_POST['shop_coupon_text']);
/* Отображаем форму ввода адреса */
// Не выбираем show_location, show_city и show_city_area, т.к. подгружаются через AJAX
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id, array('show_location' => false, 'show_city' => false, 'show_city_area' => false), $external_propertys);
}
...
}
/* Запоминаем купон */
$_SESSION['shop_coupon_text'] = to_str($_POST['shop_coupon_text']);
/* Отображаем форму ввода адреса */
// Не выбираем show_location, show_city и show_city_area, т.к. подгружаются через AJAX
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id, array('show_location' => false, 'show_city' => false, 'show_city_area' => false), $external_propertys);
}
...
и меняем его на следующий фрагмент:
...
}
/* Запоминаем купон */
$_SESSION['shop_coupon_text'] = to_str($_POST['shop_coupon_text']);
// Определяем город пользователя
@include_once (CMS_FOLDER . '/modules/geoip.class.php');
if (defined('IPGEO_SERVER'))
{
$user_ip = ($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : getenv("HTTP_X_FORWARDED_FOR");
$IPGeo = new IPGeo($user_ip);
$city = trim(to_str($IPGeo->ip($user_ip)));
if ($city)
{
$city = mb_strtolower($city);
$query = "SELECT * FROM `shop_city_table` WHERE `shop_city_name` = '{$city}'";
$DataBase = &singleton('DataBase');
$city_resource = $DataBase->select($query);
if ($city_resource)
{
$city_row = mysql_fetch_assoc($city_resource);
$city_id = $city_row['shop_city_id'];
$location_id = $city_row['shop_location_id'];
}
if (isset($city_id))
{
$location_row = $shop->GetLocation($location_id);
$country_id = $location_row['shop_country_id'];
}
}
}
/* Отображаем форму ввода адреса */
if (isset($city_id))
{
$external_propertys['city_id'] = $city_id;
$external_propertys['location_id'] = $location_id;
$external_propertys['country_id'] = $country_id;
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id,
array('show_location' => true, 'show_city' => true, 'show_city_area' => true), $external_propertys);
} else
{
// Не выбираем show_location, show_city и show_city_area, т.к. подгружаются через AJAX
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id,
array('show_location' => false, 'show_city' => false, 'show_city_area' => false),
$external_propertys);
}
}
...
}
/* Запоминаем купон */
$_SESSION['shop_coupon_text'] = to_str($_POST['shop_coupon_text']);
// Определяем город пользователя
@include_once (CMS_FOLDER . '/modules/geoip.class.php');
if (defined('IPGEO_SERVER'))
{
$user_ip = ($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : getenv("HTTP_X_FORWARDED_FOR");
$IPGeo = new IPGeo($user_ip);
$city = trim(to_str($IPGeo->ip($user_ip)));
if ($city)
{
$city = mb_strtolower($city);
$query = "SELECT * FROM `shop_city_table` WHERE `shop_city_name` = '{$city}'";
$DataBase = &singleton('DataBase');
$city_resource = $DataBase->select($query);
if ($city_resource)
{
$city_row = mysql_fetch_assoc($city_resource);
$city_id = $city_row['shop_city_id'];
$location_id = $city_row['shop_location_id'];
}
if (isset($city_id))
{
$location_row = $shop->GetLocation($location_id);
$country_id = $location_row['shop_country_id'];
}
}
}
/* Отображаем форму ввода адреса */
if (isset($city_id))
{
$external_propertys['city_id'] = $city_id;
$external_propertys['location_id'] = $location_id;
$external_propertys['country_id'] = $country_id;
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id,
array('show_location' => true, 'show_city' => true, 'show_city_area' => true), $external_propertys);
} else
{
// Не выбираем show_location, show_city и show_city_area, т.к. подгружаются через AJAX
$shop->ShowAddress(to_str($GLOBALS['LA']['xsl_delivery_address']), $shop_id,
array('show_location' => false, 'show_city' => false, 'show_city_area' => false),
$external_propertys);
}
}
...
После этого меняем код xsl-шаблона «МагазинАдресДоставки» на следующий:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="UTF-8" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>
<xsl:template match="/locations">
<!-- Строка шага заказа -->
<ul class="shop_navigation gray">
<li class="shop_navigation_current">
<span>Адрес доставки</span>→</li>
<li>
<span>Способ доставки</span>→</li>
<li>
<span>Форма оплаты</span>→</li>
<li>
<span>Данные доставки</span>
</li>
</ul>
<SCRIPT type="text/javascript" language="JavaScript">
<xsl:comment>
<xsl:text disable-output-escaping="yes">
<![CDATA[
location_select_id = "location";
city_select_id = "sel_city";
cityarea_select_id = "sel_city_area";
]]>
</xsl:text>
</xsl:comment>
</SCRIPT>
<xsl:variable name="country_id">
<xsl:choose>
<xsl:when test="/locations/external_propertys/country_id/node()">
<xsl:value-of select="/locations/external_propertys/country_id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="/locations/country[@select = 1]/@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<form name="address" id="address" method="POST">
<h1>Адрес доставки</h1>
<p>
<a href="{shop/path}cart/">Корзина</a>
</p>
<table>
<tr>
<td>Страна:</td>
<td>
<select id="country" style="width: 390px;" name="country" onchange="doSetLocation(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:apply-templates select="country"/>
</select>
<span class="red_star" style="position: relative; top: 4px;">*</span>
</td>
</tr>
<tr>
<td>Область:</td>
<td>
<select name="location" style="width: 390px;" id="location" onchange="doSetCity(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:apply-templates select="location[@parent = $country_id]"/>
</select>
<span class="red_star" style="position: relative; top: 4px;">*</span>
</td>
</tr>
<tr>
<td>Город:</td>
<td>
<select name="sel_city" style="width: 390px;" id="sel_city" onchange="doSetCityArea(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:variable name="location_id">
<xsl:choose>
<xsl:when test="/locations/external_propertys/location_id/node()">
<xsl:value-of select="/locations/external_propertys/location_id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="location[@parent = $country_id]/@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:apply-templates select="city[@parent = $location_id]"/>
</select>
</td>
</tr>
<tr>
<td>Район города:</td>
<td>
<select name="sel_city_area" style="width: 390px;" id="sel_city_area">
<option value="0">..</option>
</select>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Индекс:</td>
<td>
<input type="text" size="5" class="large_input" style="width: 90px;" name="index" value="{external_propertys/site_users_postcode}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Улица, дом, квартира:<br/>
(город, район, если не выбраны)</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="full_address" value="{external_propertys/site_users_address}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Фамилия, Имя, Отчество:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_surname" value="{external_propertys/site_users_surname}"/>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_name" value="{external_propertys/site_users_name}"/>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_patronymic" value="{external_propertys/site_users_patronymic}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Компания:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_company" value="{external_propertys/site_users_company}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Телефон:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_phone" value="{external_propertys/site_users_phone}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Факс:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_fax" value="{external_propertys/site_users_fax}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">E-mail:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_email" value="{external_propertys/site_users_email}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Комментарий к заказу:</td>
<td>
<textarea rows="2" class="large_input" style="width: 390px;" name="description"></textarea>
</td>
</tr>
<tr>
<td>
<div class="gray_button">
<div>
<input name="step_2" value="Далее →" type="submit"></input>
</div>
</div>
</td>
</tr>
</table>
</form>
<!-- Автоматически заполняем все дочерние элементы страны, если город пользователя не определился по GeoIP-->
<xsl:if test="not(/locations/external_propertys/country_id/node())" >
<SCRIPT type="text/javascript" language="JavaScript">var oldHandler=window['onload'];
window['onload']=function(){if(typeof(oldHandler)=='function'){oldHandler();}newHandler();};
function newHandler(){
doSetLocation(document.getElementById('country').options[document.getElementById('country').selectedIndex].value, '<xsl:value-of select="/locations/shop/path"/>cart/');
}</SCRIPT>
</xsl:if>
</xsl:template>
<!-- Шаблон заполняет options для стран -->
<xsl:template match="country">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="(not(/locations/external_propertys/country_id/node()) and @select=1) or (/locations/external_propertys/country_id/node() and @id = /locations/external_propertys/country_id)">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для местоположений (областей) -->
<xsl:template match="location">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="/locations/external_propertys/location_id/node() and @id = /locations/external_propertys/location_id">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для городов -->
<xsl:template match="city">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="/locations/external_propertys/city_id/node() and @id = /locations/external_propertys/city_id">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для районов -->
<xsl:template match="cityarea">
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:template>
</xsl:stylesheet>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="UTF-8" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>
<xsl:template match="/locations">
<!-- Строка шага заказа -->
<ul class="shop_navigation gray">
<li class="shop_navigation_current">
<span>Адрес доставки</span>→</li>
<li>
<span>Способ доставки</span>→</li>
<li>
<span>Форма оплаты</span>→</li>
<li>
<span>Данные доставки</span>
</li>
</ul>
<SCRIPT type="text/javascript" language="JavaScript">
<xsl:comment>
<xsl:text disable-output-escaping="yes">
<![CDATA[
location_select_id = "location";
city_select_id = "sel_city";
cityarea_select_id = "sel_city_area";
]]>
</xsl:text>
</xsl:comment>
</SCRIPT>
<xsl:variable name="country_id">
<xsl:choose>
<xsl:when test="/locations/external_propertys/country_id/node()">
<xsl:value-of select="/locations/external_propertys/country_id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="/locations/country[@select = 1]/@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<form name="address" id="address" method="POST">
<h1>Адрес доставки</h1>
<p>
<a href="{shop/path}cart/">Корзина</a>
</p>
<table>
<tr>
<td>Страна:</td>
<td>
<select id="country" style="width: 390px;" name="country" onchange="doSetLocation(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:apply-templates select="country"/>
</select>
<span class="red_star" style="position: relative; top: 4px;">*</span>
</td>
</tr>
<tr>
<td>Область:</td>
<td>
<select name="location" style="width: 390px;" id="location" onchange="doSetCity(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:apply-templates select="location[@parent = $country_id]"/>
</select>
<span class="red_star" style="position: relative; top: 4px;">*</span>
</td>
</tr>
<tr>
<td>Город:</td>
<td>
<select name="sel_city" style="width: 390px;" id="sel_city" onchange="doSetCityArea(this.options[this.selectedIndex].value, '{/locations/shop/path}cart/')">
<option value="0">..</option>
<xsl:variable name="location_id">
<xsl:choose>
<xsl:when test="/locations/external_propertys/location_id/node()">
<xsl:value-of select="/locations/external_propertys/location_id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="location[@parent = $country_id]/@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:apply-templates select="city[@parent = $location_id]"/>
</select>
</td>
</tr>
<tr>
<td>Район города:</td>
<td>
<select name="sel_city_area" style="width: 390px;" id="sel_city_area">
<option value="0">..</option>
</select>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Индекс:</td>
<td>
<input type="text" size="5" class="large_input" style="width: 90px;" name="index" value="{external_propertys/site_users_postcode}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Улица, дом, квартира:<br/>
(город, район, если не выбраны)</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="full_address" value="{external_propertys/site_users_address}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Фамилия, Имя, Отчество:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_surname" value="{external_propertys/site_users_surname}"/>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_name" value="{external_propertys/site_users_name}"/>
<input type="text" size="30" class="large_input" style="width: 124px; margin-right: 5px;" name="site_users_patronymic" value="{external_propertys/site_users_patronymic}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Компания:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_company" value="{external_propertys/site_users_company}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Телефон:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_phone" value="{external_propertys/site_users_phone}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Факс:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_fax" value="{external_propertys/site_users_fax}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">E-mail:</td>
<td>
<input type="text" size="30" class="large_input" style="width: 390px;" name="site_users_email" value="{external_propertys/site_users_email}"/>
</td>
</tr>
<tr>
<td style="vertical-align: middle;">Комментарий к заказу:</td>
<td>
<textarea rows="2" class="large_input" style="width: 390px;" name="description"></textarea>
</td>
</tr>
<tr>
<td>
<div class="gray_button">
<div>
<input name="step_2" value="Далее →" type="submit"></input>
</div>
</div>
</td>
</tr>
</table>
</form>
<!-- Автоматически заполняем все дочерние элементы страны, если город пользователя не определился по GeoIP-->
<xsl:if test="not(/locations/external_propertys/country_id/node())" >
<SCRIPT type="text/javascript" language="JavaScript">var oldHandler=window['onload'];
window['onload']=function(){if(typeof(oldHandler)=='function'){oldHandler();}newHandler();};
function newHandler(){
doSetLocation(document.getElementById('country').options[document.getElementById('country').selectedIndex].value, '<xsl:value-of select="/locations/shop/path"/>cart/');
}</SCRIPT>
</xsl:if>
</xsl:template>
<!-- Шаблон заполняет options для стран -->
<xsl:template match="country">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="(not(/locations/external_propertys/country_id/node()) and @select=1) or (/locations/external_propertys/country_id/node() and @id = /locations/external_propertys/country_id)">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для местоположений (областей) -->
<xsl:template match="location">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="/locations/external_propertys/location_id/node() and @id = /locations/external_propertys/location_id">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для городов -->
<xsl:template match="city">
<xsl:choose>
<!-- Если страна задана по умолчанию -->
<xsl:when test="/locations/external_propertys/city_id/node() and @id = /locations/external_propertys/city_id">
<option value="{@id}" selected="selected" style="font-weight: bold;">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:when>
<xsl:otherwise>
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Шаблон заполняет options для районов -->
<xsl:template match="cityarea">
<option value="{@id}">
<xsl:value-of disable-output-escaping="yes" select="name"/>
</option>
</xsl:template>
</xsl:stylesheet>
Также, весь вышеприведенный код можно скачать одним rar-архивом .
Заказов не беру. Консультирую редко.
А как бы данную нужную плюшку прикрутить так чтобы при заходе на основной сайт редиректило на сайт города согласно данным из базы GEOIp?? т.е. есть сайт при заходе на него ип пользователя сравнивался с базой GEOIp и если город например Курск, редиректило бы пользователя на
Жизнь не преодоление сложностей, а поиск возможностей © DSergeev
В принципе - вполне возможно.
Это будет своеобразный гибрид из двух решений - GeoIP и .
Идея примерно следующая:
Вы создаете в админке несколько разных сайтов для городов, и "развешиваете" их по разным субодоменам.
У сайтов есть свой ID, а GeoIP возвращаем нам идентификаторы страны, области и города. Будем мыслить широко, и определять нужный сайт по id области.
Для этого нам придется _вручную_ создать массив, в котором ключами элементов будут id областей, а значениями элементов - id сайтов.
Этот массив мы сохраняем в php-файлик.
Затем меняем содержимое redirecter.php, подключаем в нем GeoIP определялку аналогично примерам в начале темы, и анализируем результат определения - если в массиве есть элемент с индексом определившейся области - получаем id нужного сайта, вытягиваем его домен и редиретимся туда. А если в массиве нет такого элемента, или по GeoIP определить ничего не удалось, то редиректим посетителя на основной сайт (или ничего не делаем, если он и так туда зашел).
Это черновая схема алгоритма, там на самом деле надо еще учесть, что в системе могут быть сайты, с которых никого никуда редиретить не надо, но суть примерно такова.
Готового решения, разумеется, нет.
Это будет своеобразный гибрид из двух решений - GeoIP и .
Идея примерно следующая:
Вы создаете в админке несколько разных сайтов для городов, и "развешиваете" их по разным субодоменам.
У сайтов есть свой ID, а GeoIP возвращаем нам идентификаторы страны, области и города. Будем мыслить широко, и определять нужный сайт по id области.
Для этого нам придется _вручную_ создать массив, в котором ключами элементов будут id областей, а значениями элементов - id сайтов.
Этот массив мы сохраняем в php-файлик.
Затем меняем содержимое redirecter.php, подключаем в нем GeoIP определялку аналогично примерам в начале темы, и анализируем результат определения - если в массиве есть элемент с индексом определившейся области - получаем id нужного сайта, вытягиваем его домен и редиретимся туда. А если в массиве нет такого элемента, или по GeoIP определить ничего не удалось, то редиректим посетителя на основной сайт (или ничего не делаем, если он и так туда зашел).
Это черновая схема алгоритма, там на самом деле надо еще учесть, что в системе могут быть сайты, с которых никого никуда редиретить не надо, но суть примерно такова.
Готового решения, разумеется, нет.
Заказов не беру. Консультирую редко.
ех еще бы города в области определяло.. было бы здорово... а то нахожусьв краснодарском крае, г.тихорецк,а определяет краснодар... (ну понятно что по IP привязке идет) но все таки.. ))))
Kotoff, скажите или у меня глюк в системе или что не так: сделал по последней версии
теперь в корзине при указании адреса выдаает // /modules/geoip.class.php в вверху.... чтот найти не могу где это прописано????
Kotoff, скажите или у меня глюк в системе или что не так: сделал по последней версии
теперь в корзине при указании адреса выдаает // /modules/geoip.class.php в вверху.... чтот найти не могу где это прописано????
Программист без пива как шампанское без пробки- быстро выдыхается.
asys-log, города в области - это не ко мне, сервис-то совершенно посторонний. Да и вряд-ли кто-то другой вам такую точность предложит на данный момент.
По поводу ошибки - стукнитесь в аську или в почту с доступами, по приведенному вами сообщению я установить ошибку не могу.
По поводу ошибки - стукнитесь в аську или в почту с доступами, по приведенному вами сообщению я установить ошибку не могу.
Заказов не беру. Консультирую редко.
Я продолжаю постепенно наводить порядок в архиве своих наработок 
Репозиторий дополнения для GeoIP выложен на BitBucket — теперь там можно всегда скачать последнюю версию, следить за изменениями и выходами апдейтов, а в разделе wiki можно прочитать самую последнюю версию инструкции по установке дополнения.
Скачивайте и следите за обновлениями! —
На сегодняшний день, данная первая версия дополнения считается устаревший, поэтому я рекомендую всем пользоваться более новой второй версией, ее вы можете найти здесь:

Репозиторий дополнения для GeoIP выложен на BitBucket — теперь там можно всегда скачать последнюю версию, следить за изменениями и выходами апдейтов, а в разделе wiki можно прочитать самую последнюю версию инструкции по установке дополнения.
Скачивайте и следите за обновлениями! —
На сегодняшний день, данная первая версия дополнения считается устаревший, поэтому я рекомендую всем пользоваться более новой второй версией, ее вы можете найти здесь:
Заказов не беру. Консультирую редко.
Сегодня перестала работать первая версия модуля. Не может достучаться до порта 8090 геосервера (вероятно уже и не будет работать).
Решил все поменять на вторую. Все сделано по мануалу, но ничего не происходит. Абсолютно. Ни ошибок, ни геоопределения. В программизме слабоват, не подскажете, как можно проверить в чем косяк?
Решил все поменять на вторую. Все сделано по мануалу, но ничего не происходит. Абсолютно. Ни ошибок, ни геоопределения. В программизме слабоват, не подскажете, как можно проверить в чем косяк?
Авторизация