Moderne Art, lib-Dateien neu zu schreiben

21

Das Problem ist allgemein bekannt: libKlassen werden ausschließlich über den Autoloader geladen und können nur wie folgt geändert werden:

  • Kopieren Sie sie vollständig in einen CodePool, der vor lib geprüft wurde.
  • Installieren des PSR-0-Autoloaders , Angeben einer Autoload-Klassenzuordnung und anschließendes Kopieren der Datei vollständig in diese Ordnerstruktur. [meine aktuelle Lösung]

Ich bin in einer schwierigen Situation, weil ich möglicherweise viele dieser Dateien berühren möchte - aber aus Gründen meiner Vernunft und Stabilität / Aktualisierbarkeit des Speichers möchte ich nicht ganze Bibliotheksklassen kopieren.

Jetzt gibt es natürlich mögliche Lösungen für dieses Problem, aber alle haben ihre eigenen Probleme:

  • Gehen Sie auf die AOP- Route und verwenden Sie eine PHP-basierte Bibliothek wie Go! AOP : Zuletzt habe ich überprüft, dass Magento-Klassen vom Composer-Autoloader geladen werden müssen, nicht nur eine. Flyingmana hat einige Arbeiten in diesem Bereich durchgeführt, aber es ist definitiv nicht für den Einsatz in der Produktion bereit und meine Bedürfnisse sind unmittelbarer. Ich möchte auch als Erweiterung versenden, und das würde mehr Komponisten-Setup erfordern.
  • Gehen Sie auf die AOP-Route und verwenden Sie eine native PHP-Erweiterung : Wahrscheinlich die derzeit günstigste, aber es müsste eine separate Erweiterung installiert werden, ganz zu schweigen davon, dass dies mit HHVM nicht funktionieren würde.
  • Verwenden Sie PHPs Classkit und / oder Runkit : Es ist eine weitere native PHP-Erweiterung, die das gleiche Problem wie oben hat.
  • Korrigieren Sie Aufrufseiten , um meine eigene namespaced ( \Danslo\Varien_X) -Version zu verwenden, und erweitern Sie sie dann von der ursprünglichen ( \Varien_X): Es gibt einfach viel zu viele Aufrufseiten, um sie zu korrigieren, und dies würde eine alberne Menge von Neuschreibungen erfordern. Keine Option.
  • Roll my own: Es sollte möglich sein:

    1. Schreibe meinen eigenen Autoloader.
    2. Kopieren Sie die ursprüngliche Klasse in einen separaten Ordner ( {root_dir}/var/tmp) und wickeln Sie sie ein namespace \Magento { < original contents > }.
    3. Fügen Sie diese Datei hinzu.
    4. Meine geänderte Klasse einschließen OriginalClass extends Magento\OriginalClass {}

Der Nachteil liegt auf der Hand: Dynamische Codegenerierung, Regex, ein wenig Overhead beim Laden umgeschriebener Klassen. Aber ich bin mir fast sicher, dass es zu diesem Zeitpunkt besser wäre, ~ 5000 Zeilen Code zu kopieren, wenn ich nur ~ 100 Zeilen berühren / hinzufügen möchte.

Ich weiß, dass ich viel frage, aber gibt es etwas Modernes und relativ Sauberes, das zur Lösung dieses Problems beiträgt?

Daniel Sloof
quelle
1
Haben Sie Alans Observer-Lösung schon gefunden? stackoverflow.com/a/4636662/158325
B00MER

Antworten:

9

Beschlossen, Go! AOP-Framework in Magento.

Siehe Danslo_Aop auf Github.

Daniel Sloof
quelle
2

Gehen Sie auf die AOP-Route und verwenden Sie eine PHP-basierte Bibliothek wie Go! AOP: Zuletzt habe ich überprüft, dass Magento-Klassen vom Composer-Autoloader geladen werden müssen, nicht nur eine. Flyingmana hat einige Arbeiten in diesem Bereich durchgeführt, aber es ist definitiv nicht für den Einsatz in der Produktion bereit und meine Bedürfnisse sind unmittelbarer. Ich möchte auch als Erweiterung versenden, und das würde mehr Komponisten-Setup erfordern.

Ich möchte hinzufügen, dass Go! AOP Framework kann ohne Composer funktionieren, ich kann bei der Konfiguration helfen (erstelle dafür ein Problem bei Github). Composer wird nur für die transparente Integration in moderne Anwendungen benötigt.

Ersetzen Sie einfach ein include $filenameoder require $filenamein Ihrem Bootstrap durchinclude FilterInjectorTransformer::rewrite($filename) und konfigurieren Sie einen Autoloader für Go! AOP selbst.

Lisachenko
quelle
1
Wow nett. Ich werde das auf jeden Fall versuchen.
Daniel Sloof
0

Fahren Sie mit dem Autoloader-Ansatz fort. Benenne / all / classes in lib mit einem Präfix um:

find lib -name '*.php' -exec sed -e 's,^class ,class Oldlib_,' {} +

Führen Sie den folgenden "Override Fixer" aus, wenn Sie eine Datei zu mylib hinzufügen:

find lib -name '*.php' -print | while read FILE
do
    classname=$(echo ${FILE}|sed -e 's,^lib/,,' -e 's,\.php$,,' -e 's,/,_,g')
    if [ ! -f mylib/${FILE#lib/} ]; then
        # ensure is_a works by providing a stub with correct classname
        echo "class ${classname} extends Oldlib_${classname} {}" > mylib/${classname}.php
    elif [ -f mylib/${classname}.php ]; then
        # we have a new override, but the old file still exists
        rm mylib/${classname}.php
    fi
done

Bringen Sie dem Autoloader bei, zurückzukehren mylib/${classname}.php wenn er vorhanden ist, und mylib/full/path/to/class.phpwenn er es nicht mylib/full/path/to/class.phptut und tut.

Setzen Sie Ihre Außerkraftsetzungen ein mylib/full/path/to/class.phpGeben und erweitern Sie die Oldlib_-Version.

Upgrades setzen einfach das Präfix in lib / upgrade zurück, wenden das Präfix erneut an und führen den Override-Fixer erneut aus. Was übrig bleibt, sind Sachen, die eingezogen wurden lib/und zuvor überschrieben wurden, aber das hat nichts mit dem Problem zu tun. Ihr Problem kann die Anzahl der Dateien in der Mylib / -Verzeichnis sein, aber ich vertraue darauf, dass Sie das lösen können :).

Melvyn
quelle
Dieser Ansatz birgt viele Risiken und Probleme, die insbesondere bei Upgrades zu beachten sind. Es verstößt auch gegen die "Don't Touch The Core" -Regel. Darüber hinaus ist es keine praktikable Option für Erweiterungsentwickler.
Beeplogic
Bei allem Respekt ~ obwohl Ihre Lösung funktioniert ... kann sie nicht als a modernMethode zum Neuschreiben von lib-Dateien angesehen werden. Imperative Programmierung ist Old School;)
Eddie B
0

Sie können auch einen benutzerdefinierten Stream definieren und diesen über dem Autoload-Pfad hinzufügen. Es funktioniert mit jedem Autoloader und erfordert nur minimale Anpassungen. Siehe Beispiel

KAndy
quelle