Folgende Warnungen sind aufgetreten: | ||||||||||||
Warning [2] Undefined array key "dateline" - Line: 1000 - File: inc/functions_post.php PHP 8.2.25 (Linux)
|
Das Zend Framework - Druckversion +- net-board.net Archiv (https://net-board.net) +-- Forum: Deine eigene Homepage (https://net-board.net/forumdisplay.php?fid=26) +--- Forum: Scriptsprachen (+Datenbanksysteme) (https://net-board.net/forumdisplay.php?fid=19) +---- Forum: Tutorials und Artikel: Programmieren und Datenbanken (https://net-board.net/forumdisplay.php?fid=15) +---- Thema: Das Zend Framework (/showthread.php?tid=5891) |
Das Zend Framework - Futjikato - 22.09.2008 Da es im netz noch recht wenig Tutorials zum ZEND Framework [1] gibt, habe ich mir gedacht, dass ich hier mal die wichtigsten Sachen kurz zusammenfasse. Part I | Wie ist Zend aufgebaut ? Das Zend Framework ist ja nach dem MVC [2] Prinzip entwickelt worden. Das schlägt sich auch schon in der Ordnerstrucktur nieder. Die folgende Strucktur ist die am weitesten verbreitete [S1]. Man kann das aber auch so umarbeiten, wie man es für sich am liebsten hat. Die hier vorgestellte Bootstrap- Datei ist jedoch auf diese Strucktur ausgelegt. Code: /htdocs Inhalt der .htaccess im htdocs Ordner : Code: RewriteEngine On [S1] = Wenn du Ordner außerhalb des Rootverzeichnises anlegen kannst, so wird empfohlen den Application- und den Librarayordner dort zu platzieren. Last Update : 25.09 Part II | Bootstrap Datei - Futjikato - 24.09.2008 Die in Part I erstellte .htaccess Datei leitet ja nun alle Anfragen an die index.php weiter. Und diese Datei muss dann ja folglich alle Anfragen bearbeiten. Dazu müssen wir ein paar Sachen im Kopf behalten : Wir wollen unsere Anwendung immer erweitern können ohne die Bootstrap großartig umschreiben zu müssen. Nicht nur wir, sondern auch PHP arbeitet von oben nach unten. D.h. wir können nicht erst die Usererkennung machen und dort eine Datenbankverbindung benutzen und erst danach die Datenbankverbindung herstellen. Also als Schema sollte das ganze so aussehen :
Part III | Erste Seite(n) - Futjikato - 24.09.2008 Was brauchen wir ? Folgende Datein : IndexController.php ( aus application/modules/default ) index.phtml ( aus application/modules/default/views/scripts/index ) Inhalt IndexController.php [code=php] class IndexController extends Zend_Controller_Action { public function indexAction() { // Programmlogik hier $this->view->neuevariable = 'Inhalt von IndexController.php'; } } [/code] Inhalt von index.phtml [code=php] <h1>Startseite</h1> <?php echo $this->neuevariable ?> [/code] Dann sollte die Ausgabe so sein : Startseite Inhalt von IndexController.php ----------------------------------- That´s it Was lernen wir ? Um eine neue Seite auf unserer Webseite brauchen wir nur : 1a) Neuen Controller anlegen ODER 1b) Eine neue Action im Controller hinzufügen 2) Wir brauchen einen neuen Ordner (wenn wir auch nen neuen Controller erstellt haben sonst sollte der ordner schon da sein ) im Verzeichnis application/modules/default/views/script/{name des Controllers}/{name der action}.phtml Im Controller könnt Ihr auch einfach fröhlich Sachen Ausgeben, doch das bitte nur zu debugg Zwecken, denn schließlich besagt das MVC Prinzip das im Controller nur Programmlogik sein soll. Das wärs auch schon Part III b | Erweiteretes Seitenmanagement - Futjikato - 25.09.2008 Für komplexere Internetauftritte Jeder der eine mehr, oder minder komplexe Webbaplication schreiben will, der wird nach kurzer Zeit bemerken, dass er mit einem Module nicht weit kommt. Zumindest nicht wenn er keine bescheuerten Controllernamen einführen will, oder einige Controller mit 20 Funktionen bestückt. Um genau sowas zu verhindern ist eine modulare Strucktur gut. In unserem Verzeichnis modules befindet sich bis dato nur ein Ordner : default. Hier fügen wir nun einen neuen Ordner hinzu den wir special nennen. In diesem Verzeichnis erstellen wir nun wieder einen IndexController und die dazugehörigen Viewscripts ( siehe Part III -> Was lernen wir). nun sollten wir im Ordner Modules folgende Ordnerstrucktur haben : Code: /modules Achtung : Die Klasse im Controller darf hier nun nicht nur IndexControler heißen, sondern muss den Modulnamen als Präfix haben. Also : [code=php] class special_IndexController extends Zend_Controller_Action { public function IndexAction() { // Programmlogik hier } } [/code] Das Standart Routing ist : /{modul}/{controller}/{action} Also in unserem Fall : special/index/index. Es wird immer zuerst überprüft ob der erste Parameter in der URL ein Modul ist. /{controller}/{action} Hier wird alsModul 'default' benutzt. Part IV | Userauthentifizierung - Futjikato - 26.09.2008 Für eine komplette Userauthentifizierung benötigen wir 4 Sachen :
Also erstmal legen wir einen neuen Ordner im Verzeichnis library an den ich hier MyWork nennen werde. In diesem Ordner legen wir nun 3 Datein an :
Arbeiten wir uns nun mal von oben nach unten dutch die Datein. Inhalt von myacl.php [code=php] <?php class MyWork_myacl extends Zend_Acl { public function __construct(Zend_Auth $auth) { $this->add(new Zend_Acl_Resource('index')); $this->addRole(new Zend_Acl_Role('gast')) ->addRole(new Zend_Acl_Role('admin'),'gast'); $this->allow('gast','index','index'); ->allow('admin','index',array('neuenuser','userlöschen')); } } [/code] Die Klasse muss so benannt werden damit sie von Zend_Auoload im Unterordner gefunden wird ( wer sich also bis jetzt gewundert hat warum alle Zend Klassen mit dem Präfix 'Zend_' beginnen, dem geht jetzt wohl ein Licht auf Was passiert in dieser Date ? Erst definieren wir Resourcen. Wir können mit Zend_Acl nur den Zugriff von Usern auf Resourcen kontrollieren. Es macht daher sinn diese Resourcen sinnig zu bennenen. Ich benutze hier den Controllernamen. Den Actionnamen sollten wir nicht nehmen, da man später die Action als zusätzlich behandeln kann. Dann müssen wir Rollen ( Benutzergruppen ) anlegen. Eine Rolle sollte immer 'gast' o.ä. heißen. Schließlich brauchen wir eine Klasse die alle nicht angemeldeten User bekommen. Zusätzlich definiere ich nun noch eine Admingruppe. Durch den 2. Parameter 'gast' lasse ich der Admingruppe alle Erlaubnisse von der Gruppe gast erben. Also wenn Gast nun Zugriff auf xyz hat, dann hat die Admingruppe automatisch auch Zugriff auf jene Resource. Als nächstes sagen wir der Klasse welche Usergruppen auf welche Resource Zugriff hat. [code=php]allow('gast','index','index')[/code] Gast hat nun Zugriff auf die Resource 'index' und dort auf die Action 'index'. Admin hat nun automatisch durch die Vererbung auch Zugriff auf diese Action. [code=php]allow('admin','index',array('neuenuser','userlöschen')[/code] Admin hat nun Zugriff auf die Resource 'index' und dort auf die beiden Action´s 'neuenuser' und 'userlöschen'. Inhalt von myauth.php [code=php] <?php class MyWork_myauth extends Zend_Controller_Plugin_Abstract { private $_auth; private $_acl; private $_noauth = array('module' => 'default', 'controller' => 'user', 'action' => 'nouser'); private $_noacl = array('module' => 'default', 'controller' => 'error', 'action' => 'noaccess'); public function __construct($auth, $acl) { $this->_auth = $auth; $this->_acl = $acl; } public function preDispatch(Zend_Controller_Request_Abstract $request) { $controller = $request->getControllerName(); $action = $request->getActionName(); $module = $request->getModuleName(); $resource = $controller; if ($this->_auth->hasIdentity()) { $role = $this->_auth->getIdentity()->role; } else { $role = 'gast'; } if (!$this->_acl->has($resource)) { $resource = null; } if (!$this->_acl->isAllowed($role, $resource, $action)) { if (!$this->_auth->hasIdentity()) { $module = $this->_noauth['module']; $controller = $this->_noauth['controller']; $action = $this->_noauth['action']; } else { $module = $this->_noacl['module']; $controller = $this->_noacl['controller']; $action = $this->_noacl['action']; } } $request->setModuleName($module); $request->setControllerName($controller); $request->setActionName($action); } } [/code] Was passiert in dieser Datei ? Die ersten Zeilen sollten sich von selbst erklären . OOP in PHP möchte ich hier nicht näher erlätern. Die Funktion preDispatch wird vor dem Abarbeiten des Controllers gestartet. Als parameter wird hier das Request-Objekt übergeben. Aus diesem können wir nun auslesen auf welche Seite der User gerade zugreifen möchte : [code=php] $controller = $request->getControllerName(); $action = $request->getActionName(); $module = $request->getModuleName(); [/code] Nun müssen wir noch prüfen ob der User eingeloggt ist, und festlegen das unsere Resource aus Acl hier gleichzusetzten ist mit dem Controller, welcher aufgerufen werden soll. [code=php] $resource = $controller; if ($this->_auth->hasIdentity()) { $role = $this->_auth->getIdentity()->role; } else { $role = 'gast'; } [/code] Wenn der User nicht eingeloggt ist, so wird ihm die Rolle 'gast' gegeben. Die wichtigsten Zeilen : [code=php] if (!$this->_acl->isAllowed($role, $resource, $action)) { if (!$this->_auth->hasIdentity()) { $module = $this->_noauth['module']; $controller = $this->_noauth['controller']; $action = $this->_noauth['action']; } else { $module = $this->_noacl['module']; $controller = $this->_noacl['controller']; $action = $this->_noacl['action']; } } [/code] Hier wird geprüft ob der User mit der Rolle $role auf die Resource $resource und dort auf die Action $action keinen Zugriff hat. Wenn dies der Fall ist wird entschieden ob er auf die Loginseite weitergeleitet werden sollte, oder ob ihm eine Seite angezeigt werden soll, die ihm sagt, dass er keinen Zugriff auf diese Seite hat. Schließlich werden noch die eventuell neuen Angaben an den Request weitergegeben. So einfach ist der Hauptteil Nun der Inhalt von myauthadapter.php [code=php] <?php require_once 'Zend/Auth/Adapter/DbTable.php'; class MyWork_myauthadapter extends Zend_Auth_Adapter_DbTable { public $authAdapter; public function __construct() { $db = Zend_Registry::get('db'); parent::__construct($db); $this->setTableName('tabelle_mit_userdaten'); $this->setIdentityColumn('spalte_mit_username'); /* Passwörter sollten verschlüsselt sein */ $this->setCredentialColumn('spalte_mit_passwort'); /* Falls verschlüsselt dann hier sagen wie */ $this->setCredentialTreatment('MD5(?)''); } } [/code] Es gibt auch andere Adapterklassen. Wer also nicht MySQL nutzt kann sich mal in dem Teil des Manuals umsehen [1] So das wären auch schon alle wichtigen Sachen. Als letztes noch das Loginformular. Wir bauen das Formular am besten so ein das in der selben Funktion auch der tatsächliche Loginvorgang abläuft. [code=php] // Klasse usw. hier erstellen private function loginForm() { $login = new Zend_Form(); $login->setAction('/user/login') ->setMethod('post'); $username = $login->createElement('text', 'username') ->setRequired(true) ->addValidator('regex', false, array('/^[a-z0-9]*$/i')) ->addValidator('stringLength', false, array(4,15)); $password = $login->createElement('password', 'password') ->setRequired(true) ->addValidator('regex', false, array('/^[a-z0-9*]*$/i')) ->addValidator('stringLength', false, array(5,10)); $login->addElement($username) ->addElement($password) ->addElement('submit', 'login', array('label' => 'Login')); return $login; } public function indexAction() { echo $this->loginForm(); } public function loginAction() { if($this->getRequest()->isPost()){ $form = $this->loginForm(); if (!$form->isValid($_POST)) { $this->view->message = "<font style=\"color:red; font-weight:bold;\">Invalid Input</font><br />"; $this->view->badlogin=$form; }else{ $erg=$form->getValues(); $authAdapter = new MyWork_myauthadapter(); $authAdapter->setIdentity($erg['username']); $authAdapter->setCredential($erg['password']); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter); if ($result->isValid()) { $storage = $auth->getStorage(); $storage->write($authAdapter->getResultRowObject(array('spalte_mit_username','spalte_mit_rolle'),'spalte_mit_passwort')); $this->view->message = 'Login success.'; } else { switch ($result->getCode()){ case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND: $this->view->message = '<b>Anmeldung fehlgeschlagen.</b><br /> <br /> Benutzername und/oder Passwort falsch.'; break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: $this->view->message = '<b>Anmeldung fehlgeschlagen.</b><br /> <br /> Inaktiv oder gebannt.'; break; default: $this->view->message = '<b>Anmeldung fehlgeschlagen.</b><br /> <br /> Es ist ein Fehler aufgetreten.'; break; } } } }else{ return $this->_forward('index'); } [/code] Alle Fragen zum Formular an sich sollten hier geklärt werden können. Ich werde hier nur kurz sagen, was folgende Zeilen bedeuten : [code=php] $authAdapter = new MyWork_myauthadapter(); $authAdapter->setIdentity($erg['username']); $authAdapter->setCredential($erg['password']); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter); if ($result->isValid()) { $storage = $auth->getStorage(); $storage->write($authAdapter->getResultRowObject(array('spalte_mit_username', 'spalte_mit_rolle'),'spalte_mit_passwort')); [/code] Also erstmal hohlen wir uns unsere Adapterklasse und übergeben dieser die Benutzereingaben. Dann lassen wir prüfen ob diese Eingaben korrekt sind. Wenn ja, dann werden die beiden Spalten spalte_mit_username und i]spalte_mit_rolle[/i] noch gespeichert, damit unser Plugin auch bei jedem Seitenaufruf die Indentität wiederfindet. Fertig ist das komplette Usermanagement Letztes Update : 27.09.2008 - kickedINtheHEAD - 27.09.2008 Hi sieht echt gut aus - hab nur leider noch keine Zeit gehabt mir das ganze genau anzuschaun. Vielleicht ists ja auch möglich, dass du irgendwo eine Demo Version online stellst. Mfg - Futjikato - 27.09.2008 Jo danke für das positive Feedback. Also eine Demoversion ist bei nem Framework ja net so einfach. Spontan fällt mir nur meine eigene Website ein. Noch sieht diese auch mehr nach Demoversion aus, da es noch kein Design gibt. Also wer wissen will wie weit ich selbst bin mit der Entwicklung der kann sich mal auf http://cashiers-check.de umsehen - KingGO - 27.09.2008 Ich hab extra nichts geschrieben um die schöne Tutorialkette nicht zu unterbrechen aber auch ich kann nur sagen geile Anleitung =) - Futjikato - 28.09.2008 So und nun melden wir uns wieder nach dieser kleinen Werbeunterbrechung Part V | Daten auslesen aus Datenbank ( MySQL ) Alles was in diesem Part beschrieben wird gehört dem M aus MVC an. Ich werde manchmal andre Ausdrücke als Model für hier gezeigte Möglichekuten nennen, doch trotzdem ist es der Modelkomponente zuzuordnen. Es gibt mehrere Möglichkeiten Daten aus der Datenbank auszulesen. [bTabellen-Models :[/b] Im Ordner Models legen wir eine neue Datei nach folgendem Muster an : {tabellenname}Models.php in dieser Datei legen wir eine neue Klasse an [code=php] class tabelle extends Zend_Db_Table_Abstract{ protected $_name = 'tabelle'; protected $_primary = 'primary_key'; } [/code] Nun können wir in jedem Controller einfach eine Instanz dieser Klasse erzeugen und dann können wir beispielsweise ganz einfach Datensätze in dieser Tabelle anlegen. [code=php] $tabelle = new tabelle(); $insertwerte = array('col' => 'value'); $tabelle->insert($insertwerte); [/code] Auf änliche Art und Weise kann man auch Datensätze auslesen und aktualisieren. Mehr dazu im Manual [LINK] Eine andre Möglichkeit ist es einfach den in der Index.php ( Bootstrap ! ) erzeugten MySQL Adapter in der Zend Registry zu speichern und nun wieder auszulesen. Bootsrapr [code=php] Zend_Registry:et('db',$dbadapter); [/code] Controller [code=php] $db = Zend_Registry::get('db'); $getrow=$db->select(); $temp=$getrow->from('tabelle',array('col1','col2')) ->order('primary ASC'); $tmp=$getdetails->query(); $res=$tmp->fetchAll(); [/code] Diese Anfrage würde Beispielsweise alle Werte aus den Spalten col1 und col2 auslesen. Sortiert würden die Wertepaare nach dem Wer der in der Spalte primary steht ( wahrscheinlich der Primärschlüssel ). Das Ergebnis wird in der Variable $res gespeichert. $res ist ein verschachteltes Array [code=php] echo $res[0]['col1']; [/code] Dies würde den Wert aus col1 aus der ersten Reihe ausgeben. MySQL ist natürlich ein großes Thema und es gibt auch eine Vielzahl von Möglichkeiten Daten aus einer Datenbank auszulesen. Das Framework stellt dementsprechend auch viele Möglichkeiten bereit mit der Datenbank zu kommunizieren. Ein Blick ins Manual zu Zend_db ist daher für jeden Zend Framework Benutzer Pflicht. - Futjikato - 03.10.2008 An dieser Stelle mal ne Frage an die kleine aber feine Community Wollt ihr mehr ? Wollt ihr Beschreibung einzelner Komponenten ? Würde gerne noch mehr schreiben, weiß aber nicht ob hier wer überhaupt intereese dran hat ^^ |