Control de la sortida de PHP amb ob_start() i ob_flush()

Avui hem decidit canviar el comportament de l’aplicació que estem desenvolupant perquè, en cas que la base de dades petés, era terriblement lleig tenir 200 warnings i errors de MySQL rondant pel mig de la web. Era més lògic mostrar una pàgina d’error perquè el client veiés que alguna cosa havia anat malament, i que ho provés més tard.

La idea inicial era simple. Hi ha la següent funció:

db_query($query)

Aquesta funció permet fer una consulta a la base de dades abstraient (una mica) l’aplicació del MySQL. A més, en cas d’error a la consulta, afegeix entrades al registre de l’aplicació i més coses. En fi, doncs la idea era simplement modificar la funció afegint-hi això en cas que hi hagués un error:

header(”Location: error.php”);

La idea està molt bé, però no és possible, perquè si l’error es produeix un cop s’ha iniciat la sortida, tindrem el típic problema de “headers already sent by”.

I és aquí on entren en joc les funcions de búfer ob_start() i ob_flush(). Aquestes funcions retenen i alliberen, respectivament, la sortida de l’aplicació, excepte les capçaleres. Per tant, això ens permet retenir la sortida fins que estiguen segurs que no hi pot haver cap error, i llavors executar ob_flush().

D’aquesta manera se solucionen els possibles problemes d’enviament de capçaleres quan ja hi ha sortida.

Internet Explorer i focus() endarrerit

Avui a la feina estava tocant un JavaScript i m’he adonat d’una cosa. L’IE no li feia ni cas a una de les instruccions. La cosa és la següent: hi ha una part de l’aplicació que es recarrega contínuament (cada 5 segons) mitjançant Ajax. Aquesta part conté un “input” el qual, si estàs escrivint mentre es refresca, perd el contingut. La idea del JavaScript era fer la petició Ajax i en rebre la resposta:

1. Copiar el valor de l’”input” en una variable temporal.
2. Substituir el contingut del “div” corresponent amb el de la resposta.
3. Assignar el valor de la variable al nou “input”.
4. Restaurar la posició del ratolí en cas que estigués seleccionat o tingués focus.

I en aquest últim cas és en el que fallava. Una de les instruccions era que, si anteriorment tenia focus, se li tornés a donar focus. Això ho fèiem així:

document.getElementById(”elementToFocus”).focus();

Misteriosament, no funcionava. En Firefox sí, però a l’IE no. El més curiós era que si fèiem això:

document.getElementById(”elementToFocus”).focus();
document.getElementById(”elementToFocus”).focus();

Sí que funcionava! És il·lògic, però investigant, sembla que l’Explorer fa alguna cosa en segon pla i no deixa prendre el focus fins passats uns quants mil·lisegons. Es pot solventar així:

setTimeout(”document.getElementById(”elementToFocus”).focus();”, 100);

D’altra banda, ens hem trobat un altre problema. El tema de conservar la selecció actual. En Firefox, hi ha els simplíssims selectionStart i selectionEnd, que et fan tota la feina, però en Explorer, no. La manera “oficial” de Microsoft és un autèntic nyap, i a Mishoo s’han currat una alternativa fent ús d’una funció no documentada que retorna una “cadena opaca”. Això és el que hem hagut de fer, quin remei.

Com sempre, les cerques sobre coses de JavaScript amb el senyor IE són d’allò més curioses…