Foros del Web » Programando para Internet » PHP »

fabricar un lenguaje tipo foro

Estas en el tema de fabricar un lenguaje tipo foro en el foro de PHP en Foros del Web. No se como se llama el sistema.. bbcode kreo. pero me gustaria que al leer de una base de datos: Código: [codigo] aqui todo mi ...
  #1 (permalink)  
Antiguo 19/06/2005, 18:50
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
fabricar un lenguaje tipo foro

No se como se llama el sistema.. bbcode kreo. pero me gustaria que al leer de una base de datos:

Código:
[codigo]
aqui todo mi codigo
[/codigo]
Se representase como

Código PHP:
<div class="code">aqui todo mi codigo</div
Y me he creado esta funcion:

Código PHP:
function elCode$codigo ) {
    
$hay=preg_match_all("/\[(code)\]((.|\s)+)\[\/\\1\]/i",$codigo,$resultado);
    for(
$a=0;$a<count($resultado[1]);$a++) {    //por cada code
        
$HTML='<div class="code">'nl2br($resultado[2][$a]) .'</div>';
        
$codigo=str_replace$resultado[0][$a] , $HTML $codigo );
    }
    return 
$codigo;


Y funciona... en parte. El problema esta en:

Código:
[codigo]mi codigo1[/codigo]
[codigo]mi codigo2[/codigo]
es sustituido por:
Código PHP:
<div id="code">mi codigo1[/codigo][codigo]mi codigo2</div

¿Como hacer para que no tome todo el centro como un bloque y se pare en el primer [/codigo] que encuentre? Las expresiones regulares es lo que tiene..


saludillos!
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #2 (permalink)  
Antiguo 24/06/2005, 03:36
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 20 años, 9 meses
Puntos: 1
Tu primer intento es bastante bueno. La razón por la que está haciendo la transformación de ese modo es que, en las expresiones regulares, caracteres como '*' y '+' son "codiciosos" por omisión. Es decir, tratan de coincidir con tantos caracteres como les sea posible.

Como ves, en tu ejemplo la expresión regular coincide con la etiqueta de apertura [codigo], luego empieza a buscar uno o más caracteres antes de encontrarse con el cierre [/codigo]. La expresión pasa por el primer cierre, pero al ser "codicioso" el segmento (.|\s)+ continúa su trabajo en caso de que encuentre otro cierre más, y así poder coincidir con tantos caracteres como pueda. Efectivamente, encuentra la cadena '[/codigo]' otra vez, así que coincide con toda la cadena completa, y la transformación culmina del modo que observas.

Una solución es usar el caracter '?', el cual usado después de '+' o '*' le quita su naturaleza codiciosa al operador, de modo que la expresión trata de coincidir con la menor cantidad de caracteres posible.

Considera por ejemplo:

Código PHP:
function elCode ($codigo) {
    
$hay preg_match_all ('/\\[(codigo)\\]((.|\s)+?)\\[\\/\\1\\]/i'$codigo$resultado);

    if (! 
$hay)
        return 
$codigo;

    for(
$i 0$i count ($resultado[1]); $i++) {  // por cada code
        
$HTML '<div class="code">' nl2br($resultado[2][$i]) . '</div>';
        
$codigo str_replace ($resultado[0][$i], $HTML ,$codigo);
    }
    return 
$codigo;

Disculpa que hice algunos cambios de estilo :), en realidad el detalle importante es que la expresión (.|\s)+ tiene un signo '?' al final para que no coincida "codiciosamente".
  #3 (permalink)  
Antiguo 24/06/2005, 12:16
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Perfecto, me encanta, ahi esta la solucion.

Ademas he aprendido una cosa mas de expresiones regulares.

Muchas gracias leonardop! ademas me has optimizado la funcion! jeje
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #4 (permalink)  
Antiguo 24/06/2005, 15:16
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Me surge un problema añadido. El codigo debe estar identado para estar presentable. En la BD mysql meto en el campo de texto tabulaciones, pero luego al imprimirlas en la pagina web se omiten. Pasa lo mismo que si inserto en la BD unos 5 espacios seguidos (chapuza para simular), se omiten.

¿Hay alguna manera de buscar el caracter de tabulado (\t) y entonces ya formatearlo.. ya buscaria la forma?


Gracias de nuevo.
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #5 (permalink)  
Antiguo 24/06/2005, 16:57
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Si, creo que voy avanzando..

Código PHP:
/* coge las tabulaciones \t y las formatea a HTML    */
function lasTabulaciones($codigo2) {
    
$hay2=preg_match_all('/(\t){1,}((.|\s)+?)\r/i',$codigo2,$resultado2);
    if(!
$hay2) return $codigo2." NADA";
    else {
        for(
$j=0$j<count($resultado2[2]); $j++) {    //por cada tabulacion
            
$HTML2="<span style='padding-left:25px;'>".$resultado2[2][$j]."</span>";
            
$codigo2=str_replace($resultado2[0][$j], $HTML2$codigo2);
        }
        return 
$codigo2;
    }
}

/* se encarga de coger el [code][/code] y formatearlo */
function elCode ($codigo) {
    
$hay preg_match_all ('/\\[(code)\\]((.|\s)+?)\\[\\/\\1\\]/i'$codigo$resultado); 
    if (!
$hay
        return 
$codigo;
    for(
$i=0$i<count($resultado[1]); $i++) {  // por cada code 
        //$resultado[2][$i]=ereg_replace('\t(((.|\s)+)?)', "<span style='padding-left:25px;'>$1</span>" , $resultado[2][$i]);    //tabulaciones
        
$resultado[2][$i]=lasTabulaciones($resultado[2][$i]);
        
$HTML '<div class="code">'.nl2br($resultado[2][$i]).'</div>';
        
$codigo str_replace ($resultado[0][$i], $HTML ,$codigo); 
    } 
    return 
$codigo;

La funcion lasTabulaciones es muy parecida a elCode, solo que lasTabulaciones se encaga de las lineas que empiezan por tabulacion y acaban en salto de linea (las identadas).

Para una tabulacion funciona bien.
Para dos tabulaciones en la misma linea..mm.. quedan omitidas a partir de la segunda.

He intentado hacer algo recursivo, pero no me ha salido nada de lo que he probado... me parece.. demasiado locura.

¿A alguien se le ocurre algo?
Lo que quiero hacer es que:
tantos "\t" como encuentre antes de "texto" lo sustituya por "<span style='padding-left:25px;'>". Despues claro, debe cerrar los span abiertos. (metiendo antes de cerrarlos el "texto". Algo complicado?
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #6 (permalink)  
Antiguo 25/06/2005, 02:34
 
Fecha de Ingreso: julio-2004
Ubicación: Puerto Vallarta, Jalisco, Mexico
Mensajes: 186
Antigüedad: 19 años, 9 meses
Puntos: 0
Por lo regular cuando me enfrento a un problema de Expresiones Regulares uso este programa.

http://www.regexbuddy.com

tal vez te pueda ayudar a crear tu expresion de la manera como la quieres tu :)
__________________
Shanti Castillo G.
  #7 (permalink)  
Antiguo 25/06/2005, 06:14
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 20 años, 9 meses
Puntos: 1
Vaya, ¡tu progreso es bastante bueno! La idea que tienes es muy buena, y el código original de lasTabulaciones() se acerca, dando una idea de lo que quieres, aunque le hace falta un ligero ajuste.

El código original reemplaza toda la línea completa por el valor de $HTML2, y esta cadena solo declara un elemento <span>. Lo que hace falta es, considerando el número de caracteres "\t" encontrados al principo de cada línea, agregar un número igual de elementos <span>. Esto sugiere el uso de algún ciclo.

Considera como ejemplo:

Código PHP:
function lasTabulaciones ($codigo) {
    
$hay preg_match_all ('/^(\\t+)(.*)$/mi'$codigo$resultado);

    if(! 
$hay)
        return 
$codigo ' NADA';

    
// por cada linea con tabulaciones
    
for($i 0$i count ($resultado[2]); $i++) {
        
// Inicialmente, $HTML comienza como el cuerpo de la linea
        
$HTML $resultado[2][$i];

        
// Por cada tabulacion al comienzo de la linea, embeber $HTML
        // en un elemento <span>
        
$n strlen ($resultado[1][$i]);
        for (
$j 0$j $n$j++) {
            
$HTML "<span style='padding-left:25px;'>" $HTML '</span>';
        }

        
$codigo str_replace ($resultado[0][$i], $HTML$codigo);
    }

    return 
$codigo;

Algunos comentarios más sobre el código anterior:
  • No es necesario diferenciar los nombres de las variables como $codigo2, $hay2, etc. ya que todas ellas son locales a la función.
  • En la expresión regular, {1,} es equivalente a +.
  • Es posible simplificar (.|\s) por ., ya que buscas coincidencias de cualquier caracter hasta el final de línea.
  • Ya no es necesario que esa expresión sea no-codiciosa, así que puede expresarse como .* en lugar de .+?.
  • Es más confiable usar el "anclaje" para determinar el final de línea en una expresión regular. En este caso, en lugar de la secuencia \r se usa el caracter $ al final de la expresión, y se usa el modificador 'm' para indicar que el procesamiento de la expresión sea multi-línea.
  • De forma semejante, es bueno usar el anclaje al comienzo para indicar que las tabulaciones deben aparecer al comienzo de una línea. El caracter ^ al comienzo de la expresión tiene ese efecto.
  • Volviendo a la función, no es necesaria la estructura de control else ya que el bloque del if contiene una sentencia return, así que en ese punto la función finalizaría y el resto del código no es ejecutado.

Espero que te sea de ayuda :).
  #8 (permalink)  
Antiguo 25/06/2005, 10:00
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Qué buenas respuestas, asi da gusto

Ok, una solucion brillante. Sin mas. Hacia mucho que no me respondian de esa manera.

Aplausos para ti leonardop

Cita:
No es necesario diferenciar los nombres de las variables como $codigo2, $hay2, etc. ya que todas ellas son locales a la función.
Ok, no lo tenia claro, y por si acaso para que no hubiera mas conflictos añadidos.

Cita:
En la expresión regular, {1,} es equivalente a +.
Jejej es que no me acordaba si era + o...

Cita:
Es posible simplificar (.|\s) por ., ya que buscas coincidencias de cualquier caracter hasta el final de línea.
mmm pensaba que el . no cogia todo lo que coge \s. Gracias por aclararmelo!

Cita:
-Ya no es necesario que esa expresión sea no-codiciosa, así que puede expresarse como .* en lugar de .+?.
-Es más confiable usar el "anclaje" para determinar el final de línea en una expresión regular. En este caso, en lugar de la secuencia \r se usa el caracter $ al final de la expresión, y se usa el modificador 'm' para indicar que el procesamiento de la expresión sea multi-línea.
Ok, no tenia seguro ninguna de esas dos cosas . Y el modificador m nunca lo habia utilizado! (Como nunca utilice ^$ para cosas que no fueran una frase en una variable...)

Cita:
Volviendo a la función, no es necesaria la estructura de control else ya que el bloque del if contiene una sentencia return, así que en ese punto la función finalizaría y el resto del código no es ejecutado.
Ok, es solo que me quedaba mas legible.



Solo una duda, en las frases de tabulado, se tabula perfectamente, es decir, el cometido de la funcion se cumple. Lo que pasa es que la siguiente frase en vez de salir en el renglon siguiente, sale uno mas abajo, como si hubiera un <br> misterioso.

¿Eso es cosa del <span> que es un elemento que provoca esas cosas? He probado y no le he encontrado solucion. Ocurre tanto en IE como en Firefox como en Opera.

Imageshack esta caido ahora, he tenido que utilizar flickr por si no se me entendio bien:
http://www.flickr.com/photos/30924763@N00/21464997/
Aqui he dejado una foto de captura del resultado final (le he añadido borde a los span).


De ti no me olvido Shantic, muchas gracias por el programa. Lo tengo que probar, porque la verdad es que ando un poco muy verde con las expresiones regulares



salu2 a los dos y gracias por respoder!!
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #9 (permalink)  
Antiguo 28/06/2005, 07:56
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Bien, he visto que el foro tiene un redireccionador para las paginas exteriores, que no muestra bien el enlace de flickr si no se modifica manualmente. Y viendo que imageshack ya funciona, posteo la imagen directamente:



Asi sin mas.

¿Alguna idea para eliminar ese espacio?
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:17.