Portal > Foren > PHP > PHP-Programmierung > Unterscheidung zwischen User und JavaScript Request im Controller
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 23.06.2007, 19:55 Nach oben    #1
Neuer Benutzer
 
Registriert seit: 23.06.2007
Beiträge: 13
Standard Unterscheidung zwischen User und JavaScript Request im Controller

Hey!

Ich habe folgendes Problem:

Mein Controller hat verschiedene Methoden z.B. validate und insert. Jede Methode hat gemeinsam, dass via $view->assign ("key", "value"); daten an den view übergeben werden und am Ende $view->render (...); aufgerufen wird. Das funktioniert super wenn ich ohne AJAX arbeite. Wenn ich aber AJAX verwende will ich nur, dass die Daten zurückgegeben werden z.B. bei valid Fehlermeldungen und bei insert eine Erfolgsmeldung und nicht, dass mir hier der View die komplette Seite gerendert zurückgibt und ich mir mit JavaScript die Infos selbst rausparsen kann .

In Code würde ein Controller so aussehen:

PHP-Code:
<?php
class Controller {
     public function 
sthAction () {
         
$view $this->getViewInstance ();

        
// Logik

         
$view->render ("some/template");
    }
}
Jetzt hab ich mir gedacht ich schreibe mir für jeden Controller eine Hilfsklasse die die gesamte Logik enthält und dann im Controller instanziert wird und von der die View Komponente die Daten bekommt.
Somit könnte ich mir nen XML-RPC oder JSON-RPC Server schreiben, an dem meine AJAX Requests gehen und der dann eben wirklich nur die für den AJAX Request relevanten Daten zurückgibt.

Was haltet ihr davon bzw. wie habt ihr das Problem gelöst und was kann man an der Idee verbessern?

-- Peter
pmayer ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 23.06.2007, 23:42 Nach oben    #2
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 853
Standard

Hi Peter.

Was heißt denn für dich "Logik"? Sieht so aus, als hättest du deine Controller mit Funktionen überfrachtet, die eigentlich in der Model-Schicht sinnvoller aufgehoben wären. Das Validieren und Einfügen von Daten gehört doch in die Datenschicht. Der Controller gibt die Daten nur aus dem Request weiter, schaut, was passiert und reagiert entsprechend (z.B. mit einer erneuten Anzeige mit Fehlermeldung oder einem Redirect bei Erfolg).

Auch ist es nach meiner Erfahrung wenig sinnvoll, das Rendern der View im Controller zu veranlassen.

Konkret zu deinem Problem denke ich, dass du nur entweder zwei Controller bauen musst, oder deine Architektur so umbauen musst, dass dein System auch bei einer "normalen" Anfrage wie ein Ajax-System funktioniert, dass du also den Status der View speicherst und in den Controllern eben auch nur die Veränderungen durchgibst (siehe z.B. PRADO oder auch der aktuelle Thread hier im Forum zu diesem Thema).

Ein anderer Weg, der mir gerade kommt ist, den Views so zu erweitern, dass sie in der Lage sind, die Daten direkt aus dem Request zu beziehen bzw. quasi als halbe Umsetzung der Speicherung der ViewStates könntest du Widgets in die Views setzen und noch vor dem Ansprechen der Controller erstmal alle Request-Daten quasi zurück durch die Widgets jagen, damit du diese eben gar nich nochmal neu füttern musst:

PHP-Code:
class Register
{
    public function 
init()
    {
        return 
$this->createView('RegisterForm');
    }

    public function 
execute($View)
    {
        
$Form $View->get('form');

        if (
$Form->sent()) {

            
$User User::create($Form->userdata);

            if (
$User->isValid()) {

                
$User->save();
                return new 
Redirect('user.prefereces', new Message('user''register_success'));

            }
        }

        if (isset(
$User) {

            
// sowas waere dann halt nicht mehr noetig:
            // $View->assignDataObject('userdata', $User);
            
$Form->setMessage(new Message('user''register-invalid'));
            
$Form->setErrors($User->getErrors);
        }
        return 
$View;
    }

Je nach FrontController werden hier halt andere Views geladen (View_User_RegisterForm_Ajax, View_User_RegisterForm_Html), die dann eben auch andere Methoden anbieten (die natürlich in abstrakten Klassen gekapselt sind). Einmal werden die Widgets manipuliert (HTML) und im anderen Fall werden eben die Daten gesammelt und als XML-Response an den JavaScript-Client geschickt.

Irgendwie so vielleicht?

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 11:21 Nach oben    #3
Neuer Benutzer
 
Registriert seit: 23.06.2007
Beiträge: 13
Standard

danke für die antwort!

Ja so in der Art werde ich es auch machen d.h. den View über eine factory methode zu erzeugen, die dann aufgrund der HTTP Header entscheidet ob es ein XMLHttpRequest ist oder nicht und dann halt eine entsprechende unterklasse von View zurückgibt.

mfg peter
pmayer ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 16:20 Nach oben    #4
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 853
Standard

Zitat:
Zitat von pmayer Beitrag anzeigen
Ja so in der Art werde ich es auch machen d.h. den View über eine factory methode zu erzeugen, die dann aufgrund der HTTP Header entscheidet ob es ein XMLHttpRequest ist oder nicht und dann halt eine entsprechende unterklasse von View zurückgibt.
Macht es nicht Sinn, diese Abfrage viel früher anzusiedeln bzw. je nach Methode einen eigenen FrontController anzubieten?

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 16:37 Nach oben    #5
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.516
Standard

Ich würd eher pro "Sektion" einen FrontController haben. Ist beim Zend Framework ja ähnlich gelöst.

Also, dass z.B. für .xy/blog/ BlogController, für .xy/search/ SearchController, ... verwendet wird.

Entschlackt das Ganze etwas und macht es in meinen Augen sehr, sehr übersichtlich und klar abtrennbar.
Ben ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 17:14 Nach oben    #6
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 853
Standard

Zitat:
Zitat von Ben Beitrag anzeigen
Ich würd eher pro "Sektion" einen FrontController haben. Ist beim Zend Framework ja ähnlich gelöst.

Also, dass z.B. für .xy/blog/ BlogController, für .xy/search/ SearchController, ... verwendet wird.

Entschlackt das Ganze etwas und macht es in meinen Augen sehr, sehr übersichtlich und klar abtrennbar.
Die Frage ist halt, worin sich "blog" und "search" unterscheiden. Wahrscheinlich wird doch der ganze Rahmen (HTML-Request bzw. -Kontext, gleiches Layout, gleiche Navigation, gleiches Rahmen-Template etc. - von übrigen Setup der Anwendung mal ganz abgesehen) identisch sein, was in meinen Augen keinen eigenen FrontController rechtfertigt.

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 17:20 Nach oben    #7
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.516
Standard

Wobei die Frage auftaucht, was ein FrontController ist.
Ist aber auch egal, will da an dieser Stelle gar nicht drüber diskutieren, weil es schlicht "Offtopic" wäre.
Ben ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 18:29 Nach oben    #8
Christian W. Achatz
 
Benutzerbild von dr.e.
 
Registriert seit: 05.02.2007
Ort: München
Beiträge: 150
Standard

Zitat:
Zitat von Ben Beitrag anzeigen
Wobei die Frage auftaucht, was ein FrontController ist.
<klugscheiß>Da muss ich wiedersprechen. Ein FrontController ist in seinem gleichnamigen Pattern klar definiert. Er übernimmt das Handeln von Requests und baut das Model der Applikation auf. Um einen View zu erzeugen verwendet man üblicherweise einen Controller im PageController-Stil.</klugscheiß>
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> http://adventure-php-framework.org)!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist gerade online  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 19:15 Nach oben    #9
Neuer Benutzer
 
Registriert seit: 23.06.2007
Beiträge: 13
Standard

Zitat:
Zitat von Basti Beitrag anzeigen
Zitat:
Zitat von pmayer Beitrag anzeigen
Ja so in der Art werde ich es auch machen d.h. den View über eine factory methode zu erzeugen, die dann aufgrund der HTTP Header entscheidet ob es ein XMLHttpRequest ist oder nicht und dann halt eine entsprechende unterklasse von View zurückgibt.
Macht es nicht Sinn, diese Abfrage viel früher anzusiedeln bzw. je nach Methode einen eigenen FrontController anzubieten?

Basti
Verstehe ich jetzt nicht ganz. Was soll das bringen? Meine gesamte Logik ist für jeden Request gleich, nur die Ausgabe ist eine andere und deshalb lad' ich halt nen eigenen View je nach Art des Requests.

Also meine getView() Methode sieht derzeit so aus:
PHP-Code:
abstract class Controller {
    public function 
getView ($template) {
        
$isAjax $this->request->isXmlHttpRequest ();

        if (
$isAjax) {
            return new 
JsonView ("UTF-8"$this->response);
        } else {
            return new 
HtmlView ("UTF-8"$template$this->response);
        }
    }
}

public abstract function 
execute (); 
und wird in der execute Methode aufgerufen:

PHP-Code:
class IndexController extends Controller {
    public function 
execute () {
        
$view $this->getView ("Index");
    }

Die JSON implementierung des Views sieht so aus:
PHP-Code:
class JsonView extends View {

    public function 
render () {
        
$result = new stdClass ();
        
$result->message $this->encode ($this->message);
        
$result->result  $this->encode ($this->result);

        foreach (
$this->errors as $key => $error) {
            
$this->errors[$key] = $this->encode ($error);
        }

        
$result->errors  $this->errors;

        
/**
         * @see http://www.ietf.org/rfc/rfc4627
         */
        
$this->response->setHeader ("Content-Type: application/json;charset={$this->settings["encoding"]}");
        echo 
json_encode ($result);
    }

und die isXmlHttpRequest Methode des Request objekts sieht so aus:

PHP-Code:
 class HttpRequest extends Request {

    public function 
__construct (array $filters = array ()) {
        
parent::__construct (array_merge ($_REQUEST$_FILES), $filters);
    }
    ...
    public function 
isXmlHttpRequest () {
        return isset (
$_SERVER["HTTP_X_REQUESTED_WITH"]) &&
               
$_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest";
    }

Ist eine solche Lösung denn gut?

MfG Peter
pmayer ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 21:08 Nach oben    #10
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 853
Standard

Zitat:
Zitat von pmayer Beitrag anzeigen
Zitat:
Zitat von Basti Beitrag anzeigen
Zitat:
Zitat von pmayer Beitrag anzeigen
Ja so in der Art werde ich es auch machen d.h. den View über eine factory methode zu erzeugen, die dann aufgrund der HTTP Header entscheidet ob es ein XMLHttpRequest ist oder nicht und dann halt eine entsprechende unterklasse von View zurückgibt.
Macht es nicht Sinn, diese Abfrage viel früher anzusiedeln bzw. je nach Methode einen eigenen FrontController anzubieten?
Verstehe ich jetzt nicht ganz. Was soll das bringen? Meine gesamte Logik ist für jeden Request gleich, nur die Ausgabe ist eine andere und deshalb lad' ich halt nen eigenen View je nach Art des Requests.
Na, dann passt es doch. Ich konnte mir nur nicht vorstellen, dass hier der einzige Unterschied liegt. Bei mir sind die Komponenten und so auch die Views immer verschachtelt und im Falle eines Ajax-Requests müste der ganze andere Mist (Navigation etc.) ja nicht extra nochmal aufgebaut werden, aber das sind dann wohl einfach unterschiedliche Konzepte.

Eine Frage habe ich aber:
Was beinhaltet Controller::response?

Und, was den FrontController angeht, so ist das eben die eine Schnittstelle zwischen Server und Anwendung. Ich denke aber schon, dass es Sinn machen kann, hier je unterschiedlicher Verwendungsmethode (HTML, Ajax, CommandLine) je einen eigenen FrontController anzubieten. Mehr FrontController (also je "Sektion") kann ich nicht nachvollziehen. Wundert mich, dass das ZFW diesen Weg geht. Hast du, Ben, da ein konkretes Beispiel?

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 24.06.2007, 22:53 Nach oben    #11
Martin Eisengardt
 
Registriert seit: 30.03.2006
Ort: Pfinztal
Beiträge: 355
Standard

Zum Zend-Framework: Die FrontController sind ebend nicht klar definiert, da muss ich Ben uneingeschränkt recht geben (Zumindest nach meinem aktuellen Kenntnisstand). Auch die ganzen Tutorials und Artikel von IBM geben darüber keine Auskunft. Mag sein, dass ich was übersehen habe, aber das sei einmal dahingestellt. Andere Tutorials sollte man nicht als Referenz nehmen, denn die machen es ja, wie sie es selber interpretieren.

Fakt ist, dass das Zend Framework eine klare MVC-Trennung vorschreibt. Insofern sind die [Front]Controller also das, was sie vom Namen her sein sollten. Im Prinzip stellt sich nur die Frage, wie man das kapselt, also kapselt man es
- pro Webseite (also ein Controller für alles)
- pro Funktionalität (ein Controller pro Modul o.ä.)
- pro Ausgabeziel (ein Controller für HTML, eines für JSon/Ajax-Kombi)

Jeder mag es wohl so machen, wie er will. Fakt ist lediglich, dass man mit Ajax in leichte Schwierigkeiten kommt, das Design einzuhalten. Generiert man im gleichen Controller und bei gleicher Methode mal ein HTML anhand der Views, mal ein Ajax (ohne Views), hält man sich nicht mehr an die Definitionen des Zend Frameworks. Daher fällt das Beispiel "ein Controller, ein Action für alles" wohl weg.

Der aktuelle Thread, der oben angesprochen wurde ist übrigens [Design] CMS-System: Seitenstruktur


Ich mache genau sowas aktuell oder zumindest etwas, was vor einem analogen Problem stand. Ich habe einmal das initiale Betreten der Seite, bei der die Webseite aufgebaut werden soll und dann habe ich Ereignisse, die per WebRequest ausgelöst werden und sozusagen nur noch Deltas in Form von Anweisungen zurückschicken sollen, beispielsweise "Ändere Farbe auf XYZ in Komponente ABC".
__________________
Open Sourcing the Online Gaming Universe
PHP/SQL/Java/C++/Assembler.
Seit Jahren Mitglied und Entwickler in einem der wohl größten Java-Projekte der Welt: http://weblogs.java.net/blog/hansmul...e_desktop.html
mepeisen ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 25.06.2007, 22:03 Nach oben    #12
Neuer Benutzer
 
Registriert seit: 23.06.2007
Beiträge: 13
Standard

Zitat:
Eine Frage habe ich aber:
Was beinhaltet Controller::response?
Ein Response Objekt. Ist im Grunde das gleiche wie das Request Objekt nur eben für die Antwort d.h. ich kann darüber z.B. header manipulieren etc. Das hat eben den Vorteil, dass es das Unit Testing erleichtert. Also anstatt HttpRequest übergeb ich da dann halt ein CliRequest objekt, dass eben auch von Request erbt und hab da dann eine andere implementierung weil unter PHP CLI z.B. kann ich ja keine header senden....

MfG Peter
pmayer ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.06.2007, 10:18 Nach oben    #13
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 853
Standard

Danke. Was kann das Objekt noch, außer Header manipulieren?

Basti
Basti ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.06.2007, 19:34 Nach oben    #14
Neuer Benutzer
 
Registriert seit: 23.06.2007
Beiträge: 13
Standard

Du kannst damit auch die Ausgabe buffern d.h. die Klasse hat ein Attribut body und mittels appendBody/setBody kannst da was reinschreiben und durch flush alles ausgeben.

MfG Peter
pmayer ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
PingBacks sind an
RefBacks sind aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Logisches Problem beim einsatz von Ereignissen Prophet Allgemeine Java-Programmierung 19 05.06.2006 22:08
[PHP] FTP-Funktionen in PHP nutzen MrNiceGuy Tutorials 0 24.05.2006 14:18
Unterscheidung zwischen Groß-und Kleinschreibung beim Login cyberboy Datenbanken 6 22.12.2005 12:05


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:15 Uhr.


Powered by vBulletin® Version 3.7.4 (Deutsch)
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45