Magento2: Vom Beobachter zur benutzerdefinierten URL umleiten

7

Meine Anforderung ist, dass ein Kunde, der eine Website aus dem indischen Land besucht, auf die indische Website www.example.com/in/ weitergeleitet wird . In allen anderen Fällen sollte es sich nur um eine Standardwebsite handeln.

Ich benutze die geoipPHP-Bibliothek. Ich habe das Frontend-Ereignis verwendet controller_action_predispatchund hier ist mein Beobachtercode:

namespace Amit\Geoip\Observer;
require_once 'lib/geoip.inc';
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Store\Model\StoreManager;

class ControllerActionPredispatch implements  ObserverInterface {

    protected $resultRedirectFactory;

    public function __construct(
        ResultFactory $resultFactory,
        StoreManager $storeManager
    )  {
        $this->resultFactory = $resultFactory;
        $this->storeManager = $storeManager;
    }

    public function execute(\Magento\Framework\Event\Observer $observer) {
        $baseUrl = $this->storeManager->getStore()->getBaseUrl();
        $gi = geoip_open(getcwd()."/app/code/Amit/Geoip/Observer/lib/GeoIP.dat",GEOIP_STANDARD);
        $ip = $_SERVER['REMOTE_ADDR'];

        $country_code = geoip_country_code_by_addr($gi, $ip);

        if((strtoupper($country_code) == "IN")){
            $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
            $resultRedirect->setUrl($baseUrl . '/in/' . $_SERVER['REQUEST_URI']);
        }
    }
}

Probleme:

  1. Meine Beobachterfunktion wird ausgeführt und ich erhalte das Land des Kunden von seiner IP, aber es wird nicht auf die Website www.example.com/in/* weitergeleitet . Was ist der richtige Weg, um zu meiner benutzerdefinierten URL umzuleiten?
  2. Ich denke, das Ereignis controller_action_predispatchwird die Beobachterfunktion auf jeder Seite des Kundenbesuchs aufrufen. Welches Ereignis sollte ich verwenden, damit es nur zum ersten Mal ausgeführt wird, wenn der Kunde die Website besucht?
  3. Ich sehe, dass eine der möglichen Optionen darin besteht, ein Cookie dafür zu setzen, aber ich bin nicht sicher, wo ich das Cookie in meinem Modul setzen soll (Ereignisse? Welches Ereignis?) Und welchen Prozess ich befolgen sollte, um sie umzuleiten.
amitshree
quelle
Dieser Codeausschnitt verlangsamt den Speicher. Cache country_code in der PHP-Sitzung. Und wenn der Laden Lack hat, funktioniert er überhaupt nicht.
obskure

Antworten:

5

Es gibt mehrere Ansätze, wie Sie dies tun können, ohne Magento-Code zu bearbeiten (z. B. Webserver-Ebene). Diese Ansätze könnten effizienter sein.

Wenn Sie dies jedoch mit Magento tun möchten, sollte Ihr $ resultRedirect an zurückgegeben werden App\Http. Ihr Beobachter gibt $ resultRedirect nicht zurück, daher wird es nicht von verarbeitet \Magento\Framework\App\Http::launchund eine Umleitung findet nicht statt. Da Sie möchten, dass Ihre Umleitungslogik so früh wie möglich erfolgt, jedoch nur in der Storefront (stimmt das?) Anstelle von Observer, sollten Sie ein Around-Plugin aktivieren, \Magento\Framework\App\FrontControllerInterface::dispatchda dies die erste Methode ist, die aufgerufen wird, \Magento\Framework\App\Http::launchnachdem area definiert und zurückgegeben wurde ResultInterface. Über dieses Plugin können Sie Ihr $resultRedirectObjekt zurückgeben:

namespace My\Module\App\FrontController;

class Plugin
{
    // Constructor and dependencies here

    public function aroundDispatch(
        FrontControllerInterface $subject,
        callable $proceed,
        RequestInterface $request
    ) {
            $baseUrl = $this->storeManager->getStore()->getBaseUrl();
            $gi = geoip_open(getcwd()."/app/code/Amit/Geoip/Observer/lib/GeoIP.dat",GEOIP_STANDARD);
            $ip = $_SERVER['REMOTE_ADDR'];

            $country_code = geoip_country_code_by_addr($gi, $ip);

            if((strtoupper($country_code) == "IN")){
                $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
                $resultRedirect->setUrl($baseUrl . '/in/' . $_SERVER['REQUEST_URI']);
                return $resultRedirect;
            } else {
                return $proceed($request);
            }
    }
}

Wenn Sie dies nur für den ersten Kunden tun, scheint die Überprüfung der Cookie-Präsenz eine praktikable Option zu sein.

Anton Kril
quelle
Ich habe ein Modul mit dem Plugin-Konzept entwickelt. Ich habe dort ein Problem. indiawird mehrmals zwischen der Basis-URL und der angeforderten URI hinzugefügt. Die Umleitungs-URL wird so etwas wie generiert example.com/india/india/india/.../aboutus. Warum indiawird zwischen Basis-URL und angeforderter URL mehrmals hinzugefügt? github.com/amitshree/magento2-website-switcher/blob/master/app/…
amitshree
2

Dies sind die folgenden Schritte:

1. Weiterleitungen können auf folgende Weise erfolgen: $observer->getControllerAction()->getResponse()>setRedirect($redirectUrl);

2. Die beste Lösung ist vielleicht die Verwendung von controller_action_predispatch(da es leider keine anderen, geeigneteren Ereignisse gibt).

3. Im selben Beobachter können Sie auch einige Cookies einrichten (z. B. "geoip_country_code"), die von der verarbeitet werden controller_action_predispatch.

Beachten Sie jedoch, dass Sie, falls Sie sich für diesen Weg entscheiden, jedes Mal vor der Weiterleitung Kunden-Cookies überprüfen müssen.

MageWorx
quelle
Vielen Dank. Ich suchte nach möglichen Wegen. Bitte lassen Sie mich wissen, ob es einen besseren Weg gibt, wenn Sie ein Referenz-Tutorial / Dokument implementiert haben oder haben. Ich bin bereit, daran zu arbeiten, wenn es bessere Möglichkeiten gibt.
Amitshree
Ich habe keinen Zugriff auf eine setRedirect-Umleitung in meinem $ Observer-Objekt
Kevando
0

Folgendes habe ich getan (denken Sie daran, das Aktionsflag zu setzen):

/**
 * @var \Magento\Framework\App\Response\RedirectInterface
 */
protected $redirect;

/**
 * @var \Magento\Framework\App\ActionFlag
 */
protected $actionFlag;

public function __construct
(
    \Magento\Framework\App\Response\RedirectInterface $redirect,
    \Magento\Framework\App\ActionFlag $actionFlag
)
{
    $this->redirect = $redirect;
    $this->actionFlag = $actionFlag;
}

public function execute(\Magento\Framework\Event\Observer $observer)
{
     /** @var \Magento\Framework\App\Action\Action $controller */
    $controller = $observer->getControllerAction();

    $this->actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
    $this->redirect->redirect($controller->getResponse(), 'my/custom/url');
}

Aktualisieren:

Führen Sie für Magento 2.1.5 die folgenden Schritte aus

/**
 * @param Observer $observer
 * @return void
 */
public function execute(\Magento\Framework\Event\Observer $observer)
{
    $event = $observer->getEvent();
    $this->redirect->redirect($event->getResponse(), 'my/custom/url');
}
Xenocide8998
quelle
0

Anton Kril hat ein gutes Beispiel geschrieben, aber $ resultRedirect sollte den Typ \ Magento \ Framework \ App \ Response \ Http haben. Hier Beispiel aus meinem Code:

class RedirectPlugin {
protected $subDomainsPrefix = [
    'CA' => '',
    'US' => 'us',
    'UK' => 'uk',
    'EU' => 'eu',
    'AU' => 'au'
];

protected $_responseFactory;

/**
 * @var \Magento\Framework\App\Config\ScopeConfigInterface
 */
protected $_scopeConfig;

/**
 * @var \Magento\Store\Model\StoreManager
 */
protected $_storeManager;

public function __construct(
    \Magento\Store\Model\StoreManager $storeManager,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Framework\App\Response\HttpFactory $httpFactory
) {
    $this->_storeManager    = $storeManager;
    $this->_scopeConfig     = $scopeConfig;
    $this->_responseFactory = $httpFactory;
}

/**
 * Redirect to subdomain by country code
 *
 * @param \Magento\Framework\App\FrontControllerInterface $subject
 * @param \Closure                                        $proceed
 * @param \Magento\Framework\App\RequestInterface         $request
 *
 * @return mixed
 */
public function aroundDispatch(
    \Magento\Framework\App\FrontControllerInterface $subject,
    \Closure $proceed,
    \Magento\Framework\App\RequestInterface $request
) {
    $baseUrl = $this->_storeManager->getStore()->getBaseUrl();
    if (isset($_SERVER['GEOIP_COUNTRY_CODE']) && isset($this->subDomainsPrefix[$_SERVER['GEOIP_COUNTRY_CODE']])) {
        $prefix      = $this->subDomainsPrefix[$_SERVER['GEOIP_COUNTRY_CODE']];
        $mainBaseUrl = $this->_scopeConfig->getValue('web/unsecure/base_url');
        $parts       = explode('.', str_replace('://', '.', $baseUrl));
        $subDomain   = $parts[1];
        if ($subDomain == $prefix || ($prefix == '' && strrpos($subDomain, 'carnivore') !== false)) {
            return $proceed($request);
        } else {
            $subDomain = str_replace('://', '://' . $prefix . '.', $mainBaseUrl);
            /**
             * @var \Magento\Framework\App\Response\Http $response
             */
            $response  = $this->_responseFactory->create();
            $response->setRedirect($subDomain);

            return $response;
        }
    } else {
        return $proceed($request);
    }
}
maks9889
quelle