[Was ist MVC? 】
MVC ist ein Konzept, mit dem Sie „drei Teile (nämlich den vollständigen Namen von MVC, Modell, Ansicht und Controller)“ harmonisch kombinieren können, um eine komplexe Anwendung zu bilden. Ein Auto ist ein sehr gutes Beispiel für MVC im wirklichen Leben. Wenn wir uns ein Auto ansehen, schauen wir uns zwei Teile an: das Innere und das Äußere. Beides ist untrennbar mit einem Controller verbunden: dem Fahrer. Das Bremssystem, das Lenkrad und andere Steuerungssysteme stellen das Modell dar: Sie übernehmen die Steuerungsmethoden vom Fahrer (Controller) und wenden sie auf den Innen- und Außenbereich an (Ansicht).
[MVC im Web]
Die vom MVC-Framework abgedeckten Konzepte sind recht einfach und äußerst flexibel. Das Grundkonzept besteht darin, dass Sie über einen einzigen Controller (z. B. index.php) verfügen, der alle Anwendungen innerhalb des Frameworks steuert, die auf Parameteranforderungen basieren. Dieser Controller enthält normalerweise (mindestens) einen Parameter, der das Modell definiert, ein Ereignis und einen GET-Parameter. Auf diese Weise kann der Controller alle Anfragen bestätigen und die entsprechenden Ereignisse ausführen. Beispielsweise wird eine Anfrage wie diese /index.php?module=foo&event=bar wahrscheinlich verwendet, um eine Klasse namens foo zu laden und dann foo::bar()[was eine bar()-Funktion ist] auszuführen. Die Vorteile davon sind:
Die Pflege einer Schnittstelle für alle Anwendungen
und die Pflege unzähliger Codes in einer Anwendung ist sehr mühsam, da jeder Code seinen eigenen relativen Pfad, seine eigene Datenbankverknüpfung, seine eigene Überprüfung usw. hat. Dadurch ersparen Sie sich die Mühe und können Code zusammenführen und wiederverwenden
[Warum ein eigenes MVC-Framework erstellen? 】
Bisher habe ich nicht viele in PHP geschriebene MVC-Frameworks gesehen. Tatsächlich kenne ich nur eines – Solar, das vollständig in PHP5 geschrieben ist. Das andere ist Cake, das versucht, RoR (Ruby on Rails – ein Open-Source-Netzwerk-Framework für die Ruby-Sprache) von PHP zu sein. Ich selbst bin mit beiden Frameworks unzufrieden: Sie nutzen nicht den vorhandenen Code, der in PEAR, Smarty usw. enthalten ist; der aktuelle Cake ist immer noch relativ chaotisch; schließlich ist Solar ein Framework, das größtenteils von einer Person geschrieben wurde Ich habe nicht die Absicht zu sagen, dass sein Autor Paul kein guter Mensch oder guter Programmierer ist. Diese Fragen veranlassen Sie wahrscheinlich nicht dazu, sie zu leugnen, und die Chancen stehen gut, dass Sie sich überhaupt nicht darum kümmern. Aus diesem Grund bitte ich Sie, sie sich so oft wie möglich anzusehen.
[Alter Weg]
Wenn Sie ins Jahr 2001 zurückgehen und sich den von Ihnen geschriebenen Code ansehen, findet der Autor möglicherweise eine Datei namens template.txt, die so aussieht: www.phpv.net Bitte geben Sie die Quelle für den Nachdruck an
<?php
require_once('config.php'); // Andere Anforderungen, DB-Informationen usw.
$APP_DB = 'mydb';
$APP_REQUIRE_LOGIN = false; // Auf true setzen, wenn das Skript eine Anmeldung erfordert
$APP_TEMPLATE_FILE = 'foo.php'; // Smarty-Vorlage
$APP_TITLE = 'Meine Bewerbung';
if ($APP_REQUIRE_LOGIN == true) {
if (!isset($_SESSION['userID'])) {
header("Speicherort: /path/to/login.php");
Ausfahrt();
}
}
$db = DB::connect('mysql://'.$DB_USER.':'.$DB_PASS.'@localhost/'.$APP_DB);
if (!PEAR::isError($db)) {
$db->setFetchMode(DB_FETCHMODE_ASSOC);
} anders {
die($db->getMessage());
}
// Setzen Sie hier Ihre Logik ein
// Vorlage ausgeben
include_once(APP_TEMPLATE_PATH.'/header.php');
include_once(APP_TEMPLATE_PATH.'/'.$APP_TEMPLATE_FILE);
include_once(APP_TEMPLATE_PATH.'/footer.php');
?>
Oh mein Gott, allein der Anblick dieses Codes lässt mich zusammenzucken. Das Konzept dieses Codes besteht darin, sicherzustellen, dass jede Anwendung an diese Verarbeitungsmethode angepasst werden kann. Ich kann beispielsweise einfach template.txt in myapp.php kopieren, ein paar Variablen ändern und voilà, es wird ausgeführt. Dennoch hat dieser hochorganisierte Ansatz einige gravierende Nachteile: Was wäre,
wenn mein Chef wollte, dass der Autor myapp.php in einigen Fällen zur Ausgabe von PDF, in einigen Fällen von HTML und in einigen Fällen von SOAP (XML-Anfragen direkt gesendet) verwendet, was soll ich tun? Tun?
Was soll ich tun, wenn diese App eine IMAP- oder LDAP-Authentifizierung erfordert?
Wie gehe ich mit den verschiedenen Codetypen um (einschließlich Bearbeitungen, Aktualisierungen und Löschungen)?
Wie gehe ich mit der mehrstufigen Authentifizierung um (Administrator vs. Nicht-Administrator)?
Wie aktiviere ich das Ausgabe-Caching? www.phpv.net Bitte geben Sie die Quelle für den Nachdruck an
[Neuer Weg]
Werfen Sie alles in dieses MVC-Framework und Sie werden feststellen, dass das Leben so einfach ist. Bitte vergleichen Sie den folgenden Code:
<?php
Die Klasse myapp erweitert FR_Auth_User
{
öffentliche Funktion __construct()
{
parent::__construct();
}
öffentliche Funktion __default()
{
// Mach hier etwas
}
öffentliche Funktion delete()
{ }
öffentliche Funktion __destruct()
{
parent::__destruct();
}
}
?>
Beachten Sie, dass dieser Code offensichtlich nicht dazu verwendet wird, eine Verbindung zu einer Datenbank herzustellen, festzustellen, ob ein Benutzer angemeldet ist, oder andere Informationen auszugeben. Der Controller hat es in sich.
Wenn ich mich bei LDAP authentifizieren möchte, kann ich FR_Auth_LDAP einrichten. Der Controller kann bestimmte Ausgabemethoden (z. B. $_GET['output']) erkennen und jederzeit in PDF oder SOAP konvertieren. Der Event-Handler delete ist nur für das Löschen verantwortlich und kümmert sich um nichts anderes. Da dieses Modul über eine Instanz der FR_User-Klasse verfügt, kann es einfach feststellen, ob ein Benutzer angemeldet ist usw. Smarty steuert als Template-Engine natürlich den Cache, aber der Controller kann auch einen Teil des Caches steuern.
Der Wechsel von der zuvor erwähnten alten Methode zur MVC-Methode mag für viele Menschen ein neues und ungewohntes Konzept sein, aber sobald Sie zu einem solchen Konzept wechseln, wird es ziemlich schwierig sein, wieder zurück zu wechseln.
[Erstellen Sie die unterste Ebene]
Ich bin ein Fan von PEAR, insbesondere der PEAR_Error-Klasse. PHP5 führt eine neue integrierte Klasse „Exception“ ein, die PEAR_Error ersetzt. Aber PEAR_Error hat einige praktischere Funktionen als Exception. Daher wird es in den MVC-Framework-Beispielen in dieser Artikelserie zur Fehlerbehandlung verwendet. Wie auch immer, ich muss immer noch Exception verwenden, um den Fehler vom Konstruktor abzurufen, da dieser den Fehler nicht selbst zurückgeben kann.
Der Zweck des Entwurfs dieser Grundklassen ist wie folgt:
Verwenden Sie PEAR, um schnell Funktionen zu Grundklassen hinzuzufügen
, um kleine, wiederholt praktische abstrakte Klassen zu erstellen, damit Benutzer schnell Anwendungen in diesem Framework entwickeln können.
Verwenden
Sie phpDocumentor, um Dokumente für alle Grundklassen zu generieren
Die Klassenhierarchie sieht folgendermaßen aus:
- FR_Object stellt grundlegende Funktionen für alle anderen zu verwendenden Objekte bereit (einschließlich Protokollierung, allgemeines setFrom(), toArray()).
- FR_Object_DB ist eine kleine Ebene, die Datenbanklinks zu Unterklassen und anderen Funktionen bereitstellt.
- FR_Module ist es die unterste Klasse aller Anwendungen (auch Module, Modelle usw. genannt)
– FR_Auth ist die unterste Klasse aller Überprüfungsmechanismen
· FR_Auth_User ist eine Überprüfungsklasse, die zur Überprüfung aller Module verwendet wird, die überprüfen müssen, ob der Benutzer angemeldet ist
· FR_Auth_No ist alle „Fake-Validierungsklassen“ für Module, die keine Validierung erfordern
– FR_Presenter ist die zugrunde liegende Klasse für alle Anwendungen, die das Laden und Anzeigen handhaben
– FR_Presenter_Smarty ist die Präsentationsschicht, die die Möglichkeit beinhaltet, verschiedene Laufwerke zu laden. Smarty ist eine sehr gute Vorlagenklasse. Sie verfügt über einen integrierten Caching-Mechanismus und eine aktive Entwicklungsgruppe (Anmerkung des Übersetzers: Dies ist offensichtlich eine Werbung ~)
· FR_Presenter_debug ist die Anzeigeebene des Debugging-Teils. Darauf aufbauend können Entwickler Anwendungen debuggen und debuggen
. FR_Presenter_rest ist eine REST-Präsentationsschicht, die es Entwicklern ermöglicht, Anwendungen in XML auszugeben.
Aus der oben genannten grundlegenden Klassenstruktur sollten Sie in der Lage sein, die verschiedenen Teile dieses MVC-Frameworks zu erkennen. FR_Module stellt alles bereit, was das Modul benötigt, während FR_Presenter verschiedene Anzeigemethoden bereitstellt. Im nächsten Artikel dieser Serie werde ich einen Controller erstellen, der alle oben genannten Basisklassen miteinander verbindet.
[Codierungsstandards]
Bevor Sie formell Code schreiben, sollten Sie sich mit Ihren Partnern (oder sich selbst) zusammensetzen und Codierungsstandards besprechen (oder darüber nachdenken). Die Gesamtidee der MVC-Programmierung dreht sich um zwei Punkte: Wiederverwendbarkeit des Codes (Reduzierung von Zufällen) und Code-Standardisierung. Ich empfehle, mindestens die folgenden Punkte zu berücksichtigen:
Als Erstes sollten die Standards für die Benennung von Variablen und Abkürzungen berücksichtigt werden. Lassen Sie sich deshalb nicht in einen großen Streit mit Ihren Partnern verwickeln, aber sobald die Standards festgelegt sind, müssen sie von Anfang bis Ende befolgt werden, insbesondere beim Schreiben von Low-Level-Code (Basisklassen).
Passen Sie ein Standardpräfix an, das für alle Funktionen, Klassen und globalen Variablen verwendet werden soll. Leider unterstützt PHP keinen „Namespace (Namespace)“. Um Verwirrung und Konflikte mit Variablennamen zu vermeiden, ist es daher ratsam, ein Präfix zu verwenden. Ich werde in diesem Artikel „FR_“ als Präfix verwenden.
[Schreiben der untersten Ebene]
Die Planung auf Dateiebene ist sehr wichtig. Die grundlegende hierarchische Planung ist einfach und etwas eng definiert:
/
config.php
index.php
beinhaltet/
Auth.php
Auth/
Nr.php
Benutzer.php
Module.php
Object.php
Objekt/
DB.php
Presenter.php
Moderator/
common.php
debug.php
smarty.php
Smarty/
Module/
Beispiel/
config.php
example.php
tpl/
example.tpl
tpl/
Standard/
Cache/
config/
Vorlagen/
templates_c/
Man könnte meinen, dass eine solche Dateihierarchie eine Menge Code darstellen muss! Stimmt, aber Sie können es schaffen. Am Ende der Serie werden Sie feststellen, dass Ihre Programmierung einfacher und Ihre Entwicklungsgeschwindigkeit erheblich verbessert wird.
In der Dateihierarchie befinden sich alle Basisklassen im Includes-Ordner. Jedes Funktionsmodul verwendet eine Konfigurationsdatei, mindestens eine Moduldatei und eine Vorlagendatei. Alle Module sind im Modulordner enthalten. Ich habe mich daran gewöhnt, Vorlagendateien in einem separaten externen Ordner, dem TPL-Ordner, abzulegen.
config.php – die zentrale Konfigurationsdatei, die alle globalen Konfigurationsvariablen enthält.
index.php – Controller, wird im nächsten Artikel ausführlich beschrieben.
object.php – die zugrunde liegende Klasse für alle Basisklassen, die die meisten von der Klasse benötigten Funktionen bereitstellt. FR_Object_DB erbt diese Klasse und stellt Datenbankverknüpfungen bereit.
Das Grundkonzept einer Struktur besteht darin, dass alle Unterklassen von einer zentralen Klasse erben, sodass sie alle einige gemeinsame Merkmale aufweisen. Sie können die Funktion zum Verknüpfen mit der Datenbank in FR_Object einfügen, aber nicht alle Klassen benötigen diese Funktion, sodass FR_Object_DB einen Existenzgrund hat und der Autor später darauf eingehen wird.
<?php
require_once('Log.php');
/**
*FR_Object
*
* Die Basisobjektklasse für die meisten Klassen, die wir in unserem Framework verwenden.
* Bietet grundlegende Protokollierungs- und Set/Get-Funktionalität.
*
* @Autor Joe Stump < [email protected] >
* @packageFramework
*/
abstrakte Klasse FR_Object
{
/**
* $log
*
* @var gemischt $log Instanz von PEAR Log
*/
protected $log;
/**
*$ich
*
* @var gemischt $me Instanz von ReflectionClass
*/
protected $me;
/**
* __konstruieren
*
* @Autor Joe Stump < [email protected] >
* @access public
*/
öffentliche Funktion __construct()
{
$this->log = Log::factory('file',FR_LOG_FILE);
$this->me = new ReflectionClass($this);
}
/**
* setFrom
*
* @Autor Joe Stump < [email protected] >
* @access public
* @param gemischtes $data Array von Variablen, die der Instanz zugewiesen werden sollen
* @return void
*/
öffentliche Funktion setFrom($data)
{
if (is_array($data) && count($data)) {
$valid = get_class_vars(get_class($this));
foreach ($valid as $var => $val) {
if (isset($data[$var])) {
$this->$var = $data[$var];
}
}
}
}
/**
* toArray
*
* @Autor Joe Stump < [email protected] >
* @access public
* @return gemischtes Array von Mitgliedsvariablen, verschlüsselt nach Variablennamen
*/
öffentliche Funktion toArray()
{
$defaults = $this->me->getDefaultProperties();
$return = array();
foreach ($defaults as $var => $val) {
if ($this->$var Instanz von FR_Object) {
$return[$var] = $this->$var->toArray();
} anders {
$return[$var] = $this->$var;
}
}
return $return;
}
/**
* __zerstören
*
* @Autor Joe Stump < [email protected] >
* @access public
* @return void
*/
öffentliche Funktion __destruct()
{
if ($this->log instanceof Log) {
$this->log->close();
}
}
}
?>
auth.php – Dies ist die zugrunde liegende Klasse für alle Authentifizierungsfunktionen. Es ist eine Erweiterung von FR_Module und seine Hauptfunktion besteht darin, zu definieren, wie eine grundlegende Verifizierungsklasse funktioniert.
Genau wie FR_Module müssen einige Klassen nicht mit der Datenbank verbunden werden. Ebenso kann FR_Auth_No erstellt und auf Klassen angewendet werden, die keine Authentifizierungsfunktionen erfordern.
<?php
Die abstrakte Klasse FR_Auth erweitert FR_Module
{
// {{{ __construct()
function__construct()
{
parent::__construct();
}
// }}}
// {{{ authentifizieren()
abstrakte Funktion Authenticate();
// }}}
// {{{ __destruct()
function __destruct()
{
parent::__destruct();
}
// }}}
}
?>
module.php – das Herzstück aller Module
<?php
Die abstrakte Klasse FR_Module erweitert FR_Object_Web
{
// {{{ Eigenschaften
/**
* $Moderator
*
* Wird in FR_Presenter::factory() verwendet, um zu bestimmen, welche Präsentation (Ansicht)
Für das Modul sollte die Klasse * verwendet werden.
*
* @Autor Joe Stump < [email protected] >
* @var string $presenter
* @see FR_Presenter, FR_Presenter_common, FR_Presenter_smarty
*/
public $presenter = 'smarty';
/**
* $Daten
*
* Vom Modul festgelegter Datensatz, der schließlich an die Ansicht übergeben wird.
*
* @Autor Joe Stump < [email protected] >
* @var gemischte $data Moduldaten
* @see FR_Module::set(), FR_Module::getData()
*/
protected $data = array();
/**
* $name
*
* @Autor Joe Stump < [email protected] >
* @var string $name Name der Modulklasse
*/
public $name;
/**
* $tplFile
*
* @Autor Joe Stump < [email protected] >
* @var string $tplFile Name der Vorlagendatei
* @see FR_Presenter_smarty
*/
public $tplFile;
/**
* $moduleName
*
* @Autor Joe Stump < [email protected] >
* @var string $moduleName Name des angeforderten Moduls
* @see FR_Presenter_smarty
*/
public $moduleName = null;
/**
* $pageTemplateFile
*
* @Autor Joe Stump < [email protected] >
* @var string $pageTemplateFile Name der äußeren Seitenvorlage
*/
public $pageTemplateFile = null;
// }}}
// {{{ __construct()
/**
* __konstruieren
*
* @Autor Joe Stump < [email protected] >
*/
öffentliche Funktion __construct()
{
parent::__construct();
$this->name = $this->me->getName();
$this->tplFile = $this->name.'.tpl';
}
// }}}
// {{{ __Standard()
/**
* __Standard
*
* Diese Funktion wird vom Controller ausgeführt, wenn kein Ereignis angegeben ist
* in der Anfrage des Benutzers.
*
* @Autor Joe Stump < [email protected] >
*/
abstrakte öffentliche Funktion __default();
// }}}
// {{{ set($var,$val)
/**
* Satz
*
* Legen Sie die Daten für Ihr Modul fest. Diese werden schließlich an das weitergegeben
* Präsentatorklasse über FR_Module::getData().
*
* @Autor Joe Stump < [email protected] >
* @param string $var Name der Variablen
* @param gemischt $val Wert der Variablen
* @return void
* @see FR_Module::getData()
*/
protected function set($var,$val) {
$this->data[$var] = $val;
}
// }}}
// {{{ getData()
/**
*getData
*
* Gibt die Daten des Moduls zurück.
*
* @Autor Joe Stump < [email protected] >
* @return gemischt
* @see FR_Presenter_common
*/
öffentliche Funktion getData()
{
return $this->data;
}
// }}}
// {{{ isValid($module)
/**
*istGültig
*
* Bestimmt, ob $module ein gültiges Framework-Modul ist. Dies wird von verwendet
* der Controller, um festzustellen, ob das Modul in unser Framework passt
* Schimmel. Wenn es sowohl von FR_Module als auch von FR_Auth ausgeht, sollte es so sein
* gut zu laufen.
*
* @Autor Joe Stump < [email protected] >
* @static
* @param hat $module gemischt
* @return bool
*/
öffentliche statische Funktion isValid($module)
{
return (is_object($module) &&
$module-Instanz von FR_Module &&
$module-Instanz von FR_Auth);
}
// }}}
// {{{ __destruct()
öffentliche Funktion __destruct()
{
parent::__destruct();
}
// }}}
}
?>
presenter.php – der Kern der Präsentationsschicht.
<?php
Klasse FR_Presenter
{
// {{{ Factory($type,FR_Module $module)
/**
*Fabrik
*
* @Autor Joe Stump < [email protected] >
* @access public
* @param string $type Präsentationstyp (unsere Ansicht)
* @param gemischt $module Unser Modul, das dem Präsentator angezeigt wird
* @return gemischter PEAR_Error bei Fehler oder einem gültigen Präsentator
* @static
*/
statische öffentliche Funktionsfabrik($type,FR_Module $module)
{
$file = FR_BASE_PATH.'/includes/Presenter/'.$type.'.php';
if (include($file)) {
$class = 'FR_Presenter_'.$type;
if (class_exists($class)) {
$presenter = new $class($module);
if ($presenter-Instanz von FR_Presenter_common) {
return $presenter;
}
return PEAR::raiseError('Ungültige Präsentationsklasse: '.$type);
}
return PEAR::raiseError('Präsentationsklasse nicht gefunden: '.$type);
}
return PEAR::raiseError('Presenter-Datei nicht gefunden: '.$type);
}
// }}}
}
?>
Im nächsten Artikel werde ich die Struktur des Controllers vorstellen (Controller in MVC, index.php in diesem Artikel). Im dritten Artikel werde ich die Präsentationsschicht (Ansicht in MVC) vorstellen. Im vierten Artikel werde ich ein bestimmtes Modul als Beispiel zum Erstellen einer Anwendung verwenden (Modul oder Modell in MVC).