[Ajax] Yii interne Umleitung abfangen(->zum Login)

Hallo Yii-Community,

Ich steh vor einem kleinen Problem.

Ziel:

Dynamisches laden einer controller/action Seite in den <div id="content">, ohne das neu Laden der gesamten Seite.

Aktuelle Lösung:

JavaScript Code:




$( "a" ).click(function(event){

    event.preventDefault();

    url = $(this).attr("href");

    cache.lastUrl = url;

    $.ajax({

        url: url,

        dataType: "xml",

        data:{

            ajax: "xmlPage"

        },

        type: "post",

        success: function(d){

            /**

             * handle xml

             */

        },

        error: function(){

            /**

             * use normal method on ajax error

             */

            location.href = cache.lastUrl

        }

    });

});



Der meiner Controller Class überprüfe ich in der berforAction() function ob die gesamte Seite oder nur der Content gebraucht wird. Wenn ja wird einfach das Layout geändert.


if(isset($_POST['ajax']) && $_POST['ajax'] == "ajaxPage"){

            Yii::app()->clientScript->enableJavaScript = false;

            $this->layout = "//layouts/ajax";

        }

Problem:

Prinzipiell funktioniert das ganze. Im Fall das die Response nicht vom jQuery verarbeitet werden kann wird der Benutzer direkt an die Seite weitergeleitet.

So aber das eigentliche Problem ist. Wenn ich zum Beispiel auf diese Art eine Seite laden möchte, welche Benutzerrechte benötigt, will Yii automatisch auf die Loginseite weiterleiten. Das Resultat ist, das jQuery mit der Umleitung nicht zurecht kommt, da der POST verloren geht und die neue Anfrage nicht weiß das sie eigentlich eine ajaxPage(Nur Content ohne alles) sein sollte.

Resultat ist das jQuery einfach auf die Loginseite weiterleitet. Nur hätte ich gerne das ganze dynamisch.

Nun die Frage:

Wie fange ich die Umleitung von Yii ab? BeforeAction wird in diesem Falle erst gar nicht aufgerufen. Und ein richtigen Ansatz dafür ist mir noch eingefallen.

Ich hoffe Ihr könnte mir folgen.

mfg Excid

Guck dir mal die Methode CWebUser::loginRequired() an. Die kannst du so überschreiben das bei einem Ajax-Request z.B. ein JSON-String ausgegeben wird (anstatt redirect zur Login Seite).

Die Idee ist gut.

Nur komme ich dann zu einem neuen Problem.

Meine Idee war ja einfach den SourceCode von Yii zu übernehmen und wenn mein Ajax gefragt ist anstatt die Funktion Redirect die Funktion Forward aufzurufen. Nur hat die Klasse CHttpRequest nur Redirect und kein Forward. Was auch eigentlich logisch ist da ja nur ein Controller eine Anfrage an einen anderen Controller weiterreichen dürfte.

Eine Idee wäre selbst den Controller zu erstellen und aufzurufen. Aber ich hab das Gefühl dass es einfacher geht.

Wahrscheinlich müsste ich einfach nur den Request überschreiben. Aber ich stehe auf den Schlauch.

Werde mich Morgen Früh nochmal durch die Doc forsten. Aber vielleicht habt ihr ja direkt ne Idee oder nen Ansatz.

Wenn nicht hmm. Im Grunde ist das Problem auch nur ein Schönheitsfehler. Wäre aber schön wenn es dafür eine sinnvolle Lösung gäbe.

mfg Excid

Wenn ich dich richtig verstanden habe müsste das doch klappen:




public function loginRequired()

{


   if (Yii::app()->request->isAjaxRequest)

   {

      Yii::app()->controller->forward($this->loginUrl);

   }


   parent::loginRequired();


}

Funktioniert nicht.

Yii::app()->controller = NULL.

Hmm muß mich wohl mal in Ruhe am Sonntag durch den Source Code von Yii forsten. Vielleicht finde ich ja die Lösung und den Grund warum der Controller nicht initialisiert und gesetzt wurde.

Ich danke aber trotzdem für die 2 Tipps. Von der Herangehensweise bin ich weiter gekommen…

mfg Excid

Sollte eigentlich funktionieren, habe es gerade nochmal getestet.

Bin auch verwundert wieso es nicht funktioniert.

Ich habe das erstmal so gelöst. Es geschieht jetzt trotzdem ein Redirect, nur wird noch ?ajaxPreload=1 rangehangen.

In der neuen Anfrage wird der Controller dann auch korrekt geladen und ich kann in der beforAction Funktion nach der ?ajaxPreload=1 schauen. Ist sie gesetzt wird das Layout auf "ajax" gesetzt.

Mir gefällt zwar die Lösung noch nicht so sonderlich. Aber es funktioniert.

Werde trotzdem nochmal die Ursache suchen. Vielleicht liegt mein Problem auch ganz wo anders.


    public function loginRequired()

    {

        $app=Yii::app();

        $request=$app->getRequest();

        if (isset($_POST['ajax']) && $_POST['ajax'] == "preload")

        {

            if(($url=$this->loginUrl)!==null)

            {

                if(is_array($url))

                {

                        $route=isset($url[0]) ? $url[0] : $app->defaultController;

                        $url=$app->createUrl("user/login",array_splice($url,1));

                }

                $request->redirect($url."?ajaxPreload=1");


            }

        }

        else

            parent::loginRequired();

    }

mfg Excid