Redirect loop problem s Response.redirect(url)

4 years ago

Durisvk
Member | 31
+
0
-

Ahojte,
tak mám tu ďalší problém.
Vytvoril som si triedu StateSaver, ktorá uloží do cookies momentálnu hodnotu $value pod názvom $name. Ak je však v cookies už uložená $old_value pod názvom $name, porovná $value a $old value a ak sa líšia, zavolá preddefinovaný callback. Trieda vyzerá takto:

<?php

<?php

namespace Datagrid;


use Nette\Http\Request;
use Nette\Http\Response;
use Nette\InvalidStateException;
use Nette\Utils\Callback;
use Nette\Utils\DateTime;

class StateSaver extends \Nette\Object {

    /**
     * Time length to store values
     */
    const STORE_TIME_IN_MINUTES = 20;

    /** @var Request */
    protected $httpRequest;

    /** @var Response */
    protected $httpResponse;

    /** @var string */
    protected $name;

    /** @var mixed */
    protected $value;

    /** @var callable */
    protected $onchange;

    /**
     * @param Request $httpRequest
     * @param Response $httpResponse
     * @param string $name
     * @param mixed $value
     */
    public function __construct(Request $httpRequest, Response $httpResponse, $name, $value)
    {
        $this->httpRequest = $httpRequest;
        $this->httpResponse = $httpResponse;
        $this->name = $name;
        $this->value = $value;
    }


    /**
     * Stores the value into Cookies under the parameter name and for
     * STORE_TIME_IN_MINUTES
     *
     * @param null|mixed $value
     * @return $this
     */
    public function store($value = NULL)
    {
        if(!$value) {
            $value = $this->value;
        }

        if(!$value) {
            throw new InvalidStateException('Value must be set!');
        }

        $value = serialize($value);

        if($this->name && is_string($this->name)) {

            $this->httpResponse->setCookie($this->name,
                $value,
                    new DateTime('+ ' . self::STORE_TIME_IN_MINUTES . ' minute'));

        } else {
            throw new InvalidStateException(sprintf('Name must be string, %s given', gettype($this->name)));
        }
        return $this;
    }

    /**
     * Gets the stored value from the Cookies
     *
     * @return mixed|null
     */
    protected function restore()
    {
        $value = $this->httpRequest->getCookie($this->name);

        if($value) {
            return unserialize($value);
        } else {
            return NULL;
        }
    }


    /**
     * Sets callback which will be called in checkState() if the stored value
     * is different than the current one.
     * As arguments should receive old stored value and the current value.
     *
     * @param $callback
     * @return $this
     */
    public function onChange($callback)
    {
        Callback::check($callback);
        $this->onchange = $callback;
        return $this;
    }


    /**
     * Checks if value in cookies is set(if not it sets the value)
     * and whether the stored value is different than the current one.
     */
    public function checkState()
    {
        $old_value = $this->restore();

        if ($old_value) {
            if($old_value != $this->value && $this->onchange) {
                Callback::invokeArgs($this->onchange, array($old_value, $this->value));
            }
        } else {
            $this->store();
        }
    }
}

?>

Potom túto triedu používam, na uloženie URL do cookies, a ak sa stránka znovu načíta bez akýchkoľvek $_GET[] parametrov tak ju chcem redirectnúť na tú, ktorá je uložená v cookies. Ajaxovo to funguje skvele, ale keď refreshnem stránku, vytvorí sa mi redirect loop, pritom ten Response.redirect sa už po druhý krát nemá volať. Tu je kód kde používam StateSaver:
(Tu je problém)

<?php

    public function attached($presenter)
    {
        parent::attached($presenter);

        if($this->persistent) {
            /** @var \Nette\Http\Request $request */
            $request = $presenter->context->getByType('Nette\Http\Request');

            /** @var \Nette\Http\Response $response */
            $response = $presenter->context->getByType('Nette\Http\Response');

            $stateSaver = new StateSaver($request, $response, $this->getParent()->getName(), (string)$request->getUrl());

            $stateSaver->onChange(function($old_value, $new_value) use($request, $response, $stateSaver) {
                $url = new Url($new_value);
                if(!count($url->getQueryParameters())) {
                    $response->redirect($old_value);
                } else {
                    $stateSaver->store($new_value);
                }
            });
            ob_start();
            $stateSaver->checkState();
        }
    }

?>

4 years ago

amik
Member | 124
+
0
-

Hi,
we'd like to help you, but are you sure all this code is relevant to your problem?
It seems to me that the only place where you call redirect is the condition if(!count($url->getQueryParameters())) { ... , which probably means that query parameters of the created URL are empty.
Please try to confirm my idea and find out more what is actually happening, not just “it ends with loop somewhere”.
Also, please speak english there or use czech version of the forum.