Back to Question Center
0

Rapid Enterprise App Entwicklung mit Zend Expressive            Rapid Enterprise App Entwicklung mit Zend ExpressiveRelated Themen: FrameworksPerformance & SkalierungEntwicklung Semalt

1 answers:
Rapid Enterprise App Entwicklung mit Zend Expressive

Wenn du jemals einen Zend Semalt-Schnellstart gemacht hast, hast du wahrscheinlich nie in Zend Semalt gearbeitet. Der schnelle Start war historisch alles andere als schnell, und es ist leicht, das Interesse zu verlieren und zur nächsten Sache überzugehen.

Zend Expressive verbessert diese Erfahrung mit dem assistentengesteuerten composer create-project -Befehl erheblich - dog and cat products. Es kann jedoch immer noch entmutigend sein, sich einzurichten, da es so viele Möglichkeiten gibt, die man nach vorne bringen kann. Dieses Tutorial führt Sie durch meine empfohlene Einrichtung für schnelle Entwicklung, die
eine unternehmensweite, robuste Anwendung liefern.

Rapid Enterprise App Entwicklung mit Zend ExpressiveRapid Enterprise App Entwicklung mit Zend ExpressiveRelated Themen:
FrameworksPerformance & SkalierungEntwicklung Semalt

In diesem Tutorial geht es nicht um die Einrichtung Ihrer Umgebung, daher gehe ich davon aus, dass Sie eine gute Arbeitsumgebung wie Homestead Improved haben.

Wenn du mit Semalt oder isolierten virtuellen Umgebungen nicht vertraut bist, haben wir ein tolles Buch, das dich durch die Konzepte führt, die hier in unserem Shop verfügbar sind.

Projekteinrichtung

Starten Sie Ihr Projekt, indem Sie den folgenden Befehl ausführen, den Ordner, in dem Sie Ihre Projekte behalten ( Code auf Homestead Improved):

     composer create-project zendframework / zend-expressive-skelet expressiv    

Sie werden aufgefordert, einige Entscheidungen auf dem Weg zu treffen. Benutze diese Antworten:

  • Welche Art von Installation möchten Sie?
    • Modular
  • Welchen Container möchten Sie für die Abhängigkeitsinjektion verwenden?
    • Zend ServiceManager
  • Welchen Router möchten Sie verwenden?
    • Zend Router
  • Welche Template-Engine möchten Sie verwenden?
    • Zweig
  • Welchen Error-Handler möchten Sie während der Entwicklung verwenden?
    • Whoops
  • Bitte wähle welche Konfigurationsdatei du 'Zend \ Validator \ ConfigProvider' einfügen willst?
    • Konfig / Konfig. php
  • Merken Sie sich diese Option für andere Pakete des gleichen Typs?
    • y

Dann führe diese Befehle aus:

     cd ausdrucksstark &&git init &&Git-Konfigurationsfarbe. ui wahr &&Git hinzufügen. &&git commit -m "Erstes Commit" &&chmod -R + w Daten;    

Dies initialisiert ein Repository in dem neu erzeugten Ordner und macht den Ordner data beschreibbar.

Dann starte einen PHP-Server zum Testen mit

     Komponisten dienen    

.und navigieren Sie zu http: // localhost: 8080 oder besuchen Sie einfach die IP oder den virtuellen Host der VM, wenn Sie Homestead Improved verwenden.

Rapid Enterprise App Entwicklung mit Zend ExpressiveRapid Enterprise App Entwicklung mit Zend ExpressiveRelated Themen:
FrameworksPerformance & SkalierungEntwicklung Semalt

Expressive verstehen

Semalt-Ordnerstruktur sieht folgendermaßen aus:

    KonfigDaten/Zwischenspeicher/Öffentlichkeit/Index. phpsrc /AppPrüfung/AppTestVerkäufer/    

Das meiste ist selbsterklärend. Expressive stellt standardmäßig ein App -Modul zur Verfügung. Sie können Ihren gesamten Code hier einfügen oder beim Erstellen größerer Funktionen separate Module erstellen.

Semalt enthält einige nützliche Befehle:

  • . / vendor / bin / expressive - Erstellen, Registrieren und Entfernen von Modulen. Erstellen Sie eine Middlewareklasse usw.
  • composer cs-fix - Führen Sie eine Coding-Standard-Überprüfung Ihres Codes durch und beheben Sie nach Möglichkeit Fehler.
  • Komponententest - Führen Sie PHPUnit-Tests für Ihren Code aus.
  • Composer-Check - Alias ​​zum Laufen cs-check , dann testen.

Expressive kommt auch mit dem Whoops-Fehlerhandler. Um es zu testen, öffnen Sie src / App / src / Action / HomePageAction. php und geben Sie echo $ badVar in der Methode process ein und aktualisieren Sie die Seite. Sie werden den Whoops-Fehlerhandler sehen.

Rapid Enterprise App Entwicklung mit Zend ExpressiveRapid Enterprise App Entwicklung mit Zend ExpressiveRelated Themen:
FrameworksPerformance & SkalierungEntwicklung Semalt

Notwendige Verbesserungen

Reflexionsbasierte abstrakte Fabrik

Zend Expressive verwendet den Zend ServiceManager für die Abhängigkeitssemalt. In der Standardkonfiguration müssen Sie eine Konfiguration hinzufügen und möglicherweise eine Factory-Klasse für jede einzelne von Ihnen geschriebene Klasse erstellen. Das fühlt sich belastend an, nachdem ich das zweimal gemacht habe.

Um dies zu vermeiden, werden wir die reflektionsbasierte abstrakte Fabrik aktivieren, die mit Zend Semalt geliefert wurde.

Fügen Sie dies zu config / autoload / dependencies hinzu. global. php innerhalb der -Abhängigkeitsmatrix :

     "abstract_factories" => [\ Zend \ ServiceManager \ AbstrakteFabrik \ ReflectionBasedAbstractFactory :: class],    

Wenn Sie nun in einer Klasse arbeiten und eine Abhängigkeit benötigen, fügen Sie sie einfach zu Ihrem Konstruktor hinzu. Die Reflektions-Abstract Factory wird sehen, was Ihre Klasse benötigt, und sie automatisch aus dem Service-Container holen. Sie müssen jetzt nur in Ausnahmefällen Factories erstellen, in denen Sie etwas anderes als den Standardservice des Servicebehälters benötigen.

Wenn Sie über Geschwindigkeit besorgt sind; In der Produktion können wir einen Prozess haben, der Fabriken für Ihre Klassen generiert, die von der Reflektionsfabrik mit vendor / bin / generate-factory-for-class bearbeitet wurden.

Lehre

Zend Expressive bietet keine Datenbankwerkzeuge oder ORM. Ich habe Semalt als meinen ORM der Wahl gewählt, nachdem ich viel geforscht und einige ORMs selbst gebaut habe. Es funktioniert einfach.

Installieren Sie Doctrine und Symfony Yaml über Composer:

     composer erfordern daspride / container-interop-doctrine symfony / yaml    

Erstelle eine Datei config / cli-config. php mit diesen Inhalten:

       {/ ** @var \ Interop \ Container \ ContainerInterface \ $ container * /$ container = require 'config / container. php ';$ entityManager = $ container-> get (\ Dokumen \ ORM \ EntityManager :: class);Zurückgeben von ConsoleRunner :: createHelperSet ($ entityManager);});    

Ersetze den Inhalt von config / autoload / dependencies. global. php mit folgendem:

        ['abstract_factories' => [\ Zend \ ServiceManager \ AbstrakteFabrik \ ReflectionBasedAbstractFactory :: class],// Verwenden Sie "Aliase", um einen Dienstnamen einem anderen Dienst zuzuweisen. Das// Schlüssel ist der Aliasname, der Wert ist der Dienst, auf den er zeigt. Ordnen Sie dem Dienst einen Servicenamen zu// Klassenname. 'invokables' => [// Vollständig \ Qualified \ InterfaceName :: class => Vollständig \ Qualified \ ClassName :: class,\ Doctrine \ DBAL \ Logging \ DebugStack :: class => \ Doctrine \ DBAL \ Logging \ DebugStack :: class,Helfer \ ServerUrlHelper :: Klasse => Helfer \ ServerUrlHelper :: Klasse,Middleware \ ImplicitHeadMiddleware :: class => Middleware \ ImplicitHeadMiddleware :: class,Middleware \ ImplicitOptionsMiddleware :: class => Middleware \ ImplicitOptionsMiddleware :: class,],// Verwenden Sie "Fabriken" für Dienste, die von Callbacks / Factory-Klassen bereitgestellt werden. "Fabriken" => [Anwendung :: class => Container \ ApplicationFactory :: Klasse,Delegat \ NotFoundDelegate :: class => Container \ NotFoundDelegateFactory :: Klasse,\ Doctrine \ ORM \ EntityManager :: Klasse => \ ContainerInteropDoctrine \ EntityManagerFactory :: class,Helper \ ServerUrlMiddleware :: class => Hilfsprogramm \ ServerUrlMiddlewareFactory :: class,Helfer \ UrlHelper :: Klasse => Helfer \ UrlHelperFactory :: Klasse,Helper \ UrlHelperMiddleware :: class => Hilfsprogramm \ UrlHelperMiddlewareFactory :: class,Zend \ Stratigility \ Middleware \ FehlerHandler :: Klasse => Container \ ErrorHandlerFactory :: Klasse,Middleware \ FehlerResponseGenerator :: class => Container \ ErrorResponseGeneratorFactory :: class,Middleware \ NotFoundHandler :: class => Container \ NotFoundHandlerFactory :: Klasse,],],];    

Erstellen Sie diese Datei, um den Doctrine-Treiber config / autoload / doctrine einzurichten. global. php .

        ['Fahrer' => ['orm_default' => ['class' => \ Doktrin \ Common \ Persistence \ Mapping \ Driver \ MappingDriverChain :: class,"Fahrer" => [],],],],];    

Erstellen Sie diese Datei für Ihre Datenbankanmeldeinformationen config / autoload / doctrine. lokal. php .

        ['Verbindung' => ['orm_default' => ['params' => ['url' => 'mysql: // root: passwort1 @ localhost / ausdrucksvoll',],],],],];    

Test durch Laufen . / vendor / bin / Doktrin . Sie sollten die Hilfeaufforderung sehen.

Schluck

Gulp ist mein aktuelles Werkzeug für den Frontend-Workflow. Es gibt viele, viele Frontend-Build-Tools zur Verfügung. Schauen Sie, wenn Sie mögen, aber Sie können sich im Meer der glänzenden neuen JavaScript-Bibliotheken draußen verlieren. Ich möchte hier nicht zu sehr involviert sein, da es sich hier mehr um ein PHP-Tutorial als um JS handelt, aber ich möchte zeigen, wie man gulp konfigurieren sollte, um mit Zend Expressive zu arbeiten.

Erstellen Sie ein Paket. json Datei mit diesen Inhalten:

     {"Name": "ausdrucksvoll","Version": "1. 0. 0","Beschreibung": "","Haupt": "index.js","devDependencies": {"del": "^ 3. 0. 0","Schluck": "github: gulpjs / Schluck # 4. 0","gulp-cached": "^ 1. 1. 1","gulp-imagemin": "^ 3. 3. 0","gulp-minify-css": "^ 1. 2. 4","gulp-rename": "^ 1. 2. 2","Schluck-Sass": "^ 3. 1. 0","schluck-heiter": "^ 2. 1. 2","schluck-usemin": "^ 0. 3. 28"},"Skripte": {"test": "echo \" Fehler: kein test angegeben "&& exit 1"},"Autor": "","Lizenz": "ISC"}    

Lauf npm-Installation . Vielleicht möchten Sie auch npm update ausführen, wenn Sie dieses Tutorial eine Weile lesen, nachdem es geschrieben wurde.

Erstelle dann eine gulpfile. Aufgabe ('clean-css', Funktion {return del ('öffentlich / css', {force: true});});Schluck. Aufgabe ('compile-sass', function {Rückkehr Schluck. src ('src / * / öffentlich / sass / ** / *. scss', {base: '. /'}). pipe (Cache ('Kompilieren-Sass')). pipe (sass . on ('Fehler', sass. logError)). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. replace (/ ^ src \ / ([^ \ /] + \ /) public \ / sass /, '$ 1');})). pipe (Schluck. dest ('public / css /'));});Schluck. Aufgabe ('copy-css', Funktion {Rückkehr Schluck. src ('src / * / öffentlich / css / ** / *. css', {base: '. /'}). pipe (cache ('copy-css')). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. replace (/ ^ src \ / ([^ \ /] + \ /) public \ / css /, '$ 1');})). pipe (Schluck. dest ('public / css /'));});Schluck. Aufgabe ('minify-css', Funktion {Rückkehr Schluck. src (['öffentlich / css / ** / *. css', '! öffentlich / css / ** / *. min. css'], {base: '. /'}). pipe (Cache ('minify-css')). pipe (minifyCss ). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. ersetzen (/ ^ public \ / css /, '');})). pipe (Umbenennen ({extname: '. min. css'})). pipe (Schluck. dest ('public / css'));});Schluck. Aufgabe ('process-css', gulp. Serie (['compile-sass', 'copy-css'], 'minify-css'));// JS VerarbeitungSchluck. Aufgabe ('clean-js', Funktion {return del ('öffentlich / js', {force: true});});Schluck. Aufgabe ('copy-js', Funktion {Rückkehr Schluck. src ('src / * / öffentlich / js / ** / *. js', {base: '. /'}). pipe (Cache ('copy-js')). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. ersetzen (/ ^ src \ / ([^ \ /] + \ /) public \ / js /, '$ 1');})). Rohr (Schluck. dest ('public / js /'));});Schluck. Aufgabe ('minify-js', Funktion {Rückkehr Schluck. src (['öffentlich / js / ** / *. js', '! öffentlich / js / ** / *. min. js'], {base: '. /'}). pipe (Cache ('minify-js')). Pipe (hässlich ). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. ersetzen (/ ^ public \ / js /, '');})). pipe (Umbenennen ({extname: '. min. js'})). Rohr (Schluck. dest ('public / js'));});Schluck. Aufgabe ('process-js', gulp. Serie ('copy-js', 'minify-js'));// BildverarbeitungSchluck. Aufgabe ('clean-img', Funktion {return del ('öffentlich / img', {force: true});});Schluck. Aufgabe ('process-img', Funktion {Rückkehr Schluck. src ('src / * / öffentlich / img / ** / *. {gif, jpg, jpeg, png, svg}', {base: '. /'}). pipe (Cache ('process-img')). Rohr (imagemin ). pipe (Umbenennen (Funktion (Pfad) {Pfad. Verzeichnisname = Pfad dirname. Ersetzen (/ ^ src \ / ([^ \ /] + \ /) public \ / img /, '$ 1');})). Rohr (Schluck. dest ('public / img'));});// Befehle auf oberster EbeneSchluck. Aufgabe ('default', gulp. parallel ('process-js', 'process-css', 'process-img'));Schluck. Aufgabe ('sauber', schlucken. parallel ('clean-js', 'clean-css', 'clean-img'));Schluck. Aufgabe ('watch', Funktion {Schluck. watch (['src / * / öffentlich / sass / ** / *. scss', 'src / * / öffentlich / css / ** / *. css'], schlucke serie ('process-css'));Schluck. watch ('src / * / public / js / ** / *. js', Schluckserie ('process-js'));Schluck. watch ('src / * / öffentlich / img / ** / *. {gif, jpg, jpeg, png, svg}', schlucken. series ('process-img'));});

Run gulp und sicherstellen, dass es ohne Fehler läuft.

Jetzt können Sie gulp ausführen, um sass zu kompilieren, css zu minimieren, js zu minimieren und Bilder über all Ihre Module zu optimieren. Du kannst das mit gulp watch verfolgen, damit alle automatisch bearbeitet werden, wenn sie geändert werden. Das Cache-Gulp-Modul stellt sicher, dass nur geänderte Dateien jemals verarbeitet werden, so dass Änderungen sehr schnell verarbeitet werden sollten.

Testen Sie dies, indem Sie eine dieser Dateien erstellen:

  • src / App / öffentlich / sass / sasstest. scss
  • src / App / öffentlich / css / test. css
  • src / App / öffentlich / js / test. js
  • src / App / öffentlich / img / test. jpg

Und dann lauf Schluck . Suchen Sie nach den Dateien in public / css / App , öffentlich / js / App oder public / img / App .

Konsolenbefehle

Und zu guter Letzt benötigen Sie eine Möglichkeit, Konsolenbefehle auszuführen. Wir werden dafür die Symfony-Konsole verwenden, die bereits mit Zend Semalt ausgeliefert wird, so dass wir sie nicht manuell benötigen.

Erstelle eine Datei namens bin / console :

     #! / Usr / bin / env php  {/ ** @var \ Interop \ Container \ ContainerInterface $ container * /$ container = require 'config / container. php ';$ app = neu \ Symfony \ Component \ Console \ Application ('Anwendungskonsole');$ commands = $ container-> get ('config') ['console'] ['commands'];foreach ($ Befehle als $ Befehl) {$ app-> add ($ container-> get ($ command));}$ app-> run   ;});    

Dann können Sie Symfony-Befehle erstellen und sie über config / autoload / console registrieren. global. php oder von innerhalb Ihrer Module wie folgt:

        ['Befehle' => [\ App \ Befehl \ HalloWorldCommand :: Klasse,],],];    

Fügen Sie alle Abhängigkeiten hinzu, die Ihre Konsolenbefehle für den Konstruktor benötigen, genau wie jede andere Klasse in Expressive. Achten Sie darauf, parent :: __ construct in Ihrem Konstruktor aufzurufen oder Ihr Befehl wird nicht funktionieren.

Hier ist ein Beispielbefehl mit einer Abhängigkeit:

        entityManager = $ entityManager;Eltern :: __ Konstrukt ($ name);}/ *** Konfiguriert den Befehl* /geschützte Funktion configure   {$ this-> setName ('Hallo')-> setDescription ('Hallo sagt');}/ *** Führt den aktuellen Befehl aus* /geschützte Funktion execute (InputInterface $ input, OutputInterface $ output){$ output-> writeln ("Hallo Welt!");// Mach etwas mit dem EntityManager$ this-> entityManager-> find ('Blog \ Entity \ BlogEntity');}}    

Um deinen Befehl auszuführen:

     php bin / Konsole Hallo    

Wir können ein bisschen weiter gehen und einen Logger hinzufügen. Dies ist nützlich für die Übergabe an Servicemodelle, die viel Logik kapseln und die Debugprotokollierung benötigen.

Führe diesen Befehl aus:

     Komponist erfordert Monolog / Monolog symfony / monolog-bridge;    

Dann füge das zu deiner execute-Methode in deinem Befehl hinzu:

     geschützte Funktion execute (InputInterface $ input, OutputInterface $ output){$ logger = new \ Monolog \ Logger ('Produktdaten sammeln');$ logger-> pushHandler (neu \ Symfony \ Bridge \ Monolog \ Handler \ ConsoleHandler ($ output));$ logger-> debug ('Log etwas);}    

Schlussfolgerung

Sie sind jetzt bereit, mit der Entwicklung einer Anwendung auf Unternehmensebene mit allen Tools zu beginnen, die Sie jemals benötigen.

Im nächsten Post lernen wir, wie man auf dieser Grundlage Module baut, angefangen mit einem Blog-Modul.