Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Zend Framework 2 - Best Practices

8.010 Aufrufe

Veröffentlicht am

Erfahren Sie in diesem Talk, wie Sie das Zend Framework 2 gewinnbringend für Ihre eigenen Projekte einsetzen können. Sie erhalten Tipps aus der Praxis für die Praxis zu Themen wie Performance, Security, Wiederverwendbarkeit von Modulen, Einsatz des Event-Managers für eigene Zwecke, interessante Fremdmodule, Migration vom ZF1, und vieles mehr.

  • Als Erste(r) kommentieren

Zend Framework 2 - Best Practices

  1. 1. Ralf Eggert | Travello GmbH Zend Framework 2 - Best Practices Quelle: DASPRiD / flickr
  2. 2. Über Ralf Eggert • Geschäftsführer Travello GmbH • Buchautor & Kolumnist – Zend Framework 1 (Addison-Wesley) – Zend Framework 2 (Galileo Computing) – PHP Magazin • Zend Framework seit 2006 • Contributor, Speaker, Trainer – http://www.ralfeggert.de/ – http://www.zendframeworkschulung.de/
  3. 3. Drei Fragen an das Publikum? • Wer – hat Erfahrungen mit dem Zend Framework 2? – entwickelt an einem Zend Framework 2 Projekt? – hat ein ZF2 Projekt im Live-Betrieb?
  4. 4. MVC Quelle: D. Braun / pixelio.de
  5. 5. Model-View-Controller • Entwurfsmuster – Model: Business Logik – View: Präsentationslogik – Controller: Steuerungslogik • Warum MVC? – Übersichtlichkeit – Testbarkeit – Wartbarkeit • Paradigma – »Thin Controllers / Fat Models«
  6. 6. Bestandteile einer ZF2 Anwendung • Entitäten • Hydratoren • Controller • Controller-Plugins • TableGateways • Formulare • InputFilter • Filter • Validatoren • View-Skripte • View-Helper
  7. 7. Bad Practice: MVC Filter Filter Filter Formular Input Filter Validator Request Validator Controller Validator Manuela Peter Datenbank Klaus Entität Response View ViewSkripte ViewHelper
  8. 8. Lösung: Model-Services einführen • Model-Services • Entitäten • Hydratoren • Controller • Controller-Plugins • TableGateways • Formulare • InputFilter • Filter • Validatoren • View-Skripte • View-Helper
  9. 9. Better Practice: Controller & Model-Service ModelService Request Controller Formular Response View
  10. 10. Better Practice: Model mit Model-Service Controller Manuela Filter Filter Peter Filter Klaus Entität Hydrator Model Service Input Filter Validator Validator Datenbank Validator
  11. 11. Better Practice: View mit Model-Service Controller View ViewSkripte Response ViewHelper nur lesend! Model Service
  12. 12. Vorteile einer sauberen Trennung • Alles hat seinen Platz • Model-Service verwendbar von – Webanwendung – Cron-Job – RESTful Webservice – Javascript-Anwendung • Datenvalidierung nicht an Formular gekoppelt
  13. 13. Verschiedene Datenspeicher ZF2 TableGateway Doctrine ORM Controller ModelService Dateisystem REST SOAP XML-RPC
  14. 14. Module Quelle: Carsten Jünger / pixelio.de
  15. 15. Zend Framework 2 Module • Anwendungsspezifische Module – Verzeichnis /module • Fremdmodule – Verzeichnis /vendor • Unternehmensmodule – Verzeichnis /corporate – Oder Unternehmensname, z.B. /travello • Module können aufeinander aufbauen • Module können andere erweitern
  16. 16. Abhängigkeiten von ZF2 Modulen I • Beispiel: Modul Application • Funktionen – Layout – Fehlerseiten – Module laden – Konfiguration (z.B. Navigation) • Zugriff für andere Module – Ergänzende Konfiguration z.B. für ZendNavigation • Zugriff auf andere Module – Widgets über View-Helper aufrufen
  17. 17. Abhängigkeiten von ZF2 Modulen II • Beispiel: Modul User • Funktionen – Registrierung – Authentifizierung – Autorisierung – Event-Listener • Zugriff für andere Module – View-Helper: userIsAllowed und userWidget – Controller-Plugin: userIsAllowed • Direkten Zugriff auf Services vermeiden
  18. 18. Wiederverwendbarkeit • Jedes Modul braucht eigene Routen • .dist Datei für Konfiguration – Für /config/autoload Verzeichnis • Generalisiertes Markup im View verwenden – Twitter Bootstrap – Eigene CSS Struktur • Abhängigkeiten zu anderen Modulen reduzieren • Anderen Module Zugriff ermöglichen – View-Helper – Controller Plugins
  19. 19. Fremdmodule • http://modules.zendframework.com/ • https://github.com/ZF-Commons • https://github.com/zfcampus • Beispiele: – ZfcUser / ZfcUser2 – DoctrineModule – DoctrineORMModule – ZendDeveloperTools – BjyProfiler
  20. 20. ZF2 Module - Best Practices • Modulkonfiguration cachen! – Achtung! Nur getConfig() wird gecached • Jedes Modul konfiguriert eigenes Routing – Vermeiden: Keine einzelne Route für alle Module • onBootstrap() und init() sparsam nutzen • Nicht überladen: module.config.php – Konfigurationsdaten für Schuhgrößen, Währungskurse, Bildgrößen, finnische Biermarken usw. auslagern • Unternehmensmodule wiederverwenden
  21. 21. Service-Manager Quelle: neurolle - Rolf / pixelio.de
  22. 22. Service Locator • Service-Locator – Entwurfsmuster • Service-Manager – Konkrete Implementation • Aufgaben – Instanziierung von Objekten / Services – Bereitstellung der Instanzen zur Wiederverwendung
  23. 23. Spezialisierte Service-Manager ServiceManager Controller Loader Route-Plugin Loader Controller-Plugin Manager Serializer-Adapter Manager View-Helper Manager Hydrator Manager Validator Manager Filter Manager Form-Element Manager Input-Filter Manager
  24. 24. Beispiel Factory (mit kleiner Unschärfe) // Datei /module/Customer/src/Customer/Form/CustomerFormFactory.php namespace CustomerForm; use ZendServiceManagerFactoryInterface; use ZendServiceManagerServiceLocatorInterface; class CustomerFormFactory implements FactoryInterface { public function createService(ServiceLocatorInterface $formElementManager) { $serviceLocator = $formElementManager->getServiceLocator(); $hydratorManager = $serviceLocator->get('HydratorManager'); $inputFilterManager = $serviceLocator->get('InputFilterManager'); $filter = $inputFilterManager->get('CustomerCustomerFilter'); $config = $inputFilterManager->getServiceLocator()->get('Config'); $form = new CustomerForm($config['country_options']); $form->setHydrator($hydratorManager->get('ArraySerializable')); $form->setInputFilter($filter); return $form; } }
  25. 25. Beispiel Factory (verbessert) // Datei /module/Customer/src/Customer/Form/CustomerFormFactory.php namespace CustomerForm; use ZendServiceManagerFactoryInterface; use ZendServiceManagerServiceLocatorInterface; class CustomerFormFactory implements FactoryInterface { public function createService(ServiceLocatorInterface $formElementManager) { $serviceLocator = $formElementManager->getServiceLocator(); $hydratorManager = $serviceLocator->get('HydratorManager'); $inputFilterManager = $serviceLocator->get('InputFilterManager'); $filter = $inputFilterManager->get('CustomerCustomerFilter'); $config = $serviceLocator->get('Config'); $form = new CustomerForm($config['country_options']); $form->setHydrator($hydratorManager->get('ArraySerializable')); $form->setInputFilter($filter); return $form; } }
  26. 26. Konfiguration (Auszug) // Datei /module/Customer/config/module.config.php return array( 'input_filters' => array( 'invokables' => array( 'CustomerCustomerFilter' ), 'shared' => array( 'CustomerCustomerFilter' ), ), => 'CustomerInputFilterCustomerFilter', => true, 'form_elements' => array( 'invokables' => array( 'CustomerAddressFieldset' => 'CustomerFormCustomerAddressFieldset', ), 'factories' => array( 'CustomerCustomerForm' => 'CustomerFormCustomerFormFactory', ), 'shared' => array( 'CustomerCustomerForm' => true, ), ), );
  27. 27. Service Manager - Best Practices • Spezialisierte Service-Manager nutzen • ServiceLocatorAwareInterface meiden • Service-Manager niemals injizieren! Nein, nie! • new möglichst nur in Factories verwenden • Initializer sparsam einsetzen • Abstract Factories sparsam einsetzen • Factory Closures in Konfigurationsdateien verhindern Caching • ZendServiceManager schneller als ZendDi
  28. 28. Event-Manager Quelle: Rainer Sturm / pixelio.de
  29. 29. Event-Manager im MVC • MVC Events – »bootstrap« – »route« – »dispatch« / »dispatch.error« – »render« / »render.error« – »finish« • Mvc Events für eigene Zwecke verwenden – Nach »route« Event Sprache der Anwendung festlegen – Nach »dispatch.error« Event Fehlermeldungen loggen – Vor »finish« Event HTML aufräumen / minifizieren
  30. 30. Event-Manager im Model-Service // Datei /module/Order/src/Order/Service/OrderService.php namespace OrderService; use ZendEventManagerEventManagerInterface; use ZendDebugDebug; class OrderService { protected $eventManager; public function setEventManager(EventManagerInterface $eventManager) { $eventManager->setIdentifiers(array(__CLASS__); $this->eventManager = $eventManager; } public function getEventManager() { return $this->eventManager; } public function saveOrder($id) { $this->getEventManager()->trigger('preOrder', __CLASS__, array('id' => $id)); Debug::dump('Save order ' . $id); $this->getEventManager()->trigger('postOrder', __CLASS__, array('id' => $id)); } }
  31. 31. Event-Manager konfigurieren use ZendDebugDebug; use ZendEventManagerEventManager; use OrderServiceOrderService; $eventManager = new EventManager(); $eventManager->attach('postOrder', function ($e) { Debug::dump('Update stock'); }, 100); $eventManager->attach('postOrder', function ($e) { Debug::dump('Send order confirmation'); }, 300); $eventManager->attach('preOrder', function ($e) { Debug::dump('Check stock'); }); $orderService = new OrderService(); $orderService->setEventManager($eventManager); $orderService->saveOrder('12345'); // output string 'Check stock' (length=11) string 'Save order 12345' (length=16) string 'Send order confirmation' (length=23) string 'Update stock' (length=12)
  32. 32. Event Manager - Best Practices • Eindeutige Identifier verwenden (Klassenname) • SharedEventManager – Fallback für alle Event-Manager Instanzen – Events für nicht existente Objekte registrieren • EventManagerAwareInterface • Listener – Aggregat-Klassen (ListenerAggregateInterface) – Closures
  33. 33. Formularverarbeitung Quelle: Matthias Preisinger / pixelio.de
  34. 34. Formularverarbeitung • InputFilter – ZendInputFilterInputFilter erweitern – Input-Elemente in init() per Factory hinzufügen – Hierarchische InputFilter möglich • Formulare – ZendFormForm erweitern – Formularelemente in init() per Factory hinzufügen – Hierarchie durch Fieldsets umsetzbar
  35. 35. Konfiguration Filter & Validatoren // Datei /module/Customer/config/module.config.php return array( 'filters' => array( 'invokables' => array( 'CustomerAddress' => 'CustomerFilterAddressFilter', ), ), 'validators' => array( 'invokables' => array( 'CustomerCountry' => 'CustomerValidatorCountryValidator', ), ), );
  36. 36. Beispiel InputFilter // Datei /module/Customer/src/Customer/InputFilter/CustomerFilter.php namespace CustomerInputFilter; use ZendInputFilterInputFilter; class CustomerFilter extends InputFilter { public function init() { $this->add(array( 'name' => 'address', 'filters' => array( array('name' => 'CustomerAddress'), ), )); $this->add(array( 'name' => 'country', 'validators' => array( array('name' => 'CustomerCountry'), ), )); } }
  37. 37. Formularverarbeitung - Best Practices • Validierung und Formularanzeige trennen – Im Model-Service mit InputFilter validieren – Im Controller Formular bereitstellen • Controller – Plugin PostRedirectGet – Plugin FilePostRedirectGet • Spezialisierte Service-Manager verwenden
  38. 38. Application-Management Quelle: Helene Souza / wikimedia
  39. 39. Application-Management • Management des Lebenszyklus der Anwendung • Mehrere Stufen (DTAP) – Development – Testing – Acceptance – Production • Weiche in /public/index.php • Pro Stufe eigene Konfiguration
  40. 40. Application-Management Weiche // Datei /public/index.php define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); define('APPLICATION_ROOT', realpath(__DIR__ . '/..')); require_once '../vendor/autoload.php'; chdir(dirname(__DIR__)); switch (APPLICATION_ENV) { case 'production': $configFile = APPLICATION_ROOT . '/config/production.config.php'; break; case 'development': default: $configFile = APPLICATION_ROOT . '/config/development.config.php'; break; } ZendMvcApplication::init(include $configFile)->run();
  41. 41. Development Konfiguration // Datei /config/development.config.php return array( 'modules' => array( 'Application', 'User', 'Cms', 'Blog', 'ZendDeveloperTools', ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{production,development,local}.php', ), 'module_paths' => array( './module', './vendor', ), ), );
  42. 42. Production Konfiguration // Datei /config/production.config.php return array( 'modules' => array( 'Application', 'User', 'Cms', ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{production}.php', ), 'module_paths' => array( './module', './vendor', ), 'cache_dir' => './data/cache', 'config_cache_enabled' => false, 'config_cache_key' => 'module_config_cache', 'module_map_cache_enabled' => false, 'module_map_cache_key' => 'module_map_cache', ), );
  43. 43. Performance Quelle: günther gumhold / pixelio.de
  44. 44. ZF2 Performance • Modulkonfiguration cachen – Closures nicht cachebar – Achtung: Nur getConfig() wird gecached • ClassMaps und TemplateMaps einsetzen – Generator Skripte in /vendor/bin • Möglichst wenige parallele Routen • Fremdmodule – EdpSuperluminal – SpiffyNavigation – OcraCachedViewResolver
  45. 45. Performancebremsen • Größte Performancebremsen in Anwendung – Ineffiziente Datenbankabfragen – Nicht performante Berechnungen – Gelesene Daten werden nicht gecached • Generell – Einsatz eines Frameworks immer langsamer als prozedurale Skripte • Tipp – Eigenen Suchindex aufbauen
  46. 46. Security Quelle: piu700 / pixelio.de
  47. 47. ZF2 Komponenten für Security • Authentifizierung / Autorisierung – ZendAuthentication – ZendPermissions – ZendCaptcha • »Filter Input, Escape Output« – ZendFilter – ZendValidator – ZendInputFilter – ZendEscaper • Sichere Zufallswerte – ZendMath
  48. 48. Einsatzzwecke • Passwörter verschlüsseln – MD5 Hashes sind nicht sicher! – ZendCryptPasswordBcrypt • XSS vermeiden – Daten filtern und escapen • SQL Injection vermeiden – Mit ZendDbSql sicherer implementieren • Cross Site Request Forgery – ZendFormElementCsrf einsetzen
  49. 49. Migration vom ZF1 Quelle: sokaeiko / pixelio.de
  50. 50. Probleme bei Migration vom ZF1 • Kein Tool für automatische Migration • Kein Migration Layer • Migration-Guide in ZF2 Doku unvollständig • ZF1 bietet viele Freiheiten & verlangt keine 100% feste Struktur wie andere Frameworks • Allgemeingültige Schritt-für-Schritt-Anleitung für alle Anwendungen schwer umsetzbar • Kein ZF-spezifisches Problem
  51. 51. Migration ZF1 nach ZF2 • ZF1 und ZF2 parallel betreiben • Weiche in .htaccess einrichten • ZF2 Module müssen ZF1 Routing beachten • Modul für Modul migrieren • »Fat Models« leichter migrierbar • »Fat Controller« schwerer migrierbar • Weitere Quellen – Artikel im PHP Magazin 6/2013 (Teil 1) – IPC Spring Session: http://goo.gl/dgl8zH
  52. 52. Weiche in .htaccess // Datei /public/.htaccess RewriteEngine on # Slash am Ende entfernen RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L] # Umschreiberegeln für ZF2 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^$ index.zf2.php RewriteRule ^customer(.*)$ index.zf2.php RewriteRule ^order(.*)$ index.zf2.php RewriteRule ^cms(.*)$ index.zf2.php # Umschreiberegeln für ZF1 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* index.zf1.php
  53. 53. Das ZF3 kommt demnächst in diesem Kino Quelle: DASPRiD / flickr
  54. 54. Fragen?! Quelle: Tony Hegewald / pixelio.de
  55. 55. Ralf Eggert | Travello GmbH Vielen Dank für Eure Aufmerksamkeit Quelle: DASPRiD / flickr

×