Apr 25

sitemap para SMF

Hace tiempo comenté en un post que el foro SMF es un desastre para que lo indexe google y, de hecho, no aparecía en google ninguno de los temas de mi foro de java. Intenté instalar el plugin seo4smf para tratar de arreglarlo, pero no conseguí que me funcionara. Al final, como comenté en aquel post, me hice un pequeño programa java que generara un fichero sitemap.xml para colgarlo en el foro.

Esa opción no era buena del todo. Conseguí que google indexara los temas del foro, pero tenía que actualizar el sitemap periódicamente a mano. Así que decidí hacerme un pequeño script sitemap.php que hiciera de sitemap para google de forma automática.

Este script, al llamarlo, consulta en la base de datos el campo id_topic de la tabla smf_topics. Es la única información que necesita para generar el fichero XML de sitemap. El script dice que devuelve un "Content-Type : application/xml" para que cuando google lo consulte piense que es un fichero XML, luego envía los tags XML correspondientes al sitemap.

Adjunto el código php por si a alguien le interesa

<?php
header(’Content-Type: application/xml’);
include (’Settings.php’);

print (’<?xml version="1.0" encoding="UTF-8"?>’);
print (’<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">’);

$link = mysql_connect ($db_server, $db_user, $db_passwd) or die ("<center>No se puede conectar con la base de datos\n</center>\n");
$query=’select id_topic from smf_topics’;
$result=mysql_db_query ($db_name, $query, $link);

while ($row = mysql_fetch_array ($result))
{
   print (’<url>’);
   print (’<loc>’);
   print (’http://foro.chuidiang.com/index.php?topic=’.$row[0]);
   print (’</loc>’);
   print (’</url>’);
}
mysql_free_result($result);
print (’</urlset>’);
?>

El include "Settings.php" únicamente incluye un fichero de configuración del foro, en el que están las variables con el nombre de la base de datos $db_name, el usuario $db_user y la password $db_passwd. Ojo, no le busqueis pegas, que las tiene. Yo no tengo ni idea de PHP.

 

Aug 17

Impedido para programar

Siempre que me pongo a programar, aunque sea una tontería, me pasa lo mismo. Me quedo bloqueado.

Como comenté en un post anterior, estoy haciendo un pequeño programa PHP para que la gente pueda apuntar en qué proyectos trabaja durante el mes y cuánto tiempo dedica a ello. Cosas del trabajo.

Me puse a ello. Lo primero, una tabla de base de datos para apuntar a los programadores y una serie de páginas php para que se puedan registrar, hacer login y, por supuesto, para que el administrador pueda administrar esa tabla: añadir, borrar y modificar usuarios.

Todo estupendo hasta este momento.

Iba a ponerme ahora con otra tabla de base de datos en la que se apunten los proyectos en marcha. Por supuesto hay que hacer otra serie de páginas php para administrar esa tabla: crear, borrar o modificar proyectos.

Ahí me he quedado bloqueado.

Es otra vez lo mismo. Otra tabla a la que  hay que hacerle nuevamente tres páginas php para lo mismo de antes, altas, bajas y modificaciones. Lo más cómodo, copy/paste de las de usuarios e ir modificando. Pero copy/paste desde mi punto de vista ¡¡es pecado!!. El código no debería repetirse. Hay que hacer lo posible por extraer lo común a una función o grupo de funciones y reutilizarlas.

Rápidamente, me puse a darle vueltas a la cabeza. Tendría que hacer unos ficheros de configuración que digan cómo son las tablas -o bien mirar directamente los metadatos de la base de datos- y luego hacer tres funciones que me den la página de alta, baja y modificación simplemente pasándoles el nombre de la tabla y qué campos son el identificador principal de la tabla. Seguramente sea necesario algún parámetro más.

Esto, por supuesto, lleva más tiempo que un copy/paste y hacerlo todo a piñón fijo, repitiendo el código cada vez que se presente una tabla. También es más versátil. Si se hace bien, te ahorrará un montón de trabajo cada vez que tengas que hacer una tabla con añadir, borrar y modificar. En contra, también, que el código resultante será mucho menos claro.

Y en eso estoy.

Una aplicación que me podía llevar una o dos semanas a ratos libres -estoy de vacaciones-, me va a llevar:

  • unos días para hacer la primera tabla
  • otro día para empezar la segunda tabla y ver que el copy/paste me vendría bien pero no quiero usarlo.
  • una semana entera para darle vueltas a si hago o no hago la cosa esa común/reutilizable para no utilizar el copy/paste.
  • otras dos semanas para ponerme a hacerla y meterme en complicaciones.
  • un minuto para mandarlo todo a la mierda. No acabaré el común/reutilizable porque es más complejo de lo que parece y no hago el copy/paste porque es pecado. La aplicación y yo nos quedamos bloqueados.
  • Varios meses para estar pensando: "debería acabar eso que tengo a medias…."

Pues eso, ahora mismo estoy en el punto 3, empezando la semana de darle vueltas a ver si hago o no la cosa común/reutilizable. Para este proyectito no merecería seguramente la pena, pero seguro que este proyectito no es el último.

¿No estais hasta las narices de hacer siempre lo mismo, una y otra vez tabla en base de datos, ventana de alta, de modificación y de baja?. ¿Haríais la cosa común/reutilizable?.

Aug 15

Hormiguillas en el culo

Últimamente parece que tengo hormiguillas en el culo. No paro quieto y ando saltando de un tema a otro.

Primero me puse con el tema de perl, para hacer mi conversor de lenguajes. Eso fue cosa del trabajo.

Luego estuve un par de semanas de Rodriguez en casa, sin familia, así que retomé lo de JSP. Tenía los taglibs un poco atascados por una tontería de Maven.

Ahora, de vacaciones, y a ratos perdidos, he retomado lo de PHP que dejé en su día. Estoy intentando hacer una pequeña librería PHP para la validación de sesiones y usuarios. La idea es que haya una serie de páginas PHP que permitan ver una lista de usuarios y añadir, borrar y modificar dichos usuarios. Esta parte está prácticamente acabada.

Luego, haré unas funciones PHP que se puedan llamar desde otra aplicación PHP y que permitan validar una sesión con uno de los usuarios. También se podrá además llamar al conjunto de páginas PHP de usuarios para gestionarlos.

Con esto tengo intención de hacer dos aplicaciones PHP:

  • Una para el trabajo, que permita a la gente poner cuántos días del mes han dedicado a qué proyectos.
  • Otra para mi página web, que permita añadir comentarios a los tutoriales. Ya la tengo hecha, pero si algún patán mete alguna burrada, el borrado dichos comentarios se hace manejando directamente la base de datos. Quería poner un usuario administrador -yo- que pueda borrar desde el navegador los comentarios de los patanes.

Pues nada, poco a poco y a ver si acabo alguna de ellas antes de que me pique otra hormiguilla en el culo. La del J2EE con EJBs anda por las cercanías ….

Aug 03

Puente PHP/Java

Alucino con lo que se inventa por ahí.

Urgando por la red me he encontrado con un puente PHP/Java. Básicamente es un añadido a PHP de forma que se puede llamar a clases de java desde PHP.

El manejo parece muy sencillo en la página. Simplemente se instancia una clase PHP llamada Java a la que se le pasa en el constructor como String el nombre de la clase Java. La clase PHP creada así tiene todos los métodos de la clase Java y a partir de ahí podemos usarla normalmente como PHP. Un ejemplo copiado de la página

<?php
$v = new Java("java.util.Vector");
$v->add($buf=new Java("java.lang.StringBuffer"));
$buf->append("100");
echo (int)($v->elementAt(0)->toString()) + 2;
?>

En fin, es una cosa que si me preguntan antes de verla diría que es imposible llamar desde php a java -salvo quizás alguna función php para lanzar ejecutables externos-. Va a haber que pensárselo dos veces antes de decir en programación que algo no se puede hacer.

Mar 03

¿PHP o Java/JSP?

¿Qué usamos? ¿PHP o Java con JSP?

Un posible criterio es decidir si tenemos una aplicación con web o una web con aplicación. ¿Qué quiere decir esto?

Si tenemos una aplicación con web, es decir, unos datos más o menos complejos que requieren un tratamiento más o menos complejo y los resultados vamos a presentarlos en un navegador, entonces tenemos una aplicación con web. Para esto es adecuado Java/JSP. Java nos da la potencia necesaria para hacer la parte de aplicación, mientras que presentamos los resultados en el navegador con JSP. Este puede ser el caso, por ejemplo, de una gestión de empleados con nominas, contabilidad, gestión de stock en almacenes, … que ponemos accesibles desde navegador. En fin, cualquier aplicación que tuviera sentido por sí misma como aplicación de escritorio.

Si tenemos una web con aplicación, básicamente estamos haciendo una web en la que necesitamos algo de código para guardar datos en base de datos o hacer algún que otro proceso sencillo de código para presentar esos datos. Este es el caso típico de los foros, los blogs, etc, etc. Para esto es adecuado PHP.

Visto en Jarfil’s Blog. Por cierto, está curioso el gatito de arriba a la izquierda de ese blog. Echale un ojo y luego puedes jugar con él clickandolo.

Feb 16

Imágenes aleatorias en PHP

Sigo jugando con PHP. Lo siguiente que se me ocurrió fue poner un chiste aleatorio en mi página. Así que cogí unos cuantos chistes de internet (esta es la parte divertida) y los guardé en un directorio en el servidor de mi página. Luego a investigar con php cómo se lee el contenido de un directorio para poner la imagen.

Me encontré con la función scandir(), que te devuelve un array con los nombres de los ficheros dentro del directorio. También devuelve los subdirectorios "." y "..".

A partir de ahí fué fácil, simplemente llamar a rand (2, $numeroFicheros). Lo de 2 para que se salte el 0 y el 1 que corresponden a los dos subdirectorios "." y "..". List todo. Lo pruebo en mi ordenador con mi propio servidor web de prueba y va estupendamente. Lo subo a mi servidor oficial, lo prueba y no va.

Una cosa que me llama poderosísimamente la atención es lo fácil que es todo en la teoría y como se complica la realidad. Me pongo a investigar y resulta que scandir() está disponible a partir de PHP 5. En casa tengo PHP 5, en el servidor del hosting tengo PHP 4. A buscar más.

Al final encontré la función glob(), a la que le pasas un patrón, estilo "imagenes/*" y te devuelve todos los ficheros que cumplen el patrón. No es lo mismo que scandir(), pero vale perfectamente. Esta función si es válida …. a partir de PHP 4.3.0 … Me voy al servidor, con más miedo que verguenza, a ver qué versión exacta tiene, no vaya a ser …  ¡¡Buff!!, tiene la 4.4.4.

glob() no devuelve los subdirectorios "." y "..", así que a cambiar el rand() por rand(0,$numeroFicheros)

Al final el código PHP quedó así

<?php
        $fichero = glob (’chistes/*’);
        $chiste = rand(0,count($fichero)-1);
        print(’<img src="’.$fichero[$chiste].’" alt="chiste" /> ‘);
?>

Feb 14

Resuelto mi php

Ya he terminado mi experimento con php. En mi página ya se pueden añadir comentarios al final de cada artículo y funciona todo (creo).

Aunque me ha costado un poco, porque no tengo ni idea de php, he aprendido algunas cosas. Aquí un pequeño resumen

  • El  usuario y password de la base de datos se guardan como dos variables en un fichero .php en algún sitio que no esté accesible desde el navegador, protegido con un .htaccess o simplemente fuera del directorio del sitio. No sé si es muy necesario, pero supongo que nunca está de más ser algo paranoico con la seguridad.
  • Cuando se deja libertad a los visitantes para escribir texto que luego se va a insertar en base de datos o mostrar en el navegador, conviene escapar las comillas. PHP lo tiene más o menos resuelto con funciones del estilo addslashes() que hacen eso precisamente, poner una \ delante de las comillas. Hay un detalle con esto. PHP se puede configurar para que automáticamente añada las \ delante de las comillas en todas los contenidos que lleguen con $_POST o $_GET. Si esto es así, no debemos añadir nosotros más \. Para verificar esto, está la función get_magin_cuotes_gpc(), que nos devuelve 1 si PHP va a añadir automáticamente las \.
  • Pasa lo mismo con los caracteres que html interpretará luego, como <, >, o los que no son válidos, como letras con acentos, eñes y demás. PHP también tiene una función para esto: htmlspecialchars()
  • Cuando recogemos una fecha/hora de base de datos, el formato obtenido no le gusta a PHP. Para que sea más compatible, en el select de base de datos podemos poner "select UNIX_TIMESTAMP(fecha) as fecha, otrocampo from…" De esta forma, el resultado que obtenemos para fecha lo entiende perfectamente PHP.
  • Otra cosa que tuve que hacer es una página .php aparte que únicamente realiza la inserción en base de datos del comentario e inmediatamente después, con header(), redirige a la página original. Esta página de inserción es a la que llaman los submit de los formularios. Con esto evito el problema que comenté en otro post al pulsar el refrescar del navegador. El header() debe usarse antes de enviar nada al navegador.

y creo que no se me olvida nada. A ver si lo apunto todo con algo más de detalle en algún sitio.

Feb 13

“PHPando”

Para jugar un poco con php primero hice una especie de contador en mi página web.

Cree una base de datos, añadí una tabla con varios campos: mes de la visita, año de la visita, número de visitas y página visitada. Todo sin problemas y está más o menos funcionando en mi sitio.

Ahora me he puesto a hacer algo más complejo. Estoy poniendo la posibilidad de que la gente añada comentarios a los artículos. Todo está funcionando bien… salvo una pequeño detalle que no consigo resolver.

Si una vez que alguien ha insertado un comentario, pulsa “recargar” en el navegador, vuelve a insetarse el mismo comentario. Aunque el formulario esté vacío, se ve que al recargar todavía se acuerda del contenido de $_POST[] y vuelve a insetar. Así que aquí ando, peleándome con varias posibilidades:

  • Detectar si es recarga de página para no hacer la inserción del comentario.
  • Viendo si hay forma de vaciar $_POST[] después de haber hecho la inserción
  • No me gustaría, pero quizás tenga que hacer una página intermedia que haga la inserción y luego redirija con header() a la original.
  • Y me gustaría todavía menos abrir una sesion con session_start() o similar. Creo que no puedo usar las variables $_SESSION[] si no abro una sesión y la sesión debe abrirse justo antes de enviar nada al navegador, por lo que tendría que volver a tocar TODAS las páginas (ya las cambié de html a php con hoja de estilo). No se me ocurrió hacer un <?php cabecera(); … al principio de todas

A ver si esta tarde lo acabo…