YIMP - Systemsteuerung für Yii 2 auf Bootstrap 4

Ich bin sicher, dass viele Entwickler, die Frameworks vorgefertigten CMS bevorzugen, eine Lösung auf Bootstrap oder seinen Analoga auf Lager haben, mit der Administrationsschnittstellen und andere Back-Office-Schnittstellen erstellt werden. Und ich habe es. Es funktioniert seit vielen Jahren erfolgreich, ist aber hoffnungslos veraltet. Es ist Zeit umzuschreiben.


Während der Arbeit an der neuen Version habe ich versucht, alle meine Erfahrungen zu diesem Thema zusammenzufassen. Als Ergebnis habe ich YIMP erhalten - ein Fahrrad , für das ich mich nicht schäme, es zu teilen: GitHub , LiveDemo , API-Dokumentation .


YIMP ist sehr einfach. Aber hinter dieser Einfachheit steckt ein langer Gedanke, den ich auch teilen möchte. Dieser Artikel ist also keine Anweisung. Hier sprechen wir natürlich über Architektur, Abhängigkeitsmanagement, das MVC-Paradigma und die Benutzeroberfläche.


YIMP ist also ein Dashboard. Dies ist kein vorgefertigtes Admin-Panel, kein CMS oder gar CMF. Der Repräsentationscode muss unabhängig geschrieben werden oder Gii verwenden (Vorlagen sind beigefügt). YIMP bietet ein Layout, das definiert, wo sich die Steuerelemente befinden sollen, sowie die Schnittstelle, über die die Anwendung Daten an das Layout überträgt. So sieht es auf Desktops aus:



Layout adaptiv. Wenn der Bildschirm kleiner wird, verschwinden die Elemente oder bewegen sich unter den Schaltflächen in der Navigationsleiste. Infolgedessen sieht dieselbe Seite des Telefons folgendermaßen aus:


Lass es besser unter dem Spoiler sein

Was sehen wir im Layout? Der Anwendungstitel, Breadcrumbs, drei Menüs (links, rechts und oben), Widgets in den Seitenleisten, Seitentitel. In meiner Praxis reichten diese Elemente aus, um Schnittstellen zu entwickeln - von Administrationsseiten von Zielseiten bis hin zu Unternehmensinformationssystemen. Ich habe versucht, sie so anzuordnen, dass der Raum so effizient wie möglich genutzt wird. Was sagst du


Das Markup wird in reinem Bootstrap ohne Erweiterungen und Anpassungen geschrieben. Wo immer möglich, wurden Klassen von Bootstrap verwendet. Wenn Sie sich also für die Anpassung entscheiden, sollte es keine Probleme geben.


Wie gesagt, YIMP enthält eine Schnittstelle, über die die Anwendung Daten an das Layout überträgt. Mal sehen, wie das passiert. Öffne die Haube!


Layout


Ich bin der Meinung, dass der Entwickler die volle Kontrolle über das Layout haben sollte. Daher empfehle ich bei der Installation von YIMP, seinen Code in seine Anwendung zu kopieren. Meiner Meinung nach ist dies viel besser, als ein Layout im Paket zu belassen und eine Reihe von Einstellungen dafür zu blockieren. Sehen wir uns den Layout-Code an:


77 Codezeilen. Es ist nicht notwendig, sich damit zu beschäftigen!
<?php use dmitrybtn\yimp\widgets\Alert; use dmitrybtn\yimp\Yimp; use yii\bootstrap4\Html; $yimp = new Yimp(); $yimp->register($this); /** @var string $content Content came from view */ ?> <?php $this->beginPage() ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="<?= Yii::$app->charset ?>"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <?php echo Html::csrfMetaTags() ?> <title><?php echo Html::encode($yimp->nav->getTitle()) ?></title> <?php $this->head() ?> </head> <body> <?php $this->beginBody() ?> <?php echo $yimp->navbar() ?> <?php echo $yimp->beginSidebars() ?> <?php echo $yimp->beginLeftSidebar() ?> <?php echo $yimp->beginLeftSidebarMenu() ?> <?php echo $yimp->menuLeft([ 'options' => ['class' => 'nav-pills flex-column border rounded py-2'] ]) ?> <?php echo $yimp->endLeftSidebarMenu() ?> <?php if (isset($this->blocks[$yimp::SIDEBAR_LEFT])): ?> <?php echo $this->blocks[$yimp::SIDEBAR_LEFT] ?> <?php endif ?> <?php echo $yimp->endLeftSidebar() ?> <?php echo $yimp->beginRightSidebar() ?> <?php echo $yimp->beginRightSidebarMenu() ?> <?php echo $yimp->menuRight([ 'options' => ['class' => 'nav-pills flex-column border rounded py-2'] ]) ?> <?php echo $yimp->endRightSidebarMenu() ?> <?php if (isset($this->blocks[$yimp::SIDEBAR_RIGHT])): ?> <?php echo $this->blocks[$yimp::SIDEBAR_RIGHT] ?> <?php endif ?> <?php echo $yimp->endRightSidebar() ?> <?php echo $yimp->endSidebars() ?> <?php echo $yimp->beginContent() ?> <?php echo $yimp->headerDesktop() ?> <?php echo Alert::widget() ?> <?php echo $content ?> <?php echo $yimp->endContent() ?> <?php if (isset($this->blocks[$yimp::FOOTER])): ?> <?php echo $this->blocks[$yimp::FOOTER] ?> <?php endif ?> <?php $this->endBody() ?> </body> </html> <?php $this->endPage() ?> 

Wie Sie sehen können, sind alle YIMP-Markups in Methoden eingeschlossen. Die meisten dieser Methoden drucken einfach die Zeilen, die aus diesem Array stammen . Ja, das KISS- Prinzip ist unser Alles.


Bitte beachten Sie, dass im Layout Blöcke verwendet werden. Sie werden benötigt, um in Ansichten definierte Widgets anzuzeigen (so werden Formularsteuerelemente gerendert). Wenn das Widget auf allen Seiten hängen soll, ist es besser, es direkt im Layout zu bestimmen.


Der Hauptbereich und die Widgets werden also in den Ansichten definiert. Und wo sind die Überschriften, Menüs und Semmelbrösel festgelegt? Meiner Meinung nach sind sie am besten in Controllern definiert. Dies ist ein wichtiger Punkt, da eine solche Entscheidung dem MVC-Paradigma widerspricht. Schauen wir uns dieses Problem genauer an.


Controller


Lassen Sie also einen ProfileController , der Informationen zum Profil des aktuellen Benutzers anzeigen und das Kennwort ändern kann. Logischerweise wird die profile/view "Mein Profil" genannt. Es ist auch logisch, dass im Hauptmenü der Eintrag "Mein Profil" angezeigt wird. Schließlich sollte "Mein Profil" in Breadcrumbs stehen: "Home / Mein Profil / Passwort ändern". Ich denke, der Wunsch, eine Konstante mit den Worten "Mein Profil" zu definieren, ist durchaus berechtigt. Sie können dies in der Ansicht nicht tun. Die Auswahl einer separaten Ebene für Überschriften ist umständlich. Aus diesem Grund kam ich zu den Controllern.


Der nächste Schritt war die Entscheidung, nicht nur Aktionsheader in den Controllern zu definieren, sondern auch Brotkrumen und Menüs. Und tun Sie es, damit YIMP sie lesen kann. Und hier brauchen wir ein Beispiel. Schauen wir uns eine mögliche Implementierung der ProfileController Klasse an.


52 Zeilen einfacher Code. Besser genau hinschauen!
 class ProfileController extends \yii\web\Controller { public $nav; public function init() { parent::init(); $this->nav = new \dmitrybtn\yimp\Navigator; } public static function titleView() { return ' '; } public static function titlePassword() { return ' '; } public static function crumbsToView() { return [ ['label' => static::titleView(), 'url' => ['/profile/view']] ]; } public function actionView() { $this->nav->title = static::titleView(); $this->nav->menuRight = [ ['label' => ''], ['label' => static::titlePassword(), ['password']], ]; ... return $this->render('view'); } public function actionPassword() { $this->nav->title = static::titlePassword(); $this->nav->crumbs = static::crumbsToView(); ... return $this->render('password'); } } 

Header und Breadcrumbs werden mit statischen Methoden definiert, dh sie können überall verwendet werden. Zum Beispiel können Sie im Hauptmenü der Anwendung schreiben:


 ['label' => ProfileController::titleView(), 'url' => ['/profile/view']], 

Warum genau die Methoden? Denn morgen werden Sie anstelle der Wörter "Mein Profil" aufgefordert, das Login des aktuellen Benutzers anzuzeigen.


Mit Semmelbröseln das gleiche. Angenommen, unser Benutzer hat eine Liste von Bildern, für die ImageController verantwortlich ist. Dann können Sie in die Aktion image/create schreiben:


  $this->nav->crumbs = ProfileController::crumbsToView(), 

und Brotkrumen wie "Startseite / Mein Profil / Bild hinzufügen" erhalten. Übrigens, da die Aktion " image/create " als "Bild hinzufügen" bezeichnet wird, muss das Aktionsmenü " profile/view korrigiert werden:


  $this->nav->menuRight = [ ['label' => ''], ['label' => static::titlePassword(), ['password']], ['label' => ImageController::titleCreate(), 'url' => ['/image/create']] ]; 

Ich finde die Idee verständlich. Meiner Meinung nach ist dies eine einfache und effektive Lösung, für die Sie sich vom MVC-Paradigma entfernen können. Ja, der Controller-Code wird immer größer, aber es gibt einen Platz im Controller - wir schreiben dort keine Geschäftslogik, oder? Und ja, ich wäre sehr interessiert, Ihre Meinung zu diesem Thema zu erfahren.


Wir gehen weiter. Wie Sie vielleicht vermutet haben, wird die als \dmitrybtn\yimp\Navigator definierte Eigenschaft nav verwendet, um Header, Menüs und Breadcrumbs vom Controller in das Layout zu übertragen. Und dies ist eine weitere Funktion von YIMP.



Wie kommen die Einstellungen in das Layout? Sehr einfach. Während der Initialisierung prüft YIMP die nav Eigenschaft des aktuellen Controllers. Wenn diese Eigenschaft lesbar ist und ein Navigator ist ( instanceof \dmitrybtn\yimp\Navigator ), werden die entsprechenden Informationen angezeigt. Der Navigator enthält Eigenschaften, die Layoutelementen entsprechen, von denen eine vollständige Liste in der API-Dokumentation leichter zu sehen ist.


In der Anwendung wird empfohlen, einen eigenen Navigator zu erstellen und darin Menüs zu definieren, die nicht von der aktuellen Aktion abhängen (oben und links). Danach müssen Sie in allen Controllern die nav Eigenschaft erstellen und als Navigator definieren (Sie können Ihre Hände verwenden, Sie können erben oder Sie können Merkmale festlegen). Bei Bedarf können Sie mehrere Navigatoren definieren.


Dieser Ansatz beseitigt die direkte Beziehung zwischen YIMP und dem Controller. Alle Interaktionen werden über ein Objekt ausgeführt, dessen Implementierung vom Entwickler gesteuert wird. Das heißt, dies ist das gleiche Prinzip der Abhängigkeitsinversion von SOLID oder Low Coupling von GRASP .


Es wäre ideologisch korrekt, Schnittstellen sowohl für den Controller als auch für den Navigator zu verwenden. Aber hier habe ich beschlossen, den einfachsten Weg zu gehen und das System nicht zu überladen. Am Ende spricht DIP nicht über Schnittstellen, sondern über Abstraktionen. In diesem Fall ist Abstraktion eine Vereinbarung über das Vorhandensein eines bestimmten Eigenschaftstyps in einer bestimmten Klasse. Was denkst du?


Das Fehlen einer direkten Beziehung zwischen YIMP und dem Controller wird wichtig, wenn Module im System angezeigt werden, die nichts über YIMP wissen. Oder umgekehrt - unter YIMP geschriebene Module werden in einem System installiert, das YIMP nicht verwendet.


Im ersten Fall sieht YIMP keine Navigationseigenschaften im Controller. Es wird kein Fehler angezeigt, aber Ihre Menüs verschwinden vom Bildschirm und die Aktions-ID wird als Titel verwendet. Wie man ist Sehr einfach: Wenn YIMP den Navigator nicht vom Controller übernehmen kann, wird er mithilfe des Alias yimp-nav über den DI-Container yimp-nav . Mit diesem Alias ​​können Sie Ihren eigenen Standardnavigator registrieren, indem Sie beispielsweise in den Anwendungseinstellungen Folgendes angeben:


  'container' => [ 'definitions' => [ 'yimp-nav' => [ 'class' => '\your\own\Navigator', ] ] ], 

Im zweiten Fall ist der Navigator in der Steuerung, aber es gibt niemanden, der ihn lesen kann. In diesem Fall wird empfohlen, einen Wrapper für die Ansichten im Modul zu schreiben, der den Navigator vom aktuellen Controller an das in Yii akzeptierte Format anpasst. Das heißt, zeigen Sie <h1> im Hauptbereich an, <title> und Breadcrumbs durchlaufen die Parameter Yii::$app->view und zeigen das rechte Menü in Form von Schaltflächen an.


Fazit


YIMP wird jetzt ohne Version veröffentlicht. Ich sehe keinen Grund, die Vorabversion zu veröffentlichen - dafür ist alles zu einfach. Ich denke, es ist besser, ein paar Wochen an einem realen Projekt zu testen und sofort zu Version 1.0.0 zu wechseln. Kritik, Kommentare und Hilfe zu GitHub sind daher sehr willkommen.


Und ich absolviere ein Modul, das die Zugriffskontrolle implementiert. Wie man fertig wird - ich werde schreiben.


Wie Sie sehen, gibt es hier nichts Kompliziertes. Ich bin sicher, dass viele von Ihnen etwas Ähnliches auf Lager haben. Und ich wäre sehr interessiert zu wissen, wie Sie die Benutzeroberflächenaufgabe in Ihrem Administrationsbereich lösen.


Danke allen!

Source: https://habr.com/ru/post/de466505/


All Articles