Presmerovani pomoci Redirect map

Wizzard256
Člen | 18
+
0
-

Zdravim,

rad bych se zeptal zda nevite o nejakem jednoduchem reseni jak resit redirecty ze starych URL, rekneme ze mam dlouhy seznam starych a novych url, na ktere bych potreboval presmerovat, napr.:

$redirectMap = [
	'/?abc[x1]=123&def[x2]=456' => '/landing-page-1',
	'/?abc[x1]=789&def[x2]=012' => '/landing-page-2',
	...
];

nevidim zda by se toto dalo vyresit pomoci routy, a prepisovani na cilovy tvar

[
    'presenter' => 'Homepage',
    'action'    => 'default'
]

neni zadouci.

Otazka tedy je:

  1. kam toto reseni zakomponovat v nette
  2. lze nejak propojit s route, aby redirecty byli videt v tracy v seznamu rout?

Diky

Felix
Nette Core | 1183
+
0
-

Idealne to hodit do webserveru. Nebude se tim zatezovat aplikace. Jestli mas Apache, tak do htaccess. Pokud mas Nginx, tam to musis nastavit na serveru.

Wizzard256
Člen | 18
+
0
-

Zdravím,

@Felix Děkuji za návrh, bohužel toto není řešení pomocí Nette, ačkoliv je rychlejší, nedrží se tím kód na jednom místě

rád bych se podělil o své řešení, snad to někomu pomůže:

<?php

use Nette\Application\IRouter;

class RouteUrl extends \Nette\Application\Routers\Route //implements IRouter
{
    private $redirectMap = [];

    private $matchedItem;

    /**
     * new RouteUrl('link1', 'link2');
     * new RouteUrl([
     *      'link1' => 'link2',
     *      ...
     * ]);
     *
     * @param type $sourceUrl
     * @param type $destinationUrl
     * @throws Nette\InvalidArgumentException
     */
    public function __construct($sourceUrl, $destinationUrl = null)
    {
        if (is_array($sourceUrl)) {
            $this->redirectMap = $sourceUrl;
        } else {
            if (!$destinationUrl) {
                throw new Nette\InvalidArgumentException('Invalid parameters');
            }
            $this->redirectMap[$sourceUrl] = $destinationUrl;
        }
    }

    public function constructUrl(\Nette\Application\Request $appRequest, \Nette\Http\Url $refUrl)
    {
        return null;
    }

    public function getMask()
    {
        // pro tracy
        if (count($this->redirectMap) == 1) {
            return key($this->redirectMap);
        } else {
            return $this->matchedItem;
        }
    }

    public function getDefaults()
    {
        // pro tracy
        return [
            'presenter' => 'System:Redirect',
        ];
    }

    public function match(\Nette\Http\IRequest $httpRequest)
    {
        if (!isset($_SERVER['REQUEST_URI'])) {
            return null;
        }

        $requestUri = $_SERVER['REQUEST_URI']; // /test/def/?abraka
        $scriptPath = $httpRequest->getUrl()->getScriptPath(); // /test/
        $relativeUri = preg_replace('/^' . preg_quote($scriptPath, '/') . '/', '', $requestUri); // def/?abraka

        foreach ($this->redirectMap as $matchSourceUrl => $matchDestinationUrl) {
            if ($matchSourceUrl == $relativeUri) {
                $presenter = 'System:Redirect';

                $this->matchedItem = $relativeUri;

                return new \Nette\Application\Request(
                    $presenter,
                    $httpRequest->getMethod(),
                    [
                        'destinationUrl' => urlencode($httpRequest->getUrl()->getBaseUrl() . $matchDestinationUrl),
                    ],
                    $httpRequest->getPost(),
                    $httpRequest->getFiles(),
                    [\Nette\Application\Request::SECURED => $httpRequest->isSecured()]
                );
            }
        }

    }

}

dále přidat presenter pro přesměrování:

<?php

namespace SystemModule;


class RedirectPresenter extends \Nette\Application\UI\Presenter
{
    public function actionDefault()
    {
        if (!isset($this->request->parameters['destinationUrl'])) {
            throw new \Exception('Missing redirect parameter');
        }

        $destinationUrl = urldecode($this->request->parameters['destinationUrl']);

        $this->redirectUrl($destinationUrl, \Nette\Http\IResponse::S301_MOVED_PERMANENTLY);
        $this->terminate();
    }
}

v RouterFactory pak stačí

// old URLs
		$this->router[] = new RouteUrl('?abc%5Bdef%5D=xyz', 'landing-page-1');

výsledek je potom vidět v Tracy baru

CZechBoY
Člen | 3608
+
0
-

To je šílený…
Na co dělat vlastní router když to v pohodě zvládne klasická Route?
Pro starý url je v dokumentaci uveden parametr Route::ONE_WAY, který bys měl pooužít v kombinaci s Route třídou.

Takže RouterFactory by vypadala nějak takhle

class RouterFactory
{
	public static function createRouter(): IRouter
	{
		$router = new RouteList();
		$router[] = new Route('/?abc[x1]=123&def[x2]=456', [
			'presenter' => 'LandingPage',
			'action' => 'default',
			'id' => 1,
		], Route::ONE_WAY);
	}
}
Wizzard256
Člen | 18
+
0
-

to ale neakceptuje vstup jak jsem psal:

$redirectMap = [
    '/?abc[x1]=123&def[x2]=456' => '/landing-page-1',
    '/?abc[x1]=789&def[x2]=012' => '/landing-page-2',
    ...
];

tvým řešením by se musely všechny cílové URL přepsat do tvaru

[
	'presenter' => 'LandingPage',
    'action' => 'default',
    'id' => 1,
]

včetně ručního dohledávání všech parametrů presenter, action a id

CZechBoY
Člen | 3608
+
0
-

jo, aspoň bys nemusel při další změně url přepisovat celou aktuální redirect mapu.
Co ti vlastně konkrétně vadí na tom přesměrování na úrovni webserveru? To že by nebyl kod na jednom místě nechápu… však dáš přece všechny ty přesměrování na jedno místo.

Felix
Nette Core | 1183
+
0
-

@Wizzard256

@Felix Děkuji za návrh, bohužel toto není řešení pomocí Nette, ačkoliv je rychlejší, nedrží se tím kód na jednom místě

Myslim, ze doba mit vse na 1 miste je ta tam. :-)