Ralf Eggert | Travello GmbH
Migration vom ZF1 zum ZF2
von einfach bis fies
Über Ralf Eggert
• Dipl. Wirtschaftsinformatiker (FH)
• Jahrgang 1972
• GF Travello GmbH
• Buchautor zum ZF1 & ZF2 (AW / Galileo)
• Kolumnist PHP-Magazin
• ZF seit 2006
• Contributor
• https://profiles.google.com/eggert.ralf
Und Sie?
• Erfahrungen ZF1?
• Erfahrungen ZF2?
• Projekte schon migriert?
• Falls nein, warum nicht?
• Falls ja, Ihre Erfahrungen?
Überblick
• Einführung
• ZF1 Projekt vorbereiten
• ZF2 Skeleton integrieren
• Startseite nach ZF2 migrieren
• MVC-Layer für Blog Modul migrieren
• Authentifizierung & Autorisierung migrieren
• Model-Layer für Blog Modul migrieren
Einführung
Ausreden Gründe gegen Migration
• Technische Gründe
– PHP 5.3
• Betriebswirtschaftliche Gründe
– Kunde scheut den Aufwand
• Fachliche Gründe
– Know-how fehlt
• Organisatorische Gründe
– Keine Zeit
Gründe für Migration
• Zend Framework 1
– Keine Weiterentwicklung
– Support durch Zend wird 2014 eingestellt
• Zend Framework 2
– Stetige Weiterentwicklung
– Support durch Zend bis mindestens 2016
• Zend Framework 3
– Kommt in 2014
– Migration von ZF2 nach ZF3 deutlich einfacher
Probleme bei Migration
• Kein Tool für automatische Migration
• Kein Migration Layer (war mal versprochen)
• Migration-Guide in der ZF2 Dokumentation
fehlte lange und ist jetzt noch 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
Unterschiede ZF1 und ZF2 I
• Genutzte PHP Features
– Namespaces
– Closures
– Late Static Binding
• Git / GitHub
• Neue Konzepte
– »Echte« Modularität
– Dependency Injection / Service-Locator
– Event-Driven Architecture
Unterschiede ZF1 und ZF2 II
• ZF1: Convention over Configuration
• ZF2: Configuration over Convention
• Kein ZendRegistry im ZF2
• Kein ZendApplication im ZF2
• Zend_Controller → ZendMvc
• ZendForm: keine Dekorierer (ach menno ;-))
• ZendPdf und ZendService nicht im Core
• Viele Internationalisierungskomponenten
entfallen wegen Nutzung von ext/intl
Unterschiede ZF1 und ZF2 III
• Überarbeitete Komponenten
– ZendAuthentication, ZendDb, ZendForm,
ZendInputFilter, ZendMvc,
ZendPermissions, ZendView...
• Neue Komponenten
– ZendEventManager, ZendModuleManager,
ZendServiceManager, ZendDi, ZendStdlib...
• Ausgelagerte und entfallene Komponenten
– ZendDate, ZendDojo, ZendGdata, ZendLocale,
ZendPdf, ZendRegistry, ZendService...
»Einfache« Migration
• Zend Framework 1.11 oder 1.12 im Einsatz
• Empfohlene Projektstruktur wird eingehalten
• Anwendung in mehrere Module unterteilt
• Wenige eigene Framework-Erweiterungen
• View-Skripte verwenden PHP
• CSS und JS Frameworks beibehalten
• Thin Controllers / Fat Models
• Zend_Db_Table nur als Datenquelle verwendet
Komplexe Migration
• Zend Framework 1.8 bis 1.10 im Einsatz
• Projektstruktur teilweise eingehalten
• Anwendung unvollständig in Module unterteilt
• Einige wesentliche Framework-Erweiterungen
• View-Skripte mit gängiger Template-Engine
• CSS und JS Frameworks austauschen
• Medium Controllers / Medium Models
• Zend_Db_Table stark mit Methoden erweitert
Fiese Umsetzung
• Zend Framework 1.0 bis 1.7 im Einsatz
• Empfohlene Projektstruktur ignoriert
• Module gar nicht verwendet (Struktur)
• Sehr viele Framework-Erweiterungen
• View-Skripte setzen HTML_Template_IT ein
• Weder CSS noch JS Frameworks vorhanden
• Fat Controllers / No Models
• Zend_Db_Table wird nicht eingesetzt
Lösungsansätze
• ZF1 Anwendung in Namensräume portieren
– https://github.com/zendframework/Namespacer
– Viel manuelle Arbeit erforderlich
• ZF1 Library in ZF2 Applikation oder
ZF2 Library in ZF1 Applikation verwenden
– https://zf2.readthedocs.org/en/latest/
migration/zf1_zf2_parallel.html
• ZF1 Anwendung und ZF2 Anwendung
parallel laufen lassen
Vorgehensweise
• ZF1 Projekt vorbereiten
– »Default« Modul einrichten
– Verzeichnisse umbenennen
• ZF2 Projekt integrieren
– .htaccess Weiche für ZF1 und ZF2
• Routing beachten
• Startseite migrieren
• Nacheinander Module umziehen
Beispiel ZF1 Anwendung
• Setzt folgende Komponenten ein
– Zend_Acl, Zend_Auth, Zend_Cache, Zend_Db,
Zend_Navigation, Zend_Filter, Zend_Form,
Zend_Locale, Zend_Translate,
Zend_Validate, ...
• Verwendet
– Twitter Bootstrap
– jQuery
– CKEditor
– HTMLPurifier
Screenshot ZF1 Anwendung
Stufe 1
ZF1 Projekt vorbereiten
Erste Vorbereitungen
• Backup des ZF1 Projektes (!)
• Start mit Kopie des gesamten Projektes
• Versionsverwaltung verwenden
– Fehlerhafte Schritte sind zurück nehmbar
– Branches für verschiedene Schritte denkbar
• Neue Datenbank oder Kopie erstellen
• Neuen Virtual Host einrichten
• PHP Upgrade auf mindestens PHP 5.3.3
• Projekt in IDE der Wahl einrichten
Modul »Default« einrichten
• Pfad /application/modules/default
• Klasse Default_Bootstrap erweitert
Zend_Application_Module_Bootstrap in
Datei Bootstrap.php
• Unter /application bleiben Verzeichnis
/modules und Datei Bootstrap.php übrig
• Alles andere ins »Default« Modul
• index.php anpassen für application.ini
im »Default« Modul
Neue Projektstruktur
Konfiguration in application.ini
• Nicht mehr notwendig
– resources.frontController.controllerDirectory
• Pfade ggf. für »Default« Modul anpassen
– resources.layout.layoutPath
– resources.view.basePath
– resources.translate.content
• Aufnehmen, falls nicht vorhanden
– resources.modules[] = ""
• Einstellungen für Staging development,
production, usw. überprüfen
Verzeichnisse umbenennen
• Verzeichnisse umbenennen
– /application => /application.zf1
– /data => /data.zf1
– /library => /library.zf1
– /tests => /tests.zf1
• Konfiguration für Verzeichnisse anpassen
– APPLICATION_PATH in /public/index.php
– include_path in /public/index.php
– Pfade in application.ini
ZF1 Front-Controller-Datei
• Datei umbenennen in /public
– index.php => index.zf1.php
• Konfiguration in .htaccess anpassen
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.zf1.php
Anwendung prüfen!
• Läuft die Anwendung noch?
• Sind alle Module aufrufbar?
• Sind alle Seiten des »Default« Moduls
aufrufbar (Homepage, usw.)?
• Werden alle Seitenbereiche angezeigt?
• Was ist mit Übersetzungen?
• Macht PHP 5.3 Probleme?
• Erst wenn alles läuft, Migration fortsetzen!
Stufe 2
ZF2 Skeleton integrieren
Skeleton Application downloaden
• Als ZIP herunterladen und entpacken
– https://github.com/zendframework/
ZendSkeletonApplication
• Alle Dateien und Verzeichnisse ins ZF1
Projekt kopieren außer
– /public
• ZF2 installieren
– php composer.phar selfupdate
– php composer.phar install
ZF2 Front-Controller-Datei
• Aus SkeletonApplication ins ZF1 Projekt
– index.php => index.zf2.php
• PROJECT_PATH, APPLICATION_PATH und
APPLICATION_ENV definieren
• Konfiguration in .htaccess anpassen
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^application(.*)$ index.zf2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.zf1.php
ZF2 Assets
• Asset Verzeichnisse ins ZF1 Projekt kopieren
– /public/css
– /public/img
– /public/js
• Ggf. auf Dateiüberschreibungen achten
– Verschiedene Twitter Bootstrap Versionen?
– Verschiedene jQuery Versionen?
– Grafiken wie favicon.ico
• style.css aus SkeletonApplication ignorieren
Anwendung prüfen!
• Prüfen, ob alle Seiten aus der alten ZF1
Anwendung korrekt angezeigt werden!
• Was passiert beim Aufruf der neuen URL
/application?
• Wird Twitter Bootstrap, jQuery geladen?
• Wenn alles klappt, wird ZF2 Skeleton
Application angezeigt
• => ZF1 und ZF2 laufen parallel
Vorteile dieses Ansatzes
• Das alte ZF1 Projekt kann parallel zu neuen
ZF2 Features betrieben werden
• Features können schrittweise von ZF1 nach
ZF2 portiert werden
• Wenn alle alten ZF1 Features portiert sind,
können .zf1 Verzeichnisse entfernt werden
Nachteile dieses Ansatzes
• Layouts sind unabhängig
– Lösung: Layouts duplizieren
• Konfigurierbare Kombination einer Navigation
aus ZF1 und ZF2 nur schwer möglich
– Lösung: Navigation duplizieren
• Ist Nutzer in ZF1 angemeldet, ist geschützter
Zugriff auf ZF2 Module erschwert
– Lösung: Sessions in Datenbank speichern
Routing
• Überschneidungen beim Routing vermeiden!
• Neue ZF2 Features bekommen neue Routen
• Vorhandene ZF1 Routen wiederverwenden,
wenn ZF2 Modul ein altes ZF1 Modul ersetzt
• Im ZF2 keine »globalen« Routen verwenden
• Starter für neue ZF2 Routen müssen in
der .htaccess notiert werden
Stufe 3
Startseite nach ZF2
migrieren
.htaccess anpassen
• Anfragen für Homepage auf index.zf2.php
umleiten
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$|^en$ index.zf2.php
RewriteRule ^application(.*)$ index.zf2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* start.zf1.php
• Testen!
Layout migrieren
• Aus dem ZF1 ins ZF2 kopieren
• Veränderte View-Helper anpassen
• Fehlende View-Helper auskommentieren
• Layout hierarchisch?
– Header, Footer, Sidebar
– Umsetzung z.B. mit ApplicationListener
• SkeletonApplication Assets entfernen
– CSS Datei style.css & Grafik zfs-logo.png
• Testen!
Navigation migrieren
• ZF1 Navigation
– /application.zf1/modules/default/configs/
application.ini
• ZF2 Navigation konfigurieren
– /module/Application/config/module.config.php
– Service nicht vergessen!
• Links zur ZF1 Anwendung als URI definieren
– Nach Migration der Module ändern
• Partial für Ausgabe im Twitter Bootstrap Style
• Testen!
Translator migrieren I
• Dateien der SkeletonApplication löschen
– /module/Application/language/*
• Übersetzungsdateien kopieren
– Von /modules/default/locales/*.php
– Nach /module/Application/language/
• Konfiguration in module.config.php ändern
• Testen!
Translator migrieren II
• Fehlende Module unter /module anlegen
– /module/ModulName/config/
module.config.php => translator
– /module/ModulName/language/
– /module/ModulName/Module.php : getConfig()
• Übersetzungsdateien kopieren
– Für jedes Modul
• Module aktivieren
– /config/application.config.php
• Testen!
Autoloading für ZF1 Dateien I
• ClassMap für ZF1 Module erstellen
– in /application.zf1/modules
• Konfiguration im Application Modul
– Module::getAutoloaderConfig()
• Wahlweise
– include_path in /public/index.php ergänzen
mit PROJECT_ROOT . '/library.zf1'
– Alle require_once Statements aus den ZF1
Library Dateien entfernen
Autoloading für ZF1 Dateien II
namespace Application;
class Module
{
public function getAutoloaderConfig()
{
return array(
'ZendLoaderClassMapAutoloader' => array(
'zf1' => PROJECT_ROOT
. '/application.zf1/modules/autoload_classmap.php',
),
'ZendLoaderStandardAutoloader' => array(
'autoregister_zf' => true,
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
'prefixes' => array(
'Zend' => PROJECT_ROOT . '/library.zf1/Zend',
'Company' => PROJECT_ROOT . '/library.zf1/Company',
),
),
);
}
}
ZF1 Model-Service in ZF2 nutzen
• IndexController in Application Modul
greift auf Blog_Service_Article zu
• Klasse sollte gefunden werden
• Konfigurationsprobleme
– cache nicht in Zend_Registry vorhanden
– Kein Default Adapter für Zend_Db_Table gesetzt
• Lösung:
– CompatibilityListener einrichten, um
Konfigurationsprobleme zu lösen
CompatibilityListener (Auszug)
namespace ApplicationListener;
class CompatibilityListener implements ListenerAggregateInterface
{
[...]
public function setupZF1Compatibility(EventInterface $e)
{
$config = new Zend_Config_Ini(
PROJECT_PATH . '/application.zf1/modules/default/configs/application.ini',
APPLICATION_ENV
);
$cacheOptions = $config->resources->cachemanager->database->toArray();
$cache = Zend_Cache::factory(
$cacheOptions['frontend']['name' ],
$cacheOptions['backend' ]['name' ],
$cacheOptions['frontend']['options'],
$cacheOptions['backend' ]['options']
);
Zend_Registry::set('cache', $cache);
$dbOptions = $config->resources->db->toArray();
$db = Zend_Db::factory($dbOptions['adapter'], $dbOptions['params']);
Zend_Db_Table::setDefaultAdapter($db);
}
}
Startseiten View-Skript migrieren I
• View-Skript kopieren
– Von /application.zf1/modules/default/
views/scripts/index/index.phtml
– Nach /module/Application/view/
application/index/index.phtml
• Probleme mit View-Helpern
– URL View-Helper fehlen Routen
– URL View-Helper andere Parameter-Reihenfolge
– View-Helper Date und Time fehlen
Startseiten View-Skript migrieren II
• Eigenen Date View-Helper einrichten
– Zur Ausgabe von Datumswerte
– Konfiguration für Service-Manager
• Alternative
– DateFormat View-Helper
• Testen!
Offene Punkte
• Navigation zeigt alle Menüpunkte, da noch
keine ACL eingerichtet ist
• User Widget fehlt noch in der Seitenleiste
• Modul User migrieren
• Modul Blog migrieren
Screenshot ZF2 Anwendung
Zusammenfassung
• ZF2 Anwendung kann ZF1 Klassen
verwenden
• Layout, Navigation, Translator und View-
Skript wurden migriert
• CompatibilityListener für Migration von
Konfigurationseinstellungen
• ZF1 Module wurden zum Teil in ZF2
Anwendung eingerichtet
• Startseite nutzt Blog_Service_Article
Stufe 4
MVC-Layer für
Blog Modul migrieren
Routing migrieren I
• Anfragen für Blog Modul in .htaccess
umleiten
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$|^en$ index.zf2.php
RewriteRule ^application(.*)$ index.zf2.php
RewriteRule ^(de|en)/blog|beitrag|kategorie
|nutzer(.*)$ index.zf2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* start.zf1.php
Routing migrieren II
• Jedes ZF2 Modul sollte immer mindestens
eine eigene Route haben
– Nicht auf eine globale Route verlassen!
• Es werden vier Routen benötigt
– Generelle Route für Blog Modul
– Spezielle Route für Blogbeiträge
– Spezielle Route für Beiträge einer Blogkategorie
– Spezielle Route für Beiträge eines Nutzers
Navigation migrieren
• Navigation-Konfiguration aus Application
Modul ins Blog Modul verschieben
• Seitentyp von uri auf mvc wechseln
• Reihenfolge der Menüpunkte durch
Parameter order festlegen
Controller migrieren I
• Controller in module.config.php
konfigurieren und mit Routen matchen
• Verzeichnis anlegen
– /module/Blog/src/Blog/Controller
• Controller mit benötigten Methoden anlegen
– IndexController mit indexAction(),
showAction(), categoryAction(), usw.
– AdminController
– CategoryController
– usw.
Controller migrieren II
• Code der Aktionsmethoden aus ZF1 Modul
übernehmen und anpassen
– Parameter holen mit params() Controller-Plugin
– Umleitungen für redirect() Plugin anpassen
– URL-Generierung für url() Plugin anpassen
– Templatevariablen an ViewModel übergeben
• Verwendung der ZF1 Model-Services kann
vorerst beibehalten werden
View-Skripte migrieren
• View-Manager konfigurieren, damit View-
Skripte gefunden werden können
• Verzeichnisse anlegen
– /module/Blog/view/blog/index/
– /module/Blog/view/blog/admin/
– /module/Blog/view/blog/category/
• Code der View-Skripte aus ZF1 Modul
übernehmen und anpassen
– Einsatz der Standard View-Helper überprüfen
– Eigene View-Helper migrieren
View-Helper migrieren
• View-Helper im Modul Blog konfigurieren,
damit sie gefunden werden
• Im View-Helper darauf achten:
– Statt $this->view wie im ZF1 muss im ZF2
$this->getView() verwendet werden
– Auf Parameter der Standard View-Helper achten
• Url, Translate, usw.
• Anwendung testen!
Model-Layer & Forms übernehmen
• Im Administrationsbereich werden vorerst
folgende ZF1 Klassen weiterverwendet
– Model-Layer mit Entities, Datenquellen, Mapper
und Model-Service
– Formulare mit Filtern und Validatoren
• Im CompatibilityListener konfigurieren
– Zend_Controller_Front benötigt ggf. Instanzen
vom Request und Response Objekt
– Zend_Translate zur Verwendung mit Zend_Form
– Namensräume für eigene Filter und Validatoren
CompatibilityListener (Auszug) I
namespace ApplicationListener;
class CompatibilityListener implements ListenerAggregateInterface
{
public function setupZF1Compatibility(EventInterface $e)
{
Zend_Controller_Front::getInstance()
->setRequest(new Zend_Controller_Request_Http())
->setResponse(new Zend_Controller_Response_Http())
->setDispatcher(new Zend_Controller_Dispatcher_Standard());
$translations = array();
$applicationConfig = $e->getApplication()->getServiceManager()
->get('ApplicationConfig');
foreach ($applicationConfig['modules'] as $module) {
$localesFile = PROJECT_PATH . '/module/' . $module . '/language/'
. $e->getRouteMatch()->getParam('lang') . '.php';
if (file_exists($localesFile)) {
$translations = array_merge($translations, include $localesFile);
ksort($translations);
}
}
[...]
CompatibilityListener (Auszug) II
[...]
$translator = new Zend_Translate(array(
'adapter' => 'Array',
'content' => $localesFile,
'locale' => $e->getRouteMatch()->getParam('lang'),
));
$translator->addTranslation(
$translations, $e->getRouteMatch()->getParam('lang')
);
Zend_Form::setDefaultTranslator($translator);
Zend_Filter::addDefaultNamespaces('Company_Filter');
Zend_Validate::addDefaultNamespaces('Company_Validate');
}
}
Weitere Migrationen
• AdminController zum Pflegen der
Blogbeiträge inkl. der View-Skripts
• CategoryController zum Pflegen der
Blogkategorien inkl. der View-Skripts
• ZF1 Formulare benötigen für Ausgabe eine
Zend_View Instanz!
• Testen!
Zusammenfassung
• Blog Modul läuft auf ZF2 mit einigen
Einschränkungen
– Verwendet noch ZF1 Model-Layer
– Verwendet noch ZF1 Formulare
– Verwendet noch ZF1 Filter und Validatoren
– Ist abhängig vom CompatibilityListener
Stufe 5
Authentifizierung &
Autorisierung migrieren
User-Widget migrieren
• View-Helper migrieren
• Anfragen zum Einloggen auf ZF1 User Modul
umleiten
• View-Helper konfigurieren
• UserWidget in Seitenleiste ausgeben
Authentifizierung
• CompatibilityListener konfiguriert
Zend_Session für ZF1 Authentifizierung
– Konfiguration aus application.ini holen
– SaveHandler einrichten
– Session konfigurieren
– Zend_Auth Instanz im Service-Manager als
Service »UserAuthentication« speichern
CompatibilityListener (Auszug)
namespace ApplicationListener;
class CompatibilityListener implements ListenerAggregateInterface
{
public function setupZF1Compatibility(EventInterface $e)
{
[...]
$sessionOptions = $config->resources->session->toArray();
$saveHandlerClass = $sessionOptions['saveHandler']['class'];
$saveHandler = new $saveHandlerClass(
$sessionOptions['saveHandler']['options']
);
unset($sessionOptions['saveHandler']);
Zend_Session::setOptions($sessionOptions);
Zend_Session::setSaveHandler($saveHandler);
$e->getApplication()->getServiceManager()
->setService('UserAuthentication', Zend_Auth::getInstance());
}
}
Autorisierung
• Konfiguration der Benutzerrechte in den
module.config.php Dateien der Module
• Erstellung von UserAclAcl, die ZendAcl
erweitert und ACL-Konfiguration verarbeitet
• Factory für UserAclAcl
• AuthorizationListener zum Prüfen der
Benutzerrechte mit ACL und der Rolle
– Bei fehlenden Rechten Umleitung auf forbidden
Seite des ZF1 User Moduls
ACL mit Navigation kombinieren
• Konfiguration der Navigation mit Parametern
resource und privilege erweitern
• Navigation-Konfiguration auf MVC Seiten
umstellen
• Navigation für User Modul ins Modul
• Erweiterung vom AuthorizationListener
zur Übergabe der aktuellen Zend_Auth Rolle
sowie ACL an Navigation View-Helper
Zusammenfassung
• ZF2 der Anwendung nutzt Authentifizierung
des ZF1 User Moduls
• ZF2 der Anwendung stellt Autorisierung
selber bereit (wegen ZendNavigation)
• User-Widget leitet entsprechend auf ZF1
User Modul um
• Später kann gesamtes User Modul migriert
werden
Stufe 6
Model-Layer für
Blog Modul migrieren
Model-Entities
• Model-Entities nahezu 1:1 migrierbar
• Umschreibung auf Namensräume sinnvoll
• ZendStdlibArraySerializableInterface
– Implementation sinnvoll
– Für Einsatz mit Hydratoren
• Instanzierung über Service-Manager
Table-Gateways
• ZendDbTableGatewayTableGateway als
Datenquelle implementieren
• Einsatz eines ResultSets mit Hydratoren,
um Instanzen der Model-Entities zu erhalten
• Abfragen von Daten als Methoden mithilfe
von ZendDbSqlSql implementieren
• Ansonsten nicht zu viel Logik implementieren
• Instanzierung über Service-Manager
Mapper und Hydratoren I
• Aufgaben des Mappers
– Übergabe Arraydaten an Objekt und umgekehrt
– Aufbereitung Daten zum Schreiben in Datenbank
– Methoden zum Lesen der Daten
• Mapper auflösen
– Aufbereitung der Daten zum Schreiben
→ Model-Service
– Methoden zum Lesen der Daten
→ TableGateway
Mapper und Hydratoren II
• Hydrator kann Eigenschaften eines Objektes
mit Arraydaten befüllen und umgekehrt
– Datenbank → Objekt
– Objekt → Datenbank
– Formulardaten → Objekt
• Beispiele für Hydratoren
– ZendStdlibHydratorArraySerializable
– ZendStdlibHydratorClassMethods
– ZendStdlibHydratorReflection ...
• Einsatz des Hydrator-Service-Managers
Model-Services
• Model-Services nahezu 1:1 migrierbar
– Verknüpfung zum Mapper nicht notwendig
– Stattdessen Abfragen direkt an TableGateway
– Methoden create(), update() und delete()
bereiten Daten für TableGateway vor
– Ggf. Einsatz von ZendPaginator sinnvoll, da mit
Model-Entities kombinierbar
• Ging im ZF1 nicht ohne weiteres
• Instanzierung über Service-Manager
Formulare
• Große Unterschiede zwischen ZF1 und ZF2
– Keine Dekoratoren (schade!)
– Ausgabe per View-Helper
– Kombination mit Input-Filtern, Hydratoren und
Model-Entities möglich
• Alle Formulare von Grund auf neu aufbauen!
• Dazu Input-Filter erstellen, die auch
unabhängig vom Formular verwendbar sind
• Instanzierung über Service-Manager
Fazit
• Selbst für eine gut vorbereitete ZF1
Anwendung ist Migration zum ZF2 aufwändig
• Bei komplexeren Anwendungen ist ein
Schritt-für-Schritt Neubau meist sinnvoll
• Tipp:
– Nicht als erstes ZF2 Projekt ein ZF1 migrieren
– Stattdessen ein neues ZF2 Projekt aufbauen, um
sich einzuarbeiten
Vielen Dank für
Ihre Aufmerksamkeit!
Ralf Eggert
https://profiles.google.com/eggert.ralf

Migration vom ZF1 zum ZF2 von einfach bis fies (IPC Spring 2013, Berlin)

  • 1.
    Ralf Eggert |Travello GmbH Migration vom ZF1 zum ZF2 von einfach bis fies
  • 2.
    Über Ralf Eggert •Dipl. Wirtschaftsinformatiker (FH) • Jahrgang 1972 • GF Travello GmbH • Buchautor zum ZF1 & ZF2 (AW / Galileo) • Kolumnist PHP-Magazin • ZF seit 2006 • Contributor • https://profiles.google.com/eggert.ralf
  • 3.
    Und Sie? • ErfahrungenZF1? • Erfahrungen ZF2? • Projekte schon migriert? • Falls nein, warum nicht? • Falls ja, Ihre Erfahrungen?
  • 4.
    Überblick • Einführung • ZF1Projekt vorbereiten • ZF2 Skeleton integrieren • Startseite nach ZF2 migrieren • MVC-Layer für Blog Modul migrieren • Authentifizierung & Autorisierung migrieren • Model-Layer für Blog Modul migrieren
  • 5.
  • 6.
    Ausreden Gründe gegenMigration • Technische Gründe – PHP 5.3 • Betriebswirtschaftliche Gründe – Kunde scheut den Aufwand • Fachliche Gründe – Know-how fehlt • Organisatorische Gründe – Keine Zeit
  • 7.
    Gründe für Migration •Zend Framework 1 – Keine Weiterentwicklung – Support durch Zend wird 2014 eingestellt • Zend Framework 2 – Stetige Weiterentwicklung – Support durch Zend bis mindestens 2016 • Zend Framework 3 – Kommt in 2014 – Migration von ZF2 nach ZF3 deutlich einfacher
  • 8.
    Probleme bei Migration •Kein Tool für automatische Migration • Kein Migration Layer (war mal versprochen) • Migration-Guide in der ZF2 Dokumentation fehlte lange und ist jetzt noch 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
  • 9.
    Unterschiede ZF1 undZF2 I • Genutzte PHP Features – Namespaces – Closures – Late Static Binding • Git / GitHub • Neue Konzepte – »Echte« Modularität – Dependency Injection / Service-Locator – Event-Driven Architecture
  • 10.
    Unterschiede ZF1 undZF2 II • ZF1: Convention over Configuration • ZF2: Configuration over Convention • Kein ZendRegistry im ZF2 • Kein ZendApplication im ZF2 • Zend_Controller → ZendMvc • ZendForm: keine Dekorierer (ach menno ;-)) • ZendPdf und ZendService nicht im Core • Viele Internationalisierungskomponenten entfallen wegen Nutzung von ext/intl
  • 11.
    Unterschiede ZF1 undZF2 III • Überarbeitete Komponenten – ZendAuthentication, ZendDb, ZendForm, ZendInputFilter, ZendMvc, ZendPermissions, ZendView... • Neue Komponenten – ZendEventManager, ZendModuleManager, ZendServiceManager, ZendDi, ZendStdlib... • Ausgelagerte und entfallene Komponenten – ZendDate, ZendDojo, ZendGdata, ZendLocale, ZendPdf, ZendRegistry, ZendService...
  • 12.
    »Einfache« Migration • ZendFramework 1.11 oder 1.12 im Einsatz • Empfohlene Projektstruktur wird eingehalten • Anwendung in mehrere Module unterteilt • Wenige eigene Framework-Erweiterungen • View-Skripte verwenden PHP • CSS und JS Frameworks beibehalten • Thin Controllers / Fat Models • Zend_Db_Table nur als Datenquelle verwendet
  • 13.
    Komplexe Migration • ZendFramework 1.8 bis 1.10 im Einsatz • Projektstruktur teilweise eingehalten • Anwendung unvollständig in Module unterteilt • Einige wesentliche Framework-Erweiterungen • View-Skripte mit gängiger Template-Engine • CSS und JS Frameworks austauschen • Medium Controllers / Medium Models • Zend_Db_Table stark mit Methoden erweitert
  • 14.
    Fiese Umsetzung • ZendFramework 1.0 bis 1.7 im Einsatz • Empfohlene Projektstruktur ignoriert • Module gar nicht verwendet (Struktur) • Sehr viele Framework-Erweiterungen • View-Skripte setzen HTML_Template_IT ein • Weder CSS noch JS Frameworks vorhanden • Fat Controllers / No Models • Zend_Db_Table wird nicht eingesetzt
  • 15.
    Lösungsansätze • ZF1 Anwendungin Namensräume portieren – https://github.com/zendframework/Namespacer – Viel manuelle Arbeit erforderlich • ZF1 Library in ZF2 Applikation oder ZF2 Library in ZF1 Applikation verwenden – https://zf2.readthedocs.org/en/latest/ migration/zf1_zf2_parallel.html • ZF1 Anwendung und ZF2 Anwendung parallel laufen lassen
  • 16.
    Vorgehensweise • ZF1 Projektvorbereiten – »Default« Modul einrichten – Verzeichnisse umbenennen • ZF2 Projekt integrieren – .htaccess Weiche für ZF1 und ZF2 • Routing beachten • Startseite migrieren • Nacheinander Module umziehen
  • 17.
    Beispiel ZF1 Anwendung •Setzt folgende Komponenten ein – Zend_Acl, Zend_Auth, Zend_Cache, Zend_Db, Zend_Navigation, Zend_Filter, Zend_Form, Zend_Locale, Zend_Translate, Zend_Validate, ... • Verwendet – Twitter Bootstrap – jQuery – CKEditor – HTMLPurifier
  • 18.
  • 19.
  • 20.
    Erste Vorbereitungen • Backupdes ZF1 Projektes (!) • Start mit Kopie des gesamten Projektes • Versionsverwaltung verwenden – Fehlerhafte Schritte sind zurück nehmbar – Branches für verschiedene Schritte denkbar • Neue Datenbank oder Kopie erstellen • Neuen Virtual Host einrichten • PHP Upgrade auf mindestens PHP 5.3.3 • Projekt in IDE der Wahl einrichten
  • 21.
    Modul »Default« einrichten •Pfad /application/modules/default • Klasse Default_Bootstrap erweitert Zend_Application_Module_Bootstrap in Datei Bootstrap.php • Unter /application bleiben Verzeichnis /modules und Datei Bootstrap.php übrig • Alles andere ins »Default« Modul • index.php anpassen für application.ini im »Default« Modul
  • 22.
  • 23.
    Konfiguration in application.ini •Nicht mehr notwendig – resources.frontController.controllerDirectory • Pfade ggf. für »Default« Modul anpassen – resources.layout.layoutPath – resources.view.basePath – resources.translate.content • Aufnehmen, falls nicht vorhanden – resources.modules[] = "" • Einstellungen für Staging development, production, usw. überprüfen
  • 24.
    Verzeichnisse umbenennen • Verzeichnisseumbenennen – /application => /application.zf1 – /data => /data.zf1 – /library => /library.zf1 – /tests => /tests.zf1 • Konfiguration für Verzeichnisse anpassen – APPLICATION_PATH in /public/index.php – include_path in /public/index.php – Pfade in application.ini
  • 25.
    ZF1 Front-Controller-Datei • Dateiumbenennen in /public – index.php => index.zf1.php • Konfiguration in .htaccess anpassen RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* index.zf1.php
  • 26.
    Anwendung prüfen! • Läuftdie Anwendung noch? • Sind alle Module aufrufbar? • Sind alle Seiten des »Default« Moduls aufrufbar (Homepage, usw.)? • Werden alle Seitenbereiche angezeigt? • Was ist mit Übersetzungen? • Macht PHP 5.3 Probleme? • Erst wenn alles läuft, Migration fortsetzen!
  • 27.
  • 28.
    Skeleton Application downloaden •Als ZIP herunterladen und entpacken – https://github.com/zendframework/ ZendSkeletonApplication • Alle Dateien und Verzeichnisse ins ZF1 Projekt kopieren außer – /public • ZF2 installieren – php composer.phar selfupdate – php composer.phar install
  • 29.
    ZF2 Front-Controller-Datei • AusSkeletonApplication ins ZF1 Projekt – index.php => index.zf2.php • PROJECT_PATH, APPLICATION_PATH und APPLICATION_ENV definieren • Konfiguration in .htaccess anpassen RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^application(.*)$ index.zf2.php RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* index.zf1.php
  • 30.
    ZF2 Assets • AssetVerzeichnisse ins ZF1 Projekt kopieren – /public/css – /public/img – /public/js • Ggf. auf Dateiüberschreibungen achten – Verschiedene Twitter Bootstrap Versionen? – Verschiedene jQuery Versionen? – Grafiken wie favicon.ico • style.css aus SkeletonApplication ignorieren
  • 31.
    Anwendung prüfen! • Prüfen,ob alle Seiten aus der alten ZF1 Anwendung korrekt angezeigt werden! • Was passiert beim Aufruf der neuen URL /application? • Wird Twitter Bootstrap, jQuery geladen? • Wenn alles klappt, wird ZF2 Skeleton Application angezeigt • => ZF1 und ZF2 laufen parallel
  • 32.
    Vorteile dieses Ansatzes •Das alte ZF1 Projekt kann parallel zu neuen ZF2 Features betrieben werden • Features können schrittweise von ZF1 nach ZF2 portiert werden • Wenn alle alten ZF1 Features portiert sind, können .zf1 Verzeichnisse entfernt werden
  • 33.
    Nachteile dieses Ansatzes •Layouts sind unabhängig – Lösung: Layouts duplizieren • Konfigurierbare Kombination einer Navigation aus ZF1 und ZF2 nur schwer möglich – Lösung: Navigation duplizieren • Ist Nutzer in ZF1 angemeldet, ist geschützter Zugriff auf ZF2 Module erschwert – Lösung: Sessions in Datenbank speichern
  • 34.
    Routing • Überschneidungen beimRouting vermeiden! • Neue ZF2 Features bekommen neue Routen • Vorhandene ZF1 Routen wiederverwenden, wenn ZF2 Modul ein altes ZF1 Modul ersetzt • Im ZF2 keine »globalen« Routen verwenden • Starter für neue ZF2 Routen müssen in der .htaccess notiert werden
  • 35.
  • 36.
    .htaccess anpassen • Anfragenfür Homepage auf index.zf2.php umleiten RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^$|^en$ index.zf2.php RewriteRule ^application(.*)$ index.zf2.php RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* start.zf1.php • Testen!
  • 37.
    Layout migrieren • Ausdem ZF1 ins ZF2 kopieren • Veränderte View-Helper anpassen • Fehlende View-Helper auskommentieren • Layout hierarchisch? – Header, Footer, Sidebar – Umsetzung z.B. mit ApplicationListener • SkeletonApplication Assets entfernen – CSS Datei style.css & Grafik zfs-logo.png • Testen!
  • 38.
    Navigation migrieren • ZF1Navigation – /application.zf1/modules/default/configs/ application.ini • ZF2 Navigation konfigurieren – /module/Application/config/module.config.php – Service nicht vergessen! • Links zur ZF1 Anwendung als URI definieren – Nach Migration der Module ändern • Partial für Ausgabe im Twitter Bootstrap Style • Testen!
  • 39.
    Translator migrieren I •Dateien der SkeletonApplication löschen – /module/Application/language/* • Übersetzungsdateien kopieren – Von /modules/default/locales/*.php – Nach /module/Application/language/ • Konfiguration in module.config.php ändern • Testen!
  • 40.
    Translator migrieren II •Fehlende Module unter /module anlegen – /module/ModulName/config/ module.config.php => translator – /module/ModulName/language/ – /module/ModulName/Module.php : getConfig() • Übersetzungsdateien kopieren – Für jedes Modul • Module aktivieren – /config/application.config.php • Testen!
  • 41.
    Autoloading für ZF1Dateien I • ClassMap für ZF1 Module erstellen – in /application.zf1/modules • Konfiguration im Application Modul – Module::getAutoloaderConfig() • Wahlweise – include_path in /public/index.php ergänzen mit PROJECT_ROOT . '/library.zf1' – Alle require_once Statements aus den ZF1 Library Dateien entfernen
  • 42.
    Autoloading für ZF1Dateien II namespace Application; class Module { public function getAutoloaderConfig() { return array( 'ZendLoaderClassMapAutoloader' => array( 'zf1' => PROJECT_ROOT . '/application.zf1/modules/autoload_classmap.php', ), 'ZendLoaderStandardAutoloader' => array( 'autoregister_zf' => true, 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), 'prefixes' => array( 'Zend' => PROJECT_ROOT . '/library.zf1/Zend', 'Company' => PROJECT_ROOT . '/library.zf1/Company', ), ), ); } }
  • 43.
    ZF1 Model-Service inZF2 nutzen • IndexController in Application Modul greift auf Blog_Service_Article zu • Klasse sollte gefunden werden • Konfigurationsprobleme – cache nicht in Zend_Registry vorhanden – Kein Default Adapter für Zend_Db_Table gesetzt • Lösung: – CompatibilityListener einrichten, um Konfigurationsprobleme zu lösen
  • 44.
    CompatibilityListener (Auszug) namespace ApplicationListener; classCompatibilityListener implements ListenerAggregateInterface { [...] public function setupZF1Compatibility(EventInterface $e) { $config = new Zend_Config_Ini( PROJECT_PATH . '/application.zf1/modules/default/configs/application.ini', APPLICATION_ENV ); $cacheOptions = $config->resources->cachemanager->database->toArray(); $cache = Zend_Cache::factory( $cacheOptions['frontend']['name' ], $cacheOptions['backend' ]['name' ], $cacheOptions['frontend']['options'], $cacheOptions['backend' ]['options'] ); Zend_Registry::set('cache', $cache); $dbOptions = $config->resources->db->toArray(); $db = Zend_Db::factory($dbOptions['adapter'], $dbOptions['params']); Zend_Db_Table::setDefaultAdapter($db); } }
  • 45.
    Startseiten View-Skript migrierenI • View-Skript kopieren – Von /application.zf1/modules/default/ views/scripts/index/index.phtml – Nach /module/Application/view/ application/index/index.phtml • Probleme mit View-Helpern – URL View-Helper fehlen Routen – URL View-Helper andere Parameter-Reihenfolge – View-Helper Date und Time fehlen
  • 46.
    Startseiten View-Skript migrierenII • Eigenen Date View-Helper einrichten – Zur Ausgabe von Datumswerte – Konfiguration für Service-Manager • Alternative – DateFormat View-Helper • Testen!
  • 47.
    Offene Punkte • Navigationzeigt alle Menüpunkte, da noch keine ACL eingerichtet ist • User Widget fehlt noch in der Seitenleiste • Modul User migrieren • Modul Blog migrieren
  • 48.
  • 49.
    Zusammenfassung • ZF2 Anwendungkann ZF1 Klassen verwenden • Layout, Navigation, Translator und View- Skript wurden migriert • CompatibilityListener für Migration von Konfigurationseinstellungen • ZF1 Module wurden zum Teil in ZF2 Anwendung eingerichtet • Startseite nutzt Blog_Service_Article
  • 50.
  • 51.
    Routing migrieren I •Anfragen für Blog Modul in .htaccess umleiten RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^$|^en$ index.zf2.php RewriteRule ^application(.*)$ index.zf2.php RewriteRule ^(de|en)/blog|beitrag|kategorie |nutzer(.*)$ index.zf2.php RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* start.zf1.php
  • 52.
    Routing migrieren II •Jedes ZF2 Modul sollte immer mindestens eine eigene Route haben – Nicht auf eine globale Route verlassen! • Es werden vier Routen benötigt – Generelle Route für Blog Modul – Spezielle Route für Blogbeiträge – Spezielle Route für Beiträge einer Blogkategorie – Spezielle Route für Beiträge eines Nutzers
  • 53.
    Navigation migrieren • Navigation-Konfigurationaus Application Modul ins Blog Modul verschieben • Seitentyp von uri auf mvc wechseln • Reihenfolge der Menüpunkte durch Parameter order festlegen
  • 54.
    Controller migrieren I •Controller in module.config.php konfigurieren und mit Routen matchen • Verzeichnis anlegen – /module/Blog/src/Blog/Controller • Controller mit benötigten Methoden anlegen – IndexController mit indexAction(), showAction(), categoryAction(), usw. – AdminController – CategoryController – usw.
  • 55.
    Controller migrieren II •Code der Aktionsmethoden aus ZF1 Modul übernehmen und anpassen – Parameter holen mit params() Controller-Plugin – Umleitungen für redirect() Plugin anpassen – URL-Generierung für url() Plugin anpassen – Templatevariablen an ViewModel übergeben • Verwendung der ZF1 Model-Services kann vorerst beibehalten werden
  • 56.
    View-Skripte migrieren • View-Managerkonfigurieren, damit View- Skripte gefunden werden können • Verzeichnisse anlegen – /module/Blog/view/blog/index/ – /module/Blog/view/blog/admin/ – /module/Blog/view/blog/category/ • Code der View-Skripte aus ZF1 Modul übernehmen und anpassen – Einsatz der Standard View-Helper überprüfen – Eigene View-Helper migrieren
  • 57.
    View-Helper migrieren • View-Helperim Modul Blog konfigurieren, damit sie gefunden werden • Im View-Helper darauf achten: – Statt $this->view wie im ZF1 muss im ZF2 $this->getView() verwendet werden – Auf Parameter der Standard View-Helper achten • Url, Translate, usw. • Anwendung testen!
  • 58.
    Model-Layer & Formsübernehmen • Im Administrationsbereich werden vorerst folgende ZF1 Klassen weiterverwendet – Model-Layer mit Entities, Datenquellen, Mapper und Model-Service – Formulare mit Filtern und Validatoren • Im CompatibilityListener konfigurieren – Zend_Controller_Front benötigt ggf. Instanzen vom Request und Response Objekt – Zend_Translate zur Verwendung mit Zend_Form – Namensräume für eigene Filter und Validatoren
  • 59.
    CompatibilityListener (Auszug) I namespaceApplicationListener; class CompatibilityListener implements ListenerAggregateInterface { public function setupZF1Compatibility(EventInterface $e) { Zend_Controller_Front::getInstance() ->setRequest(new Zend_Controller_Request_Http()) ->setResponse(new Zend_Controller_Response_Http()) ->setDispatcher(new Zend_Controller_Dispatcher_Standard()); $translations = array(); $applicationConfig = $e->getApplication()->getServiceManager() ->get('ApplicationConfig'); foreach ($applicationConfig['modules'] as $module) { $localesFile = PROJECT_PATH . '/module/' . $module . '/language/' . $e->getRouteMatch()->getParam('lang') . '.php'; if (file_exists($localesFile)) { $translations = array_merge($translations, include $localesFile); ksort($translations); } } [...]
  • 60.
    CompatibilityListener (Auszug) II [...] $translator= new Zend_Translate(array( 'adapter' => 'Array', 'content' => $localesFile, 'locale' => $e->getRouteMatch()->getParam('lang'), )); $translator->addTranslation( $translations, $e->getRouteMatch()->getParam('lang') ); Zend_Form::setDefaultTranslator($translator); Zend_Filter::addDefaultNamespaces('Company_Filter'); Zend_Validate::addDefaultNamespaces('Company_Validate'); } }
  • 61.
    Weitere Migrationen • AdminControllerzum Pflegen der Blogbeiträge inkl. der View-Skripts • CategoryController zum Pflegen der Blogkategorien inkl. der View-Skripts • ZF1 Formulare benötigen für Ausgabe eine Zend_View Instanz! • Testen!
  • 62.
    Zusammenfassung • Blog Modulläuft auf ZF2 mit einigen Einschränkungen – Verwendet noch ZF1 Model-Layer – Verwendet noch ZF1 Formulare – Verwendet noch ZF1 Filter und Validatoren – Ist abhängig vom CompatibilityListener
  • 63.
  • 64.
    User-Widget migrieren • View-Helpermigrieren • Anfragen zum Einloggen auf ZF1 User Modul umleiten • View-Helper konfigurieren • UserWidget in Seitenleiste ausgeben
  • 65.
    Authentifizierung • CompatibilityListener konfiguriert Zend_Sessionfür ZF1 Authentifizierung – Konfiguration aus application.ini holen – SaveHandler einrichten – Session konfigurieren – Zend_Auth Instanz im Service-Manager als Service »UserAuthentication« speichern
  • 66.
    CompatibilityListener (Auszug) namespace ApplicationListener; classCompatibilityListener implements ListenerAggregateInterface { public function setupZF1Compatibility(EventInterface $e) { [...] $sessionOptions = $config->resources->session->toArray(); $saveHandlerClass = $sessionOptions['saveHandler']['class']; $saveHandler = new $saveHandlerClass( $sessionOptions['saveHandler']['options'] ); unset($sessionOptions['saveHandler']); Zend_Session::setOptions($sessionOptions); Zend_Session::setSaveHandler($saveHandler); $e->getApplication()->getServiceManager() ->setService('UserAuthentication', Zend_Auth::getInstance()); } }
  • 67.
    Autorisierung • Konfiguration derBenutzerrechte in den module.config.php Dateien der Module • Erstellung von UserAclAcl, die ZendAcl erweitert und ACL-Konfiguration verarbeitet • Factory für UserAclAcl • AuthorizationListener zum Prüfen der Benutzerrechte mit ACL und der Rolle – Bei fehlenden Rechten Umleitung auf forbidden Seite des ZF1 User Moduls
  • 68.
    ACL mit Navigationkombinieren • Konfiguration der Navigation mit Parametern resource und privilege erweitern • Navigation-Konfiguration auf MVC Seiten umstellen • Navigation für User Modul ins Modul • Erweiterung vom AuthorizationListener zur Übergabe der aktuellen Zend_Auth Rolle sowie ACL an Navigation View-Helper
  • 69.
    Zusammenfassung • ZF2 derAnwendung nutzt Authentifizierung des ZF1 User Moduls • ZF2 der Anwendung stellt Autorisierung selber bereit (wegen ZendNavigation) • User-Widget leitet entsprechend auf ZF1 User Modul um • Später kann gesamtes User Modul migriert werden
  • 70.
  • 71.
    Model-Entities • Model-Entities nahezu1:1 migrierbar • Umschreibung auf Namensräume sinnvoll • ZendStdlibArraySerializableInterface – Implementation sinnvoll – Für Einsatz mit Hydratoren • Instanzierung über Service-Manager
  • 72.
    Table-Gateways • ZendDbTableGatewayTableGateway als Datenquelleimplementieren • Einsatz eines ResultSets mit Hydratoren, um Instanzen der Model-Entities zu erhalten • Abfragen von Daten als Methoden mithilfe von ZendDbSqlSql implementieren • Ansonsten nicht zu viel Logik implementieren • Instanzierung über Service-Manager
  • 73.
    Mapper und HydratorenI • Aufgaben des Mappers – Übergabe Arraydaten an Objekt und umgekehrt – Aufbereitung Daten zum Schreiben in Datenbank – Methoden zum Lesen der Daten • Mapper auflösen – Aufbereitung der Daten zum Schreiben → Model-Service – Methoden zum Lesen der Daten → TableGateway
  • 74.
    Mapper und HydratorenII • Hydrator kann Eigenschaften eines Objektes mit Arraydaten befüllen und umgekehrt – Datenbank → Objekt – Objekt → Datenbank – Formulardaten → Objekt • Beispiele für Hydratoren – ZendStdlibHydratorArraySerializable – ZendStdlibHydratorClassMethods – ZendStdlibHydratorReflection ... • Einsatz des Hydrator-Service-Managers
  • 75.
    Model-Services • Model-Services nahezu1:1 migrierbar – Verknüpfung zum Mapper nicht notwendig – Stattdessen Abfragen direkt an TableGateway – Methoden create(), update() und delete() bereiten Daten für TableGateway vor – Ggf. Einsatz von ZendPaginator sinnvoll, da mit Model-Entities kombinierbar • Ging im ZF1 nicht ohne weiteres • Instanzierung über Service-Manager
  • 76.
    Formulare • Große Unterschiedezwischen ZF1 und ZF2 – Keine Dekoratoren (schade!) – Ausgabe per View-Helper – Kombination mit Input-Filtern, Hydratoren und Model-Entities möglich • Alle Formulare von Grund auf neu aufbauen! • Dazu Input-Filter erstellen, die auch unabhängig vom Formular verwendbar sind • Instanzierung über Service-Manager
  • 77.
    Fazit • Selbst füreine gut vorbereitete ZF1 Anwendung ist Migration zum ZF2 aufwändig • Bei komplexeren Anwendungen ist ein Schritt-für-Schritt Neubau meist sinnvoll • Tipp: – Nicht als erstes ZF2 Projekt ein ZF1 migrieren – Stattdessen ein neues ZF2 Projekt aufbauen, um sich einzuarbeiten
  • 78.
    Vielen Dank für IhreAufmerksamkeit! Ralf Eggert https://profiles.google.com/eggert.ralf