<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PHPBSD.net &#187; output-buffer</title>
	<atom:link href="http://www.phpbsd.net/tag/output-buffer/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.phpbsd.net</link>
	<description>Blogueando sobre PHP, BSD, SEO, AJAX, Seguridad, Rendimiento... y mucho más</description>
	<lastBuildDate>Thu, 07 Oct 2010 11:57:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Cache de páginas estáticas para PHP</title>
		<link>http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/</link>
		<comments>http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/#comments</comments>
		<pubDate>Wed, 16 May 2007 01:31:45 +0000</pubDate>
		<dc:creator>Oriol</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[output-buffer]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[webmaster]]></category>

		<guid isPermaLink="false">http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/</guid>
		<description><![CDATA[El motor de PHP es uno de los más rápidos generando páginas web aún así nunca será tan rápido como no tener que generar nada y que el servidor web devuelva páginas estáticas. A pesar de disponer de una aplicación web escrita en PHP podemos conseguir la misma velocidad que en una web estática cacheando [...]


Entradas relacionadas:<ul><li><a href='http://www.phpbsd.net/2007/05/02/cache-en-memoria-compartida-con-apc/' rel='bookmark' title='Permanent Link: Cache en memoria compartida con APC'>Cache en memoria compartida con APC</a></li><li><a href='http://www.phpbsd.net/2007/04/26/instalacion-del-apc-alternative-php-cache-sobre-freebsd/' rel='bookmark' title='Permanent Link: Instalación del APC (Alternative PHP Cache) sobre FreeBSD'>Instalación del APC (Alternative PHP Cache) sobre FreeBSD</a></li><li><a href='http://www.phpbsd.net/2007/07/12/nuevos-estandares-para-las-pear2/' rel='bookmark' title='Permanent Link: Nuevos estándares para las PEAR2'>Nuevos estándares para las PEAR2</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p>El motor de PHP es uno de los más rápidos generando páginas web aún así nunca será tan rápido como no tener que generar nada y que el servidor web devuelva <strong>páginas estáticas</strong>. A pesar de disponer de una aplicación web escrita en PHP podemos conseguir la misma <strong>velocidad</strong> que en una web estática cacheando las páginas generadas. Lo que se porpone a continuación es un <strong>sistema de cache</strong> donde las páginas sólo se generarán la primera vez que se acceda a ellas, en siguientes peticiones el servidor web devolverá las páginas estáticas generadas.</p>
<p>Existen varias propuestas de sistemas de cache donde siempre se ejecuta un script PHP trabajando con el output-buffer para guardar la respuesta. Estos sistemas de cache tiene el inconveniente de que a pesar de tener la página cacheada siempre estamos ejecutando un script PHP con el coste en rendimiento que ello conlleva. Como solución se propone trabajar con el output-buffer pero usar la directiva de configuración <a target="_blank" href="http://httpd.apache.org/docs/2.0/mod/core.html#errordocument" title="errordocument - core - Servidor HTTP Apache">ErrorDocument</a> del Apache para que si ya tenemos la página generada no se ejecute ni un script PHP.</p>
<p>La directiva <em>ErrorDocument</em> se usa para configurar lo que el servidor devolverá al cliente en caso de error. Pues bien, se trata de configurar el error que indica que no existe la página solicitada (error 404) para que apunte a un script PHP donde generaremos la página. En la siguiente petición a la misma página el Apache devolverá directamente el archivo HTML generado.</p>
<p>Algunas consideraciones previas:</p>
<ul>
<li>Necesitas tener permisos de escritura en el directorio donde pretendas guardar las páginas. (esto lo puedes conseguir fijando los permisos a 777).
<li>Necesitas poder configurar la directiva <em>ErrorDocument</em> de tu servidor Apache. (algunos hostings no lo permiten).</li>
</ul>
<p><strong>[1] Configurar el Apache</strong></p>
<p>Debemos añadir lo siguiente en nuestro <em>.htaccess</em> o en la configuración del servidor Apache:</p>
<p><code>ErrorDocument 404 genera_pagina.php</code></p>
<p><strong>[2] Añadir el código necesario</strong></p>
<p>Es necesario añadir un bloque de código al principio y al fin de cada script. A continuación una implementación de ejemplo:</p>
<div class="syntax_hilite">
<div id="php-3">
<div class="php"><span style="color:#FF9933; font-style:italic;">//obtenemos el nombre de la página solicitada</span><br />
<span style="color:#0000FF;">$pagina</span> = <a href="http://www.php.net/array_pop"><span style="color:#000066;">array_pop</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><a href="http://www.php.net/explode"><span style="color:#000066;">explode</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">'/'</span>,<span style="color:#0000FF;">$_SERVER</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#FF0000;">'REQUEST_URI'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
<span style="color:#FF9933; font-style:italic;">//iniciamos el output buffer</span><br />
<a href="http://www.php.net/ob_start"><span style="color:#000066;">ob_start</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
<span style="color:#FF9933; font-style:italic;">//.............................</span><br />
<span style="color:#FF9933; font-style:italic;">//código que genera la página</span><br />
<a href="http://www.php.net/echo"><span style="color:#000066;">echo</span></a> <span style="color:#FF0000;">'hola'</span>;<br />
<span style="color:#FF9933; font-style:italic;">//.............................</span><br />
<span style="color:#FF9933; font-style:italic;">//obtenemos el output bufer</span><br />
<span style="color:#0000FF;">$contenido</span> = <a href="http://www.php.net/ob_get_contents"><span style="color:#000066;">ob_get_contents</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
<span style="color:#FF9933; font-style:italic;">//guardamos la pagina estática</span><br />
file_put_contents<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$pagina</span>,<span style="color:#0000FF;">$contenido</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
<span style="color:#FF9933; font-style:italic;">//volcamos por pantalla y cerramos el output buffer</span><br />
<a href="http://www.php.net/ob_end_flush"><span style="color:#000066;">ob_end_flush</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</div>
</div>
<p></p>
<p>Se puede guardar el anterior código en un script llamado "genera_pagina.php" sustituyendo la linea <em>echo "hola"</em> por el código de nuestra aplicación (p.e. con un <em>include()</em>) o podemos dividir el código en dos scripts y usar las directivas <a target="_blank" href="http://es2.php.net/manual/es/ini.core.php#ini.auto-append-file" title="auto-append-file - PHP: Descripción de las directivas de núcleo en php.ini - Manual">auto-append-file</a> y <a target="_blank" href="http://es2.php.net/manual/es/ini.core.php#ini.auto-prepend-file" title="auto-prepend-file - PHP: Descripción de las directivas de núcleo en php.ini - Manual">auto-prepend-file</a> para no tener que modificar nuestra aplicación (cortar por las lineas de puntos).</p>
<p>En el ejemplo se obtiene sólo el nombre de la página solicitada y se crea una archivo con el mismo nombre con el contenido de la respuesta. Pero no soporta directorios, está pensado para trabajar sobre un directorio en concreto o en una web sin directorios en las URL. Cambiando la primera linea del ejemplo podéis hacer que se comporte de otra forma, el ejemplo simplemente obtiene el último trozo de la URL usando como delimitador "/".</p>
<p>A diferencia de otras propuestas de cache aquí estamos modificando el Apache para que ejecute un script en caso de no encontrar una página. Es por esto que en vuestra aplicación debéis generar una <strong>página de error</strong> en el caso de que la página solicitada no exista. Lo correcto es que en esta página de error se envíe la header correspondiente tal y como lo haría el Apache por defecto:</p>
<div class="syntax_hilite">
<div id="php-4">
<div class="php"><a href="http://www.php.net/header"><span style="color:#000066;">header</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"HTTP/1.0 404 Not Found"</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</div>
</div>
<p></p>
<p><strong>[3] Mantenimiento de la cache</strong></p>
<p>Por ultimo nos falta programar un proceso en el cron para que elimine los archivos de la cache que han caducado. Por ejemplo para mantener una cache de una hora:</p>
<p><code>0 * * * * find /web -mtime +1h -print0 | xargs -0 rm -f</code></p>
<p>Se ha de sustituir "/web" por la ruta física donde tenemos nuestra aplicación web. Si no queremos programar un cron siempre podemos hacer lo anterior desde algún script PHP que se ejecute constantemente en nuestra web.</p>
<p>Lo que comento en este post no es nada nuevo, ya fue propuesto por <a target="_blank" href="http://www.lerdorf.com/tips.pdf" title="Tips and Tricks PHPCon2002">Rasmus Lerdorf en el PHPCon del 2002</a> (aunque un poco caducada la presentación que enlazo merece la pena).</p>


<p>Entradas relacionadas:<ul><li><a href='http://www.phpbsd.net/2007/05/02/cache-en-memoria-compartida-con-apc/' rel='bookmark' title='Permanent Link: Cache en memoria compartida con APC'>Cache en memoria compartida con APC</a></li><li><a href='http://www.phpbsd.net/2007/04/26/instalacion-del-apc-alternative-php-cache-sobre-freebsd/' rel='bookmark' title='Permanent Link: Instalación del APC (Alternative PHP Cache) sobre FreeBSD'>Instalación del APC (Alternative PHP Cache) sobre FreeBSD</a></li><li><a href='http://www.phpbsd.net/2007/07/12/nuevos-estandares-para-las-pear2/' rel='bookmark' title='Permanent Link: Nuevos estándares para las PEAR2'>Nuevos estándares para las PEAR2</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Capturando los fatal errors del PHP con nuestro handler</title>
		<link>http://www.phpbsd.net/2007/01/14/capturando-los-fatal-errors-del-php-con-nuestro-handler/</link>
		<comments>http://www.phpbsd.net/2007/01/14/capturando-los-fatal-errors-del-php-con-nuestro-handler/#comments</comments>
		<pubDate>Sun, 14 Jan 2007 17:18:34 +0000</pubDate>
		<dc:creator>Oriol</dc:creator>
				<category><![CDATA[Artículos]]></category>
		<category><![CDATA[error-handler]]></category>
		<category><![CDATA[fatal-error]]></category>
		<category><![CDATA[output-buffer]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[webmaster]]></category>

		<guid isPermaLink="false">http://www.phpbsd.net/2007/01/14/capturando-los-fatal-errors-del-php-con-nuestro-handler/</guid>
		<description><![CDATA[Tal como comentaba en el post anterior voy a explicar como capturar los fatal errors del PHP para poder tratarlos en la medida de lo posible. Según este mensaje de la lista de desarrollo del PHP (fijaros en los autores) los fatal errors nunca podrán ser capturados en el userland, por ejemplo con un handler [...]


Entradas relacionadas:<ul><li><a href='http://www.phpbsd.net/2007/01/13/un-error-handler-que-lance-exceptions-en-php/' rel='bookmark' title='Permanent Link: Un error handler que lance exceptions en PHP'>Un error handler que lance exceptions en PHP</a></li><li><a href='http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/' rel='bookmark' title='Permanent Link: Cache de páginas estáticas para PHP'>Cache de páginas estáticas para PHP</a></li><li><a href='http://www.phpbsd.net/2007/02/09/leyendo-xml-desde-php-con-simplexml/' rel='bookmark' title='Permanent Link: Leyendo XML desde PHP con SimpleXML'>Leyendo XML desde PHP con SimpleXML</a></li></ul>]]></description>
			<content:encoded><![CDATA[<p>Tal como comentaba en el post anterior voy a explicar como capturar los fatal errors del PHP para poder tratarlos en la medida de lo posible. Según este <a title="'Re: [PHP-DEV] set_error_handler() and fatal errors?' - MARC" target="_blank" href="http://marc.theaimsgroup.com/?l=php-dev&#038;m=97673386418430&#038;w=2">mensaje de la lista de desarrollo del PHP</a> (fijaros en los autores) los fatal errors nunca podrán ser capturados en el userland, por ejemplo con un handler de errores personalizado, ya que en estos casos el intérprete es probable que quede en un estado inestable y es necesario de una terminación rápida y limpia.</p>
<p>Podemos conseguir un buen comportamiento ante los fatal error configurando adecuadamente las directivas implicadas. Sólo editando el php.ini podemos conseguir que se muestre un mensaje personalizado por pantalla, que se guarde en archivo o no, etc. Para más detalles podéis consultar <a title="PHP: Error Handling and Logging Functions - Manual" target="_blank" href="http://es2.php.net/manual/en/ref.errorfunc.php">el capítulo sobre el tema</a> en el manual del PHP. Lo que aquí se describe es una forma alternativa que nos permite tenerlo controlado desde nuestro código PHP. Como requisitos hemos de tener configurado el PHP para que nos muestre errores por pantalla mediante la directiva de configuración <em>display_errors</em>.</p>
<p>La idea es sencilla, se trata de capturar todo el output buffer de nuestra aplicación y antes de enviarlo al usuario parsearlo en busca de la palabra "error" en negrita seguida de dos puntos con un mensaje y un salto de línea. El fallo es que, lógicamente, si nosotros sacamos por pantalla un string que cumpla lo anterior lo detectaremos como un fatal error del intérprete... aunque es muy difícil que tengamos una cadena de texto que cumpla estas condiciones a no ser que sean errores de nuestra aplicación, en ese caso siempre les podemos cambiar el texto o también podemos configurar la directiva <em>error_prepend_string</em> con una key identificable y modificar el código aquí incluido.</p>
<p>El código es el siguiente:</p>
<div class="syntax_hilite">
<div id="php-7">
<div class="php"><span style="color:#000000; font-weight:bold;">function</span> fatal_error_handler<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$buffer</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; <span style="color:#616100;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><a href="http://www.php.net/ereg"><span style="color:#000066;">ereg</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"(error&lt;/b&gt;:)(.+)(&lt;br)"</span>, <span style="color:#0000FF;">$buffer</span>, <span style="color:#0000FF;">$regs</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color:#0000FF;">$err</span> = <a href="http://www.php.net/preg_replace"><span style="color:#000066;">preg_replace</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"/&lt;.*?&gt;/"</span>,<span style="color:#FF0000;">""</span>,<span style="color:#0000FF;">$regs</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC66CC;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
&nbsp; &nbsp; <a href="http://www.php.net/error_log"><span style="color:#000066;">error_log</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$err</span>,<span style="color:#CC66CC;">1</span>,<span style="color:#FF0000;">'tu.email@de.alertas.com'</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color:#616100;">return</span> <span style="color:#FF0000;">'Mensaje de error personalizado para el usuario'</span>;<br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#616100;">return</span> <span style="color:#0000FF;">$buffer</span>;<br />
<span style="color:#006600; font-weight:bold;">&#125;</span><br />
<a href="http://www.php.net/ob_start"><span style="color:#000066;">ob_start</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"fatal_error_handler"</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
funcion_que_no_existe<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;<br />
<a href="http://www.php.net/ob_end_flush"><span style="color:#000066;">ob_end_flush</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</div>
</div>
<p></p>
<p>Entre lo aquí descrito y el handler de errores detallado en el post anterior deberíamos tener cualquier error del PHP bajo control. Existen otros errores que no vamos a poder controlar nunca como son todos los errores de sintaxis que provocan <em>parse errors</em>, por ejemplo que falte un ";", estos normalmente se detectan en la etapa de desarrollo y no se espera que sucedan en producción... y si suceden sólo nos queda tener correctamente configuradas las directivas pertinentes del PHP.</p>


<p>Entradas relacionadas:<ul><li><a href='http://www.phpbsd.net/2007/01/13/un-error-handler-que-lance-exceptions-en-php/' rel='bookmark' title='Permanent Link: Un error handler que lance exceptions en PHP'>Un error handler que lance exceptions en PHP</a></li><li><a href='http://www.phpbsd.net/2007/05/16/cache-de-paginas-estaticas-para-php/' rel='bookmark' title='Permanent Link: Cache de páginas estáticas para PHP'>Cache de páginas estáticas para PHP</a></li><li><a href='http://www.phpbsd.net/2007/02/09/leyendo-xml-desde-php-con-simplexml/' rel='bookmark' title='Permanent Link: Leyendo XML desde PHP con SimpleXML'>Leyendo XML desde PHP con SimpleXML</a></li></ul></p>]]></content:encoded>
			<wfw:commentRss>http://www.phpbsd.net/2007/01/14/capturando-los-fatal-errors-del-php-con-nuestro-handler/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

