Estrategia para el desarrollo de espacios de nombres y versiones no-espacio de nombres de mismo código PHP

StackOverflow https://stackoverflow.com/questions/1836387

Pregunta

Estoy manteniendo librería escrita para PHP 5.2 y me gustaría crear la versión 5.3 de PHP-espacio de nombres de la misma. Sin embargo, también me guardo versión no namespaced al día hasta que PHP 5.3 llega a ser tan viejo, que incluso Debian barcos estables ella;)

Tengo código en lugar limpio, cerca de 80 clases siguientes Project_Directory_Filename esquema de nombres (que cambiaría a \Project\Directory\Filename por supuesto) y sólo unas pocas funciones y constantes (también con el prefijo nombre del proyecto).

La pregunta es: ¿cuál es la mejor manera de desarrollar versiones de espacios de nombres y no de espacios de nombres en paralelo

?
  • ¿Debo crear tenedor en el repositorio y mantener la fusión de los cambios entre las ramas? ¿Hay casos donde el código de barra invertida-rociada se vuelve difícil de combinar?

  • ¿Debo escribir script que convierte la versión 5.2 a 5.3 o viceversa? ¿Debo usar tokenizer PHP? sed? C preprocesador?

  • ¿Hay una mejor manera de utilizar los espacios de nombres cuando sea necesario y mantener la compatibilidad hacia atrás con PHP mayor?


Actualización: decidió en contra de uso de espacios de nombres, después de todo

.
¿Fue útil?

Solución

No creo que el procesamiento previo del código 5.3 esto es una gran idea. Si el código es funcionalmente idéntica tanto en PHP 5.2 y 5.3, con la excepción de la utilización de espacios de nombres, en lugar de prefijos subrayado separados por espacios de nombres, por qué su uso en todo? En ese caso, me suena como que desea utilizar espacios de nombres, por el bien de la utilización de espacios de nombres ..

Creo que usted encontrará que a medida que migra a los espacios de nombres, que comenzará a 'pensar un poco diferente' sobre la organización de su código.

Por esta razón, estoy totalmente de acuerdo con su primera solución. Crear un tenedor y hacer backports de características y correcciones de errores.

Buena suerte!

Otros consejos

Esta es una continuación de mi respuesta anterior :

El código de simulación espacio de nombres de bastante estable. Ya puedo conseguir que funcione Symfony2 (todavía algunos problemas, pero en el fondo). Aunque todavía hay algunas cosas que faltan como espacio de nombres resolución variable para todos los casos, aparte de new $class.

Ahora me escribió un script que se repetirá de forma recursiva a través de un directorio y todos los archivos de proceso: http://github.com/nikic/prephp/blob/master/prephp/namespacePortR.php


Instrucciones de uso

Requisitos para su código para trabajar

Sus nombres de las clases no deben contener el carácter _. Si lo hacen, nombres de las clases podrían obtener ambigua en la conversión.

El código no debe redeclare las funciones o constantes globales dentro de un espacio de nombres. De este modo se garantiza que todo el código puede ser resuelto en tiempo de compilación.

Básicamente estas son las únicas restricciones a su código. Aunque debo señalar que en una configuración por defecto del namespacePortR no resolverá cosas como $className = 'Some\\NS\\Class'; new $className, ya que sería necesario insertar código adicional. Es mejor que este está parcheado hasta más tarde (ya sea manualmente o utilizando un sistema de aplicación de parches automatizada.)

Configuración

Como ya hemos hecho la suposición de que ninguna función global o constante es redeclarada en un espacio de nombres debe establecer la constante en la assumeGlobal clase "http://github.com/nikic/prephp/blob/master/ prephp / oyentes / namespaces.php" rel = "nofollow noreferrer"> espacio de nombres oyente . En el mismo archivo establecer la constante SEPARATOR a _.

En el namespacePortR cambiar el bloque de configuración para satisfacer sus necesidades.


PS: La secuencia de comandos puede proporcionar una opción ?skip=int. Esto le dice a saltar los primeros archivos int. No lo necesita, si ha configurado el modo de anulación para inteligente.

Esto es lo que he encontrado:

Hacer esto con expresiones regulares es una pesadilla. Usted puede obtener la mayoría de los que se haga con sólo unos simples expresiones, pero luego el borde casos son un asesino. He terminado con el lío horrible, frágil que apenas se trabaja con una base de código.

Es factible con una función de tokenizer y simple analizador descendente recursivo que sólo maneja simplifica subconjunto del lenguaje.

he terminado con un diseño bastante feo (analizador y el transformador en uno - en su mayoría sólo cambiar o fichas re-emisor de luz), porque parecía demasiado trabajo para construir el árbol de sintaxis útil con espacios en blanco mantenido (quería que resulta ser de código legible).

quería probar phc para esto, pero no podía convencer a su configure que he construido versión requerida de la biblioteca Boost.

No he probado antlr para esto todavía, pero es probablemente la mejor herramienta para ese tipo de tareas.

Estoy trabajando en un proyecto que emula PHP 5.3 en PHP 5.2: prephp . Incluye soporte de espacio de nombres (todavía no está completa sin embargo.)

Ahora, fuera de la experiencia de escribir esto hay un problema ambigüedad en espacio de nombres resolución : llamadas a funciones no cualificados y de las actualizaciones constantes tienen una reserva para el espacio de nombres global. Por lo que podría convertir el código automáticamente sólo si está bien cualificado completo o todas sus llamadas a funciones / constantes operaciones de búsqueda o si no se vuelve a definir cualquier función o constante en un espacio de nombres con el mismo nombre que un PHP función integrada.

Si estrictamente conforme con esta práctica (lo que de ellos a elegir), sería bastante fácil para convertir su código. Sería un subconjunto del código para emular los espacios de nombres en prephp. Si necesitas ayuda a la ejecución, no dudes en preguntarme, yo estaría interesado;)

PS: El código de emulación espacio de nombres de prephp es todavía tan incompleta y puede tener errores. Pero le puede dar algunas ideas.

Esta es la mejor respuesta que creo que va a ser capaz de encontrar:

Paso 1:. Crear un directorio llamado 5.3 para cada directorio w / código PHP5.3 en ella y se adhieren todos los códigos 5,3-específica en ella

Paso 2: Tome una clase que desea poner en un espacio de nombres y hacer esto en 5.3 / Página Web / Consolidator.inc.php

namespace WebPage;
require_once 'WebPageConsolidator.inc.php';

class Consolidator extends \WebpageConsolidator
{
    public function __constructor()
    {
        echo "PHP 5.3 constructor.\n";

        parent::__constructor();
    }
}

Paso 3: Utilice una función estrategia a utilizar el nuevo código PHP 5.3. Lugar en findclass.inc.php no PHP5.3:

// Copyright 2010-08-10 Theodore R. Smith <phpexperts.pro>
// License: BSD License
function findProperClass($className)
{
    $namespaces = array('WebPage');

    $namespaceChar = '';
    if (PHP_VERSION_ID >= 50300)
    {
        // Search with Namespaces
        foreach ($namespaces as $namespace)
        {
            $className = "$namespace\\$className";
            if (class_exists($className))
            {
                return $className;
            }
        }

        $namespaceChar = "\\";
    }

    // It wasn't found in the namespaces (or we're using 5.2), let's search global namespace:
    foreach ($namespaces as $namespace)
    {
        $className = "$namespaceChar$namespace$className";
        if (class_exists($className))
        {
            return $className;
        }
    }

    throw new RuntimeException("Could not load find a suitable class named $className.");
}

Paso 4: Vuelva a escribir el código para tener este aspecto:

<?php
require 'findclass.inc.php';

$includePrefix = '';
if (PHP_VERSION_ID >= 50300)
{
        $includePrefix = '5.3/';
}

require_once $includePrefix . 'WebPageConsolidator.inc.php';

$className = findProperClass('Consolidator');
$consolidator = new $className;

// PHP 5.2 output: PHP 5.2 constructor.
// PHP 5.3 output: PHP 5.3 constructor. PHP 5.2 constructor.

Eso trabajo por usted. Es un cuanto al rendimiento cludge, pero sólo un poco, y será destruido cuando se decida a dejar de apoyar a 5.3.

Lo que hice, con una gran base de código que utiliza la convención de nomenclatura guión bajo (entre otros), y require_once una porción entera en lugar de un cargador automático, era definir un cargador automático, y añadir class_alias líneas en los archivos que definen los alias a un nombre antiguo clases después de cambiar sus nombres para ser agradable con espacios de nombres.

luego empecé a quitar declaraciones require_once donde la ejecución no depende de la inclusión fin, ya que el cargador automático recogería la materia para arriba, y cosas por el espacio de nombres a medida que avanzaba corregir errores y así sucesivamente.

Ha funcionado muy bien hasta ahora.

Bueno, no sé si es la "mejor", pero en teoría, se puede utilizar una secuencia de comandos para llevar a su código de 5,3 migran y acondicionarlo en 5.2 (potencialmente, incluso usando PHP).

En los archivos de espacios de nombres que se quiere hacer algo converso:

namespace \Project\Directory\Filename;

class MyClass {
  public $attribute;

  public function typedFunction(MyClass $child) {
    if ($child instanceof MyClass) {
      print 'Is MyClass';
    }
  }
}

Para algo como:

class Project_Directory_Filename_MyClass {
  public $attribute;

  public function typedFunction(Project_Directory_Filename_MyClass $child) {
    if ($child instanceof Project_Directory_Filename_MyClass) {
      print 'Is MyClass';
    }
  }
}

Y en el código de espacio de nombres que se necesita para convertir de:

$myobject = new Project\Directory\Filename\MyClass();

Para:

$myobject = new Project_Directory_Filename_MyClass();

Mientras todo su includes y requires permanecería igual, creo que casi se podría necesitar para mantener algún tipo de caché de todas sus clases y espacio de nombres para hacer la conversión complejo alrededor de la 'instanceof' y mecanografiado parámetros si se utilizan. Esa es la cosa más difícil que puedo ver.

No he probado esto por mi cuenta, pero es posible echar un vistazo a este php 5.2 -.> php 5.3 conversión de la escritura

Es no es el mismo que 5.3 -> 5.2, pero tal vez usted encontrará algunas cosas útiles allí

.

Nuestra software DMS Reingeniería Toolkit puede probable implementar su solución bastante bien. Está diseñado para llevar a cabo transformaciones de código fuente fiable, mediante el uso de AST a AST transforma codificados en términos de superficie de sintaxis.

Tiene una PHP frontales que es un PHP completa, precisa analizador, constructor de AST y AST al regenerador de código PHP. DMS prevé prettyPrinting AST, o la impresión fidelidad ( "preservar números de columna, cuando sea posible").

Esta combinación se ha utilizado para implementar una variedad de herramientas de manipulación de código fuente PHP digno de confianza para PHP 4 y 5.

Edit (en respuesta a un comentario un tanto incrédula):

Para la solución de la OP, la siguiente regla de transformación DMS debe hacer la mayoría del trabajo:

rule replace_underscored_identifier_with_namespace_path(namespace_path:N)
   :namespace_path->namespace_path
"\N" -> "\complex_namespace_path\(\N\)" 
if N=="NCLASS_OR_NAMESPACE_IDENTIFIER" && has_underscores(N);

Esta regla se encuentra todos los identificadores "simples" que se utilizan donde se permiten caminos de espacio de nombres, y reemplaza los identificadores simples con la trayectoria de espacio de nombres correspondiente construido rasgando la cadena para el identificador aparte en elementos consitutent separados por guiones. Uno tiene que codificar algo de ayuda de procedimientos en langauge aplicación de DMS, PARLANSE, para comprobar que el identificador contiene guiones ( "has_underscores"), y para poner en práctica el desgarro aparte lógica mediante la construcción de la ruta correspondiente subárbol espacio de nombres ( "complex_namespace_path").

La regla funciona mediante la identificación abstracta árboles que corresponden a los no terminales de idioma (en este caso, "namespace_path", y la sustitución de los sencillos de árboles más complejos que representan la trayectoria espacio nombre completo. La regla está escrita en forma de texto, pero la regla sí analizado por DMS para la construcción de los árboles que necesita para que coincida con árboles de PHP.

DMS lógica de la aplicación de reglas puede trivialmente aplicar esta regla en todas partes del AST producido por el intérprete PHP.

Esta respuesta puede parecer demasiado simple en la cara de todas las cosas complicadas que conforma el langauge PHP, pero todas esas otras complejidad se oculta en la definición de PHP langauge utilizado por DMS; que definición es unas 10.000 líneas de definiciones léxicas y gramaticales, pero ya se ha probado y de trabajo. Toda la maquinaria DMS, y estas líneas 10K, son indicaciones de qué expresiones regulares simples no pueden hacer el trabajo de forma fiable. (Es sorprendente la cantidad de maquinaria que se necesita para hacer esto bien, he estado trabajando en DMS desde 1995).

Si quieres ver todos la maquinaria que compone la forma DMS define / manipula un idioma, puede ver un ejemplo sencillo agradable .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top