5

目前我在默认位置有一个 Zend 应用程序 www.example.com/{controller}/{action}

但是当用户从特定国家访问时,如何检测他们的 IP 地址并将他们重定向到这个基于 countryCode 的 url www.example.com/uk/{controller}/{action}

为了检测用户访问的国家/地区,我编写了一个助手:

require_once '../library/Ipinfo/ip2locationlite.class.php';

class Application_View_Helper_GetLocation extends Zend_View_Helper_Abstract
{
    public function getLocation()
    {

        $ipLite = new ip2location_lite;
        $ipLite->setKey('APIKEY');

        //Get errors and locations
        $locations = $ipLite->getCity($_SERVER['REMOTE_ADDR']);
        $errors = $ipLite->getError();

        $country = strtolower($locations['countryName']);

        return "$country";
    }
}

上面的代码将返回国家名称。如果用户从法国访问,我该如何重写 url 以使 url 变为example.com/france/{controller}/{action}

4

2 回答 2

2

将您的视图助手重构为控制器插件并重定向。

控制器插件可以在请求调度循环的早期执行,因此您可以在加载和呈现任何控制器之前拦截请求并重定向到另一个响应。下面的示例(警告,可能包含错误!)

class App_Plugin_DetectCountry extends Zend_Controller_Plugin_Abstract {

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        $ipLite = new ip2location_lite;
        $ipLite->setKey('APIKEY');

        //Get errors and locations
        $locations = $ipLite->getCity($_SERVER['REMOTE_ADDR']);
        $errors = $ipLite->getError();

        $country = strtolower($locations['countryName']);

        //Check if set country equals detected country
        if (!isset($_COOKIE['country']) || $country !== $_COOKIE['country']) {
            $_COOKIE['country'] = $country;
            $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
            $redirector->gotoUrl($country . '/' . $request->getControllerName() . '/' . $request->getActionName()); 
        }
    }
}
于 2012-07-25T03:23:24.317 回答
1

我同意@tripleee 关于使用 HTTP 标头而不是查找他们的 IP 的评论,这通常会导致不正确的值,或者强制远程代理后面的用户进入他们不想要的设置。

尝试使用此控制器插件根据浏览器给出的用户区域设置进行重定向:

<?php

class Application_Plugin_Language extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        /*
        // if you add "localization.default_locale = "en_US" to your application.ini, uncomment the following
        $config = new Zend_Config($this->getOption('localization'), true);
        $loc = (isset($config->default_locale)) ? $config->default_locale : 'en_US';
        */

        $module = $request->getModuleName();
        if ($module != 'default') return ;

        // You can also check a cookie or session value here to see if you can return from the plugin as well

        $loc = 'en_US';

        Zend_Locale::setDefault($loc);

        try {
            $locale = new Zend_Locale(Zend_Locale::BROWSER);
        } catch (Zend_Locale_Exception $e) {
            $locale = new Zend_Locale($loc);
        }

        $language = $locale->getLanguage();  // e.g. "en", "de", "ru" etc.

        $urlHelper = new Zend_Controller_Action_Helper_Url();
        $url = $urlHelper->url(array('module' => $language, 'controller' => 'form', 'action' => 'index'));

        $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
        $redirector->gotoUrl($url);
    }
}

如果用户当前正在请求默认模块,此插件将根据用户浏览器设置的语言重定向到具有语言名称的模块。

请注意,此代码不会检查您重定向到的模块是否存在。您应该在重定向之前检查该语言是否受支持。

您还可以添加对包含用户所需语言的 cookie 或会话值的检查,并基于此进行重定向。

通过将其添加到以下内容来注册插件application.ini

resources.frontController.plugins.language = "Application_Plugin_Language"

如果您想根据国家而不是语言重定向,请更改$language = $locale->getLanguage();$region = $locale->getRegion();

希望有帮助。

于 2012-07-25T03:37:02.057 回答