Manera moderna de reescribir archivos lib

21

El problema es bien conocido: las libclases se cargan exclusivamente a través del autocargador, y no podemos cambiarlas más que:

  • Copiándolos por completo a un codePool que se verifica antes que lib.
  • Instalando el cargador automático PSR-0 , especificando un mapa de clase de carga automática, y luego copiando el archivo completamente en esa estructura de carpetas. [mi solución actual]

Estoy en una situación difícil porque quiero tocar potencialmente muchos de estos archivos, pero por el bien de mi cordura y estabilidad / capacidad de actualización de la tienda no quiero copiar clases de biblioteca completas.

Ahora, obviamente, hay posibles soluciones a este problema, pero todas vienen con su propio conjunto de problemas:

  • Siga la ruta AOP y use una biblioteca basada en PHP como Go! AOP : la última vez que verifiqué esto requerirá que las clases de Magento sean cargadas por el autocargador del compositor, no solo una disponible. Flyingmana ha realizado un trabajo en esta área, pero definitivamente no está listo para el uso de producción y mis necesidades son más inmediatas. También quiero enviar como una extensión, y eso requeriría más configuración del compositor.
  • Vaya a la ruta AOP y use una extensión PHP nativa : probablemente la más favorable en este punto, pero requeriría instalar una extensión separada, sin mencionar que no funcionaría con HHVM.
  • Uso de PHP classkit y / o runkit : Es otra extensión nativa de PHP por lo que tiene el mismo problema que el anterior.
  • Revise los sitios de llamadas para usar mi propia \Danslo\Varien_Xversión del espacio de nombres ( ), luego extienda desde el original ( \Varien_X): hay demasiados sitios de llamadas para parchar y requeriría una cantidad tonta de reescrituras. No es una opción.
  • Roll my own: Debería ser posible:

    1. Escribe mi propio cargador automático.
    2. Copie la clase original en una carpeta separada ( {root_dir}/var/tmp), envuélvala namespace \Magento { < original contents > }.
    3. Incluye ese archivo.
    4. Incluir mi clase modificada OriginalClass extends Magento\OriginalClass {}

La desventaja de esto es obvia: generación dinámica de código, expresiones regulares, un poco de sobrecarga para cargar clases reescritas. Pero estoy casi seguro de que en este punto sería mejor copiar ~ 5000 líneas de código cuando solo quiero tocar / agregar ~ 100 líneas.

Sé que estoy preguntando mucho, pero ¿hay algo moderno y relativamente limpio que ayude a resolver este problema?

Daniel Sloof
fuente
1
¿Ya ha encontrado la solución de observador de Alans? stackoverflow.com/a/4636662/158325
B00MER

Respuestas:

9

Decidió implementar Go! Marco de AOP en Magento.

Ver Danslo_Aop en github.

Daniel Sloof
fuente
2

Siga la ruta AOP y use una biblioteca basada en PHP como Go! AOP: la última vez que verifiqué esto requerirá que las clases de Magento sean cargadas por el autocargador del compositor, no solo una disponible. Flyingmana ha realizado un trabajo en esta área, pero definitivamente no está listo para el uso de producción y mis necesidades son más inmediatas. También quiero enviar como una extensión, y eso requeriría más configuración del compositor.

Quiero agregar que Go! El marco de trabajo de AOP puede funcionar sin compositor, puedo ayudar con la configuración (solo crea un problema en github para eso). Composer solo se necesita para una integración transparente con aplicaciones modernas.

Simplemente reemplace uno include $filenameo require $filenameen su programa de arranque con include FilterInjectorTransformer::rewrite($filename)y configure un cargador automático para Go! AOP en sí.

lisachenko
fuente
1
Vaya! Bien. Definitivamente probaré esto.
Daniel Sloof
0

Ir con el enfoque de autocargador. Cambie el nombre de / all / classes en lib con un prefijo:

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

Ejecute el siguiente "arreglador de anulación" cada vez que agregue un archivo a mylib:

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

Enseñe al autocargador a regresar mylib/${classname}.phpsi existe y mylib/full/path/to/class.phpsi no existe y si existe mylib/full/path/to/class.php.

Ponga sus anulaciones mylib/full/path/to/class.phpy extienda la versión Oldlib_.

Las actualizaciones simplemente retrotraen el prefijo en lib / actualícelo, vuelva a aplicar el prefijo y vuelva a ejecutar el fijador de anulación. Lo que queda son cosas que se trasladaron lib/y fueron anuladas anteriormente, pero eso no está relacionado con el problema. Su problema puede ser la cantidad de archivos del directorio mylib /, pero confío en que pueda resolver eso :).

Melvyn
fuente
Este enfoque presenta muchos riesgos y cosas que mantener especialmente en lo que respecta a las actualizaciones. También rompe la regla de "no tocar el núcleo". Además, no es una opción viable para los desarrolladores de extensiones.
beeplogic
Con el debido respeto ~ aunque su solución funciona ... no puede considerarse una a modernforma de reescribir archivos lib. La programación imperativa es de la vieja escuela;)
Eddie B
0

También puede definir Stream personalizado y agregarlo en la parte superior de la ruta de carga automática. Funciona con cualquier cargador automático y requiere una adopción mínima. Ver ejemplo

Kandy
fuente