Impressum · Kontakt · Hilfe
Besucher online · Mitglieder



Antwort
 
Themen-Optionen
Alt 01.11.2006, 10:56   Nach oben    #1
Artemis
Semantic Web Fanatic
 
Benutzerbild von Artemis
 
Registriert seit: 03.06.2006
Beiträge: 237
Standard Verständnisfrage - MVC (Model-View-Controller)

Moin,

ich habe vor, mein Projekt auf Basis des MVC-Musters zu erstellen.
Deshalb frage ich mich, ob ich das ganze auch richtig verstanden habe.

Dazu habe ich dieses kleine Beispiel geschrieben.
PHP-Code:
<?php

class Model_Search
{
    function 
getResults($search)
    {
        
// do some db queries
        
        // fill result array with values - here only for demonstration
        
$search_result = array();
        
$search_result[] = 'Testseite 1'
        
$search_result[] = 'Testseite 2';
        
        
//return values 
        
return $search_result;
    }
}

class 
View_Search
{
    function 
displaySearchForm()
    {
        
// do some stuff and put out the search form
    
}
    
    function 
displayResults($results)
    {
        
// do some stuff and display the values of $results
    
}
}

class 
Controller_Search
{
    function 
checkSearch()
    {
        
// check $_POST values
        
        // if all values are ok then query results and display them
        
if ($valuesAreOk)
        {
            
$results Model_Search::getResults($search);
            
View_Search::DisplayResults($results);
        }
        
// else show the search form
        
else
        {
            
View_Search::DisplaySearchForm();
        }
    }
}

?>
Meine Frage ist nun:

Habe ich das ganze richtig verstanden, oder müsste das ganze anders aussehen?

Thx, Artemis
__________________
Applikations-Programmierung:
BlitzMax, BlitzPlus

Webentwicklung:
PHP, (X)HTML, CSS, JavaScript, MySQL


Artemis ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 01.11.2006, 13:01   Nach oben    #2
Basti
Erfahrener Benutzer
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 781
Standard

Hi.

Jo, so etwa kann man das machen. Ich hatte zuerst auch für jede Komponente (MVC-Einheit) je eine Model-Klasse definiert. Das ist aber quatsch, weil man ständig nur rumkopiert. Das Model ist das Datenmodell und es ist geschickt, wenn der Controller dieses direkt ansteuert. Also nicht eine "Model-Klasse", sondern eben alle Objekte, mit denen er arbeitet. (Siehe Beispiel unten)

Dann finde ich es geschickt, wie z.B. bei Symfony die Daten den Views nicht per Parameter zugänglich zu machen, sonden, indem du sie als öffenliche Attribute in den Controllern definierst. In den Views kannst du dann über eine Methode (im einfachsten Fall __get()) direkt auf diese Werte zugreifen (die Methode kodiert diese ggf. um und den Aufruf kannst du z.B. über deine Template-Engine lösen, so dass der Template-Designer nichts davon mitbekommt). Dazu ist es natürlich nötig, dass die View seinen Controller kennt oder irgendwie drauf zugreifen kann. Mit Statischen Klassen ist da also nichts mehr.

Weiter macht es Sinn, im Controller die View nur auszuwählen und diese Auswahl als Rückgabewert zurückzugeben. Mitunter willst du ja nichts anzeigen, sondern einen Redirect machen oder die Anfrage an eine andere Komponente weitergeben. Die Controller zeigen die Views also nicht an, sondern wählen diese nur aus.

Und, weiter wirst du Komponenten auch in einem Baum organisieren wollen, so dass jede Komponente Unterkomponenten einbinden kann. Auch hierfür ist es eben wichtig, dass die Komponente ihre View nicht selbst ausgibt, denn eine Komponente "Page", deren Methode "edit" aufgerufen wurde, könnte z.B. mehrere Komponenten einbinden (z.B. PageImage, Text, Attachments) und kann dann ja erst nach Abarbeitung der letzten Unterkomponente feststellen, dass der Benutzer alles korrekt eingegeben hat. Hier wird sie also einen Redirect machen, andernfalls die Komponenten nochmal anzeigen, um das Formular korrigieren zu können.

Beispiel:
PHP-Code:
<?php

class Component_Page_Controller extends Controller
{
    public 
$Page// oeffentliche Variable fuer die View

    
public function __construct()
    {
        
$sPageId $this->Request->get('page');
        
$this->Page $this->Persistence->get('Page'$sPageId);  // oder wer auch immer dir die DataObjects bereitstellen kann
    
}

    public function 
action_display()
    {
        return 
$this->view(); // ohne Parameter = default view
    
}

    public function 
action_edit()
    {
        if (
$this->Request->get('save')) {

            
$this->Page->set($this->Request['pagedata']);
            if (
$this->Page->isValid()) {
                
$this->Page->save();
                return 
$this->redirect($this->sPageId, array('message' => 'edit_success'));
            }
        }
        return 
$this->view('EditForm');
    }
}
?>

Page.tpl

<h1><?php echo $this->Page->title?></h1>
<div><?php echo $this->Page->content?></div>

Page_EditForm.php
<form ...>
<?php if (!$this->Page->isValid()) { ?>
    <div class="error">
        <h2>Fehler!</h2>
        <ul>
<?php foreach($this->Page->getErrors as $sError?>
            <li><?php echo $sError?></li>
<?php ?>
        </ul>
    <iput type="text" name="pagedata[title]" value="<?php $this->Page->title?>"/>
    <textarea name="pagedata[content]"><?php echo $this->Page->content?></textarea>
</form>
So etwa könnte das dann aussehen ... natürlich einfacherer mit einer Template-Engine, die dann obigen Template-Code produziert bzw. dann auch ohne __get() die Werte eben über bestimmte Methoden aus dem Controller zieht und Fehler im Template entsprechend behandelt (z.B. nicht gesetzte Properties oder eine Variable für eine Schleife, die kein Array enthält).

Eigentlich reicht auch ein Template als View. Eine Klasse würde ich dann verwenden, wenn hier nochmal bestimmte Daten aus dem oder zusammengetragen oder umgeschrieben weden sollen. Der einzige Zweck läge dann darin, das Template abzuspecken und dem Template-Designer bestimmte Flags etc. zur Verfügung zu stellen.

Natürlich kann dann in so einer View-Klasse z.B.die display-Methode überschrieben werden, so dass garkein Tempalte eingebunden wird, sondern die Daten irgendwie anders ausgegeben werden.

Basti

Geändert von Basti (03.11.2006 um 15:34 Uhr).
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 01:11   Nach oben    #3
Basti
Erfahrener Benutzer
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 781
Standard

Zitat:
Zitat von Basti Beitrag anzeigen
Dann finde ich es geschickt, wie z.B. bei Symfony die Daten den Views nicht per Parameter zugänglich zu machen, sonden, indem du sie als öffenliche Attribute in den Controllern definierst. In den Views kannst du dann über eine Methode (im einfachsten Fall __get()) direkt auf diese Werte zugreifen (die Methode kodiert diese ggf. um und den Aufruf kannst du z.B. über deine Template-Engine lösen, so dass der Template-Designer nichts davon mitbekommt). Dazu ist es natürlich nötig, dass die View seinen Controller kennt oder irgendwie drauf zugreifen kann. Mit Statischen Klassen ist da also nichts mehr.
Ich frag mich, wie man hier die Unabhängigkeit der Views von den Controllern noch weiter treiben kann. Eigentlich greift die View ja nur auf die Modell-Schicht zu und garnicht auf die Controller. Aber mir ist noch nicht ganz klar, wie sich das umsetzen lässt. Hat da jemand einen gescheiten Ansatz? Alles in die Session oder irgendweinen Container zu packen ist ja auch nichts anderes, als obige Lösung in grün.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 04:42   Nach oben    #4
WarrenFaith
Mensch
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.710
Standard

Zitat:
Ich frag mich, wie man hier die Unabhängigkeit der Views von den Controllern noch weiter treiben kann. Eigentlich greift die View ja nur auf die Modell-Schicht zu und garnicht auf die Controller.
Wasn nun?
Sinn von MVC ist doch, dass View und Model sich nicht kennen und alles nur über den Controller passiert. Demzufolge darf es nur einen Weg geben: Der Controller holt sich Daten aus dem Model und gibt sie dem View.
Zitat:
In den Views kannst du dann über eine Methode (im einfachsten Fall __get()) direkt auf diese Werte zugreifen (die Methode kodiert diese ggf. um und den Aufruf kannst du z.B. über deine Template-Engine lösen, so dass der Template-Designer nichts davon mitbekommt).
Nehmen wir an du willst ein Datum ausgeben. Jetzt müsstest du festlegen, ob das View oder das Model den Timestamp zur Ausgabe in ein "human readable" Format umformt. Das wäre aber definitiv keine Aufgabe für Model oder View, also nur für den Controller.
Zitat:
Dazu ist es natürlich nötig, dass die View seinen Controller kennt oder irgendwie drauf zugreifen kann.
Ne der Controller kennt View und Model; und Model und View kennen nichts!
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 10:28   Nach oben    #5
Artemis
Semantic Web Fanatic
 
Benutzerbild von Artemis
 
Registriert seit: 03.06.2006
Beiträge: 237
Standard

Jo, ich denke auch das das so abläuft:
Controller holt sich die Daten aus dem Model, verarbeitet sie und gibt sie dann an den View weiter, welches alles ausgibt.

Dafür müsste nur der Controller wissen, welches Model und welchen View er braucht.
__________________
Applikations-Programmierung:
BlitzMax, BlitzPlus

Webentwicklung:
PHP, (X)HTML, CSS, JavaScript, MySQL


Artemis ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 14:45   Nach oben    #6
Basti
Erfahrener Benutzer
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 781
Standard

Zitat:
Zitat von WarrenFaith Beitrag anzeigen
Zitat:
Ich frag mich, wie man hier die Unabhängigkeit der Views von den Controllern noch weiter treiben kann. Eigentlich greift die View ja nur auf die Modell-Schicht zu und garnicht auf die Controller.
Wasn nun?
Sinn von MVC ist doch, dass View und Model sich nicht kennen und alles nur über den Controller passiert. Demzufolge darf es nur einen Weg geben: Der Controller holt sich Daten aus dem Model und gibt sie dem View.
Nein, das hast du falsch abgespeichert. Im klassischen MVC holt sich die Präsentationsschicht die Daten prinzipiell aus dem Modell. Der Controller gibt ihr (in der passiven Variante) lediglich die Info, dass er etwas am Modell geändet hat und dass sie sich selbst aktualisieren soll. Im aktiven Modell gibt es noch nichtmal diese Info vom Vontroller, sondern die Views beobachten die für sie relevanten Teile des Models und aktualisieren sich selbst.

Im PHP-Anwendungen ist diese Architektur natürlich quatsch, es sei denn, man speichert den Status (Viewstate), wie z.B. Prado in der Session.

Ich frag mich halt nach einem tauglichen Weg. Denn einerseits finde ich es reizvoll, wenn die Controller den Views nicht alles "vorkauen" müssen (also alle Daten, die diese verwenden können zuvor bereitstellen), auf der anderen Seite ist das mitunter aber der einfachste Weg.

Zitat:
Zitat:
In den Views kannst du dann über eine Methode (im einfachsten Fall __get()) direkt auf diese Werte zugreifen (die Methode kodiert diese ggf. um und den Aufruf kannst du z.B. über deine Template-Engine lösen, so dass der Template-Designer nichts davon mitbekommt).
Nehmen wir an du willst ein Datum ausgeben. Jetzt müsstest du festlegen, ob das View oder das Model den Timestamp zur Ausgabe in ein "human readable" Format umformt. Das wäre aber definitiv keine Aufgabe für Model oder View, also nur für den Controller.
Zitat:
Dazu ist es natürlich nötig, dass die View seinen Controller kennt oder irgendwie drauf zugreifen kann.
Ne der Controller kennt View und Model; und Model und View kennen nichts!
Doch, View kennt Model, denn daher bezieht es seine Daten. So zumindest im klassischen MVC-Pattern. Diese Methode oben wäre quasi eine Art Request-Model, auf die die Views zugreifen. Dass die Daten vom Controller kommen bräuchte die View garnicht interessieren. Aber eben - diese Daten müssen wüssten eigentlich in die Modell-Schicht, aber da fällt mir noch kein besonders sinniger Weg ein.

Zitat:
Zitat von Artemis Beitrag anzeigen
Jo, ich denke auch das das so abläuft:
Controller holt sich die Daten aus dem Model, verarbeitet sie und gibt sie dann an den View weiter, welches alles ausgibt.

Dafür müsste nur der Controller wissen, welches Model und welchen View er braucht.
Ja, das ist die klasische Smarty-Vorgehensweise, ist aber nicht MVC. Ist ja auch letztlich Wurscht, nur ertappe ich mich dabei, mitunter in den Controllern Daten aus dem Model zu holen, nur um sie dann in die View zu kopieren (alle Display-Actions machen nichts anderes, falls sie nicht noch andere Komponenten einbinden). Wäre ja einfacher, das im Template zu lösen.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 22:45   Nach oben    #7
WarrenFaith
Mensch
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.710
Standard

Zitat:
Zitat von Basti
Ist ja auch letztlich Wurscht, nur ertappe ich mich dabei, mitunter in den Controllern Daten aus dem Model zu holen, nur um sie dann in die View zu kopieren
Hm, also bisher sind meine MVC-Vorgehensweisen genau so gewesen, nur das der Controller die Daten aus dem Model noch zurechtmacht (formatiert etc) bevor er sie ans View weiterleitet.
Ich werde mal nach einer gescheiten "Anleitung" bzw Einführung ins MVC suchen und dann hier mal vorstellen und diskutieren.
Mal wieder interessantes Thema
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 12.11.2006, 23:25   Nach oben    #8
Basti
Erfahrener Benutzer
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 781
Standard

Hi.

Ich denke, es ist in der PHP-Welt auch absolut üblich, es so zu machen, dass die Controller eben die Daten für die Views zusammenstellen. Zumindest Symphony, WACT, CAKE und andere machen es so. Ob die jeweils noch Mechanismen bieten, direkt auf das Model zuzugreifen, weiß ich nicht. Letztlich ist das ja auch in Ordnung bzw. tauglich und bieet den großen Vorteil, dass Template-Designer nur Zugriff auf Daten haben, die ihnen auch bereitgestellt werden (was natürlich auch wieder ein Nachteil sein kann, wenn ein Entwickler einbezogen werden muss, wenn der Designer da noch eine Info mehr reisetzen mag, die er sich eigentlich selbst aus dem Model ziehen könnte).

Übrigens ist die Darstellung der Zeit in meinen Augen absolut die Aufgabe der View und nicht der Controller. Das Formatieren allgemein packe ich grundsätzlich in die View. Woher soll denn der Controller wissen, ob die Site nachher z.B. utf-8-codiert ist oder in latin 1?

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 13.11.2006, 10:05   Nach oben    #9
WarrenFaith
Mensch
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.710
Standard

Zitat:
Woher soll denn der Controller wissen, ob die Site nachher z.B. utf-8-codiert ist oder in latin 1?
Weil der Controller das festlegt
Also ich arbeite so, dass das View die Daten wirklich nur ausgibt. Aufbereitet werden sie über den Controller, denn nur der weiß, in welcher Lokalisierung er die Daten dem View zur Verfügung stellen soll.
Sonst müsste die View ja viel mehr als nur Contentdaten noch vom Model beziehen. Und das würde in meinem Verständnis eher die Rolle des Controllers, der ja nicht nur Datenfluß sondern auch Datenart kontrollieren soll deutlich schmälern. Ich seh da halt nicht dieses Dreipunktekonstrukt sondern eher 3 Schichten in denen der Controller in der Mitte liegt.
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 13.11.2006, 11:05   Nach oben    #10
Basti
Erfahrener Benutzer
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 781
Standard

Das heißt aber auch, dass du für jede Kodierung je einen Controller brauchst. Das Ganze dann einmal für HTML, einmal für WAP und einmal für Atom oder so...

Ich denke als "Datenart" kann man auch z.B. einen i18n-String oder ein "l10n-Zeitstempel" verstehen. Ich weiß aber noch nicht, was da für mich am Geschicktesten ist. Ich verwende da im Moment eine arge Mischform und bin ständig am umbauen.

Was den Punkt Schichten vs. Punkte angeht, so hat das mit der Thematik aber nichts zu tun. Hierbei geht es ja nur darum, woher die View die Daten bezieht, also ob (ausschließlich) vom Controller oder aus den Models. Der Punkt hier ist ja der, in wie weit die Controller die Daten für die View aufbereiten bzw. ob es die Aufgabe der Controller ist, diese überhaupt irgendwie aufzubereiten, anstatt sie einfach als blanke Datenobjekte zu übergeben.

Mal weg davon, was MVC bzw. Model 2 bedeutet hin dazu, was taugt, würde ich die Verantwortung für die Darstellung trotzdem in jedem Fall in die View-Schicht packen. Das ist bei lokalisierten Datumsormaten für mich eindeutig, z.B. bei mehrsprachigen Texten wiederum nicht so ganz. Ein häufig erwähnter Punkt in dieser Diskussion ist ja z.B. die Sortierung von Listen oder das Aufteilen von Listen auf mehrere Seiten. Eigentlich ganz klar Aufgabe der View, aber prakisch eben mitunter ungünstig, das so umzusetzen. Zumindest, wenn die Controller die Daten zur Verfügung stellen müssten diese ja prinzipiell alle Daten (die komplette Liste) auslesen und das ist ja nicht vertretbar.

Ganz gute Diskussion zur Entwicklung der MVC-Konfusion *g, aber sicher schon bekannt:
http://c2.com/cgi/wiki?WhatsaControllerAnyway

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 13.11.2006, 11:21   Nach oben    #11
WarrenFaith
Mensch
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.710
Standard

Zitat:
Das Ganze dann einmal für HTML, einmal für WAP und einmal für Atom oder so...
Der Controller sagt: die Daten in dem Format und dann das View (WAP, HTML, XML, PDF, ...)
View nimmt die Daten und füttert damit seine Templates oder was auch immer benutzt wird.
Die Steuerung der View übernimmt aber auch der Controller, meiner Meinung nach. Aber da scheiden sich wahrscheinlich wieder die Geister

Zum Link: zu lang für die Arbeit aber für daheim sicher lesenswert
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.12.2006, 11:57   Nach oben    #12
ex³
Erfahrener Benutzer
 
Registriert seit: 30.10.2005
Beiträge: 274
Standard

Hallo ich hab selbst mal mit MVC rumprobiert, vielleicht könnt ihr euch mal dazu äußern. Ein News Bereich o. ä. ist nicht vielleicht nicht gerade ein Paradebeispiel, aber schaut euch das mal an und kommentiert was dazu.

Dann wäre nochwas
Wie bringt man in diesem Konzept denn ein error handling mit exception am geschicktesten unter?
und ist es wirklich nötig Funktionen,etc. statisch zu machen oder mit Referenzen zu arbeiten also :: oder &=
Ich denk doch mit PHP5 ist das doch egal oder

PHP-Code:
<?php
class NewsView {

    public function 
getView(Array $newsposts) {
        echo 
'<pre>';
        
print_r($newsposts);
        echo 
'</pre>';
    }
}
?>
PHP-Code:
<?php
class NewsModel {

    private 
$mdb2 null;

    public function 
NewsModel(MDB2_Driver_Common $mdb2) {
        
$this->mdb2 $mdb2;
    }

    public function 
getNewsposts() {
        
$data $this->mdb2->queryAll('SELECT n.id, n.seo, n.title, n.post, n.postdate, n.author, ' .
        
'COUNT(c.id) AS comments ' .
        
'FROM newspost AS n ' .
        
'LEFT JOIN newscomment AS c ON n.id = c.newsid ' .
        
'WHERE n.postdate < ' $this->mdb2->quote(time()) . ' AND n.textstatus = 1 ' .
        
'GROUP BY n.id ' .
        
'ORDER BY n.postdate DESC LIMIT 0, 5');

        if (
PEAR :: isError($data)) {
            die(
$data->getMessage() . ' - ' $data->getUserinfo());
        }

        return 
$data;
    }
    

}
?>
PHP-Code:
<?php

require_once 'lib/NewsModel.php';
require_once 
'lib/NewsView.php';

class 
NewsController {

    private 
$model null;
    private 
$view null;
    
    public function 
NewsController(MDB2_Driver_Common $mdb2) {
        
$this->model = new NewsModel($mdb2);
        
$this->view();
    }
    
    public function 
view() {
        
$this->view = new NewsView();
        
        
$newsposts $this->model->getNewsposts();
        
        
$this->view->getView($newsposts);
    }
}
?>
ex³ ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.12.2006, 12:06   Nach oben    #13
Chr!s
Erfahrener Benutzer
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Grundsätzlich ist es beim MVCModell so, dass du ein View, ein Controller und ein Model hast. Hier mögen die Geister zwar schon ausseinandergehn, jedoch halt ich dies sehr sinnvoll. Die News von denen du sprichst, wäre dann ein "Modul".

Du kannst soviele Module haben wie du möchtest und brauchst - es existiert dennnoch nur ein View, ein Model und ein Controller.
Dein Modul macht dann z.B. folgendes:
PHP-Code:
<?php
class Modul_news {
        public function 
renderNewsOfTheDay() {
                
$this -> oModel -> fetch("SELECT ...");
                
// Daten verarbeiten

                
$this -> oView -> load('newsOfTheDay.tpl');
                
$this -> oView -> assign('...''..');
                
$this