0

Google Chromeでのみ奇妙な問題が発生しています。(Firefox、IE では問題ありません) これを再現するためのコードを以下に示します。手順は次のとおりです。

  1. セッション変数を設定してリダイレクトするページに移動します
  2. 新しい宛先ページは、次の関数を呼び出します。
    1. セッション変数を読み取り、ローカル変数に格納します
    2. セッション変数の設定を解除します
    3. ローカル変数を返します
  3. 次に、ページは戻り値を読み取り、それを HTML にエコーします (または試みます)。

次の 2 つのことがわかります。

  1. ページの最初の出力の前に echo を呼び出すと、ブラウザーにエコーされますが、実際のソースにはエコーされません(つまり、「ソースを表示」しても、「エコー」したテキストは表示されません)。

  2. HTML 内で echo を呼び出すと、エコーされず、ソースにまったく出力されません。

リダイレクトするページ (このページに直接移動できます)

<?php
class LandingRedirector
{
    private static $SESSION_VARIABLE = "redirectedFrom";

    function __construct() {}

    public function redirect()
    {
        //Make sure we have a session
        session_start();

        //Set the redirect variable
        $_SESSION[ self::$SESSION_VARIABLE ] = "red.php";

        session_write_close();

        //Redirect to correct page
        header( "Location: /end.php" );
        exit();
    }

    //Call this and this correctly prints the value
    public function setonly()
    {
        //Make sure we have a session
        session_start();

        //Set the redirect variable
        $_SESSION[ self::$SESSION_VARIABLE ] = "red.php";

        session_write_close();
    }

    public function getRedirect()
    {
        try
        {
            //Make sure we have a session
            session_start();

            //It's set
            if ( isset( $_SESSION[ self::$SESSION_VARIABLE ] ) )
            {
                $redFrom = $_SESSION[ self::$SESSION_VARIABLE ];

                //Unset it
                unset( $_SESSION[ self::$SESSION_VARIABLE ] );

                return $redFrom;
            }
        }
        catch (Exception $e) {}

        return null;
    }
}

//Create
$redirector = new LandingRedirector();

//Redirect
if ( !isset( $stopHere ) || $stopHere != true ) $redirector->redirect();
?>

宛先ページ

<?php
    $stopHere = true;

    //Handles any redirect code
    require_once $_SERVER[ "DOCUMENT_ROOT" ] . "/red.php";

    //Were we redirected?
    $redirectOrigin = $redirector->getRedirect();

    //This echos into the browser but is NOT in the page when you "view source"
    if ( $redirectOrigin ) echo $redirectOrigin;
?>
<html>
    <head>
        <script>
        <?php
        //This does not echo into the browser AND is not visible in "view source" either!
        if ( $redirectOrigin ) echo $redirectOrigin;
        ?>
    </script>
    </head>
    <body></body>
</html>

編集: リダイレクトではなく end.php に直接アクセスした場合にのみ呼び出される別の関数を追加しました。セッション変数の取得と設定解除と同じ設定を行いますが、これは機能します。

編集 2: 奇妙さを示すコードを追加

これら 2 つの関数を比較します。関数 1 を呼び出すと (どちらの関数も をチェックしないことに注意してisset()ください)、エラーが発生しますNotice: Undefined index: redirectedFrom。しかし、関数 2 を呼び出すと、エラーは発生せず、存在します。唯一の違いは、unset 呼び出しが追加されたことです。そして、 unset 呼び出しのの回線でエラーが発生します!

    public function getRedirect1()
    {
        //Make sure we have a session
        session_start();

        //This should exist, but it throws an index error
        $redFrom = $_SESSION[ self::$SESSION_VARIABLE ];

        //Unset it
        unset( $_SESSION[ self::$SESSION_VARIABLE ] );

        return $redFrom;
    }

    public function getRedirect2()
    {
        //Make sure we have a session
        session_start();

        $redFrom = $_SESSION[ self::$SESSION_VARIABLE ];

        return $redFrom;
    }
4

2 に答える 2

0

__sleep と __wakeup() を見てみましょう。 http://php.net/manual/en/oop4.magic-functions.php

私があなたを正しく理解しているなら、あなたは次のようなことをしたいと思っています:

<?php
session_start();

class LandingRedirector
{
    private $file = "red.php";

    function __sleep()
    {
        return array('file'); //Which variables you want to store when object do the serialization
    }

    function __construct() {}

    public function redirect()
    {   
        //Redirect to correct page
        //header( "HTTP/1.1 301 Moved Permanently" );
        header( "Location: end.php" );
        exit;
    }

    public function setFile($nFile) {
        $this->file = $nFile;
    }

    public function getRedirect()
    {                   
        return $this->file;
    }
}

//Create new object if session does not exist. If it exist, then unserialize it
if (!isset($_SESSION['redirector'])) {
    $redirector = new LandingRedirector();
    $redirector->setFile('sausage.php');
    $_SESSION['redirector'] = serialize($redirector); //This calls __sleep() and serialize current object (or parts of it)
}
else {
    $redirector = unserialize($_SESSION['redirector']); //Unserialize will call __wakeup()
}
//Create

//Redirect
if ( !isset( $stopHere ) || $stopHere != true ) $redirector->redirect();
?>

end.php の getRedirect() の出力は、sausage.php になります。

于 2013-04-20T05:20:52.690 に答える
0

Google Chrome はページを 2 回要求しています (応答を高速化するためにこれを行います)。

これはばかげた解決策ですが、私が仕事に取り掛かることができる唯一の解決策です。

他の 2 つのセッション変数を作成して、これが永久に true を返し続けないようにし、2 番目のチェックも設定解除できるようにする必要があることに注意してください。

<?php
class LandingRedirector
{
    private static $SESSION_VARIABLE = "redirectedFrom";
    private static $CHROME_SESSION_VARIABLE = "redirectedFromChrome";
    private static $CHROME_SESSION_VARIABLE_TO_READ = "redirectedFromChromeRead";

    function __construct() {}

    public function redirect()
    {
        //Make sure we have a session
        session_start();

        //Set the redirect variable
        $_SESSION[ self::$SESSION_VARIABLE ] = "red.php";
        $_SESSION[ self::$SESSION_VARIABLE ] = "red.php";

        session_write_close();

        //Redirect to correct page
        header( "HTTP/1.1 301 Moved Permanently" );
        header( "Location: /end.php" );
        exit;
    }

    public function setonly()
    {
        //Make sure we have a session
        session_start();

        //Set the redirect variable
        $_SESSION[ self::$SESSION_VARIABLE ] = "red.php";

        session_write_close();
    }

    public function getRedirect()
    {
        try
        {
            //Make sure we have a session
            session_start();

            //It's set
            if ( isset( $_SESSION[ self::$SESSION_VARIABLE ] ) )
            {
                $redFrom = $_SESSION[ self::$SESSION_VARIABLE ];

                //This is to deal with Chrome's double request bug
                $_SESSION[ self::$CHROME_SESSION_VARIABLE ] = $redFrom;
                $_SESSION[ self::$CHROME_SESSION_VARIABLE_TO_READ ] = $redFrom;

                //Unset it
                unset( $_SESSION[ self::$SESSION_VARIABLE ] );

                return $redFrom;
            }

            //Not set, but is this a Chrome second request?
            else if ( isset( $_SESSION[ self::$CHROME_SESSION_VARIABLE ] ) )
            {
                $redFrom = $_SESSION[ self::$CHROME_SESSION_VARIABLE_TO_READ ];

                //Unset the one we check
                unset( $_SESSION[ self::$CHROME_SESSION_VARIABLE ] );

                return $redFrom;
            }
        }
        catch (Exception $e) {}

        return null;
    }
}

//Create
$redirector = new LandingRedirector();

//Redirect
if ( !isset( $stopHere ) || $stopHere != true ) $redirector->redirect();
?>
于 2013-04-20T06:20:59.430 に答える