<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9182126501089271480</id><updated>2012-02-16T09:05:11.869Z</updated><category term='sesiones'/><category term='KROWORK'/><category term='reflection'/><category term='problemas'/><category term='objetos'/><category term='plantillas'/><category term='static'/><category term='soluciones'/><title type='text'>KROWORK: Anotaciones de PHP</title><subtitle type='html'>Anotaciones de PHP</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-2348120504274376265</id><published>2007-12-23T12:24:00.000Z</published><updated>2007-12-27T09:17:53.993Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='plantillas'/><title type='text'>Plantillas en PHP (IV)</title><content type='html'>Cuarta parte de esta serie. Como había dicho vamos a finalizar con el ejemplo e incluir el paginador en la plantilla principal.&lt;br /&gt;&lt;div class=fullpost&gt;&lt;br /&gt;Podríamos, como dije en el anterior post, incluir el paginador en nuestra plantilla haciendo un include del archivo que contiene la plantilla. Podríamos pensar que si todas las plantillas están en la misma carpeta no tenemos que especificar la ruta de la plantilla paginador(¿podemos poner simplemente: &lt;em&gt;include "paginador.phpt";&lt;/em&gt;?), pero esto no es así. Como vimos, la plantilla principal en última instancia se carga con un include por lo tanto tendrá como path el del archivo que la haya invocado. Esto es un problema ya que si la plantilla principal puede ser invocada desde scripts en diferentes carpetas la ruta del include del paginador debería variar! Para solventar esto añadiremos un método __toString al objeto Template:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;  function __toString(){&lt;br /&gt;   $this-&gt;dump();&lt;br /&gt;   return "";&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ojo, este método no devuelve una cadena de texto, sino que hace un echo de la plantilla. Es decir, no tendría sentido hacer $cadena=$miPlantilla-&gt;__toString() ya que $cadena quedaría vacía. Se que esto no es del todo ortodoxo pero veremos que es una forma muy buena de representar objetos en una plantilla.&lt;br /&gt;&lt;br /&gt;Esto nos permitirá crear ambas plantillas por separado de modo que especificamos las rutas de la plantillas desde el script que las va a usar:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;$miPlantilla=new Template(&amp;quot;plantillas/miPlantilla.phpt&amp;quot;);&lt;br /&gt;$paginador=new Template(&amp;quot;plantillas/paginador.phpt&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ahora en nuestra plantilla principal añadimos debajo de la tabla:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?=$PAGINADOR?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;y en nuestro código PHP haremos:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;$miPlantilla-&amp;gt;set("PAGINADOR",$paginador);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;De esta forma conseguimos incluir el paginador en la plantilla principal de manera elegante.&lt;br /&gt;&lt;br /&gt;A continuación veremos como nos quedaría nuestra plantilla principal:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot content=&amp;quot;text/html; charset=UTF-8&amp;quot; /&gt;&lt;br /&gt;  &amp;lt;title&amp;gt;&amp;lt;?=$TITULO?&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;  &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;  #paginador{&lt;br /&gt;  }&lt;br /&gt;  #paginador a.pagina{&lt;br /&gt;  }&lt;br /&gt;  #paginador a.pagina:hover{&lt;br /&gt;  }&lt;br /&gt;  #paginador a.pagina:visited{&lt;br /&gt;  }&lt;br /&gt;  &amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;thead&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;campo 1&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;campo 2&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;/thead&amp;gt;&lt;br /&gt;    &amp;lt;tbody&amp;gt;&lt;br /&gt;&amp;lt;? foreach($DATOS AS $D): ?&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;?=$D-&gt;CAMPO1?&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;?=$D-&gt;CAMPO2?&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;? endforeach ?&amp;gt;&lt;br /&gt;    &amp;lt;/tbody&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;?=$PAGINADOR?&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si nos fijamos en la sección style he referenciado todos los estilos al id paginador de forma que estos estilos no van a afectar al resto de la página. Tendremos que tener esto en cuenta para no definir ningún otro elemento con id="paginador", ya que los id deben ser únicos.&lt;br /&gt;&lt;br /&gt;Hemos dicho en el anterior post que para indicar la página a mostrar usaríamos la variable $_GET["pagina"]. Por lo que si no está definida tendremos que mostrar la primera página y en caso contrario la que nos indique la variable. Veamos entonces la parte de código PHP:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;$num_por_pagina=10;&lt;br /&gt;$pagina=(isset($_GET["pagina"])?$_GET["pagina"]:1);&lt;br /&gt;$desplazamiento=$num_por_pagina*($pagina-1);&lt;br /&gt;&lt;br /&gt;$miPlantilla=new Template(&amp;quot;plantillas/miPlantilla.phpt&amp;quot;);&lt;br /&gt;$miPlantilla-&amp;gt;set(&amp;quot;TITULO&amp;quot;,&amp;quot;KROWORK: Anotaciones de PHP (página &amp;quot;.$pagina.&amp;quot;)&amp;quot;);&lt;br /&gt;$miPlantilla-&amp;gt;set("PAGINADOR",$paginador=new Template(&amp;quot;plantillas/paginador.phpt&amp;quot;));&lt;br /&gt;&lt;br /&gt;list($num)=mysql_fetch_row($result=mysql_query(&amp;quot;SELECT COUNT(*) FROM mitabla&amp;quot));&lt;br /&gt;mysql_free_result($result);&lt;br /&gt;&lt;br /&gt;$paginador-&amp;gt;set("NUM_PAGINAS", ceil($num/num_por_pagina) );&lt;br /&gt;&lt;br /&gt;$result=mysql_query(&lt;br /&gt; &amp;quot;SELECT micampo1 as CAMPO1, micampo2 as CAMPO2 FROM mitabla LIMIT &amp;quot;.$desplazamiento.&amp;quot;,&amp;quot;.$num_por_pagina&lt;br /&gt; );&lt;br /&gt;while($obj=mysql_fetch_object($result)) $miPlantilla-&amp;gt;setArray(&amp;quot;DATOS&amp;quot;,$obj);&lt;br /&gt;&lt;br /&gt;$miPlantilla-&amp;gt;dump();&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Es sencillo, legible y tenemos separada la parte de presentación de la lógica de la aplicación.&lt;br /&gt;&lt;br /&gt;Otra mejora sería cambiar en la plantilla del paginador el &lt;strong&gt;src&lt;/strong&gt; de las imágenes que hacen de botones de "página siguiente" y "página anterior" por dos variables. Si usamos, por ejemplo $URL_FLECHA_IZQUIERDA y $URL_FLECHA_DERECHA, podremos especificar distintas imágenes según el script que use la plantilla y además evitamos problemas con las rutas como sucedía con el include de la plantilla paginador en la principal.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-2348120504274376265?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/2348120504274376265/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=2348120504274376265' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/2348120504274376265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/2348120504274376265'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/12/plantillas-en-php-iv.html' title='Plantillas en PHP (IV)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-1393009934304241275</id><published>2007-12-17T11:37:00.000Z</published><updated>2007-12-20T16:06:49.978Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='plantillas'/><title type='text'>Plantillas en PHP (III)</title><content type='html'>En los dos anteriores artículos hemos definido un modo de crear plantillas utilizando el motor PHP y hemos visto un pequeño ejemplo de uso. En este post mostraré como realizar una plantilla más elaborada a partir de la que ya hemos visto añadiéndole una plantilla paginador.&lt;br /&gt;&lt;div class=fullpost&gt;&lt;br /&gt;Siguiendo con el ejemplo de los anteriores post, si tenemos muchos registros en la base de datos deberíamos dividir su visualización en páginas. Para navegar entre ellas podemos poner unos botones de &lt;em&gt;"alante"&lt;/em&gt; y &lt;em&gt;"atrás"&lt;/em&gt; o poner un paginador. Un paginador muestra los enlaces a las primeras páginas, a las vecinas de la actual y a las últimas páginas, además de los botones "anterior" y "siguiente".&lt;br /&gt;&lt;br /&gt;Para probar esta plantilla sólo tendremos que cargarla con un objeto Template y establecer la variable NUM_PAGINAS:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;include "/classes/Template.class.php";&lt;br /&gt;&lt;br /&gt;$tmplt=new Template("platillas/paginador.phpt");&lt;br /&gt;$tmplt-&gt;set("NUM_PAGINAS",20);&lt;br /&gt;@$tmplt-&gt;dump();&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;La plantilla en cuestión es la siguiente, aunque el código es muy complejo no es necesario entenderlo para usarla, como ya hemos visto:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?&lt;br /&gt;$CENTRO=2;  //numero de paginas a cada lado de la página seleccionada     ...k-2,k-1,k,k+1,k+2...&lt;br /&gt;$LADO=3; //número de primeras paginas 1,2,3... y de ultimas...n-2, n-1, n&lt;br /&gt;&lt;br /&gt;//Preparamos la URL siguiente&lt;br /&gt;$PAGINA=(empty($_GET["pagina"])?1:$_GET["pagina"]);&lt;br /&gt;unset($_GET["pagina"]);&lt;br /&gt;$URL_PAGINA=$_SERVER["PHP_SELF"]."?".http_build_query($_GET);&lt;br /&gt;?&amp;gt;&lt;br /&gt;&amp;lt;div id="paginas"&amp;gt;&lt;br /&gt;&amp;lt;? if($NUM_PAGINAS&amp;gt;1): ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- BOTON PAGINA ANTERIOR --&amp;gt;&lt;br /&gt; &amp;lt;? if($PAGINA&amp;gt;1): ?&amp;gt;&lt;br /&gt;  &amp;lt;a href="&amp;lt;?=$URL_PAGINA?&amp;gt;&amp;amp;amp;pagina=&amp;lt;?=($PAGINA-1)?&amp;gt;" class="pagina"&amp;gt;&lt;br /&gt;   &amp;lt;img src="imagenes/flecha_izq" alt="Página anterior" /&amp;gt;&lt;br /&gt;  &amp;lt;/a&amp;gt;&lt;br /&gt; &amp;lt;? endif ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--  ENLACES A LAS  PRIMERAS PAGINAS --&amp;gt;&lt;br /&gt; &amp;lt;? for($i=1;$i&amp;lt;$LADO+1 &amp;&amp; $i&amp;lt;$NUM_PAGINAS+1 &amp;&amp; $i&amp;lt;$PAGINA-$CENTRO;$i++): ?&amp;gt;&lt;br /&gt;  &amp;lt;a href="&amp;lt;?=$URL_PAGINA?&amp;gt;&amp;amp;amp;pagina=&amp;lt;?=$i?&amp;gt;" class="pagina"&amp;gt;&lt;br /&gt;   &amp;lt;?=$i?&amp;gt;&lt;br /&gt;  &amp;lt;/a&amp;gt;&lt;br /&gt; &amp;lt;? endfor ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- SEPARADOR --&amp;gt;&lt;br /&gt; &amp;lt;? if( $PAGINA&amp;gt;$LADO+$CENTRO+1 ): ?&amp;gt;&lt;br /&gt;  ...&lt;br /&gt; &amp;lt;? endif ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- PAGINAS VECINAS A LA ACTUAL --&amp;gt;&lt;br /&gt; &amp;lt;? for( $i=((($PAGINA-$CENTRO)&amp;gt;0)?($PAGINA-$CENTRO):1); $i&amp;lt;$NUM_PAGINAS+1 &amp;&amp; $i&amp;lt;$PAGINA+$CENTRO+1; $i++ ): ?&amp;gt;&lt;br /&gt;  &amp;lt;? if($i==$PAGINA): ?&amp;gt;&lt;br /&gt;   &amp;lt;?=$i?&amp;gt;&lt;br /&gt;  &amp;lt;? else: ?&amp;gt;&lt;br /&gt;   &amp;lt;a href="&amp;lt;?=$URL_PAGINA?&amp;gt;&amp;amp;amp;pagina=&amp;lt;?=$i?&amp;gt;" class="pagina"&amp;gt;&lt;br /&gt;    &amp;lt;?=$i?&amp;gt;&lt;br /&gt;   &amp;lt;/a&amp;gt;&lt;br /&gt;  &amp;lt;? endif ?&amp;gt;&lt;br /&gt; &amp;lt;? endfor ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- SEPARADOR --&amp;gt;&lt;br /&gt; &amp;lt;? if($NUM_PAGINAS&amp;gt;$PAGINA+$CENTRO+$LADO): ?&amp;gt;&lt;br /&gt;  ...&lt;br /&gt; &amp;lt;? endif ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- ENLACES A LAS ULTIMAS PAGINAS --&amp;gt;&lt;br /&gt; &amp;lt;? if( $NUM_PAGINAS&amp;gt;$PAGINA+$CENTRO ): ?&amp;gt;&lt;br /&gt;  &amp;lt;? for( $i=((($NUM_PAGINAS-$LADO+1)&amp;lt;=($PAGINA+$CENTRO))?($PAGINA+$CENTRO+1):($NUM_PAGINAS-$LADO+1)); $i&amp;lt;$NUM_PAGINAS+1; $i++ ): ?&amp;gt;&lt;br /&gt;   &amp;lt;a href="&amp;lt;?=$URL_PAGINA?&amp;gt;&amp;amp;amp;pagina=&amp;lt;?=$i?&amp;gt;" class="pagina"&amp;gt;&lt;br /&gt;    &amp;lt;?=$i?&amp;gt;&lt;br /&gt;   &amp;lt;/a&amp;gt;&lt;br /&gt;  &amp;lt;? endfor ?&amp;gt;&lt;br /&gt; &amp;lt;? endif ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- BOTON PAGINA SIGUIENTE --&amp;gt;&lt;br /&gt; &amp;lt;? if($PAGINA&amp;lt;$NUM_PAGINAS): ?&amp;gt;&lt;br /&gt;  &amp;lt;a href="&amp;lt;?=$URL_PAGINA?&amp;gt;&amp;amp;amp;pagina=&amp;lt;?=($PAGINA+1)?&amp;gt;" class="pagina"&amp;gt;&lt;br /&gt;   &amp;lt;img src="imagenes/flecha_der.gif" alt="Página siguiente" /&amp;gt;&lt;br /&gt;  &amp;lt;/a&amp;gt;&lt;br /&gt; &amp;lt;? endif ?&amp;gt;&lt;br /&gt;&amp;lt;? endif ?&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Como es de espera estaremos accediendo al script que muestra la lista a través de una llamada GET. La plantilla se encarga de regenerar la URL de esta llamada (con todas sus variables) añadiendo la variable "pagina" para indicar(obviamente) la página a la que se desea acceder. Esto estrictamente no debería estar en la plantilla y la variable URL_PAGINA deberíamos establecerla nosotros desde fuera de la plantilla, pero vamos a utilizar este atajo ya que tenemos las funciones PHP a nuestra disposición y esto nos simplifica mucho las cosas.&lt;br /&gt;&lt;br /&gt;¿Pero como incluirla en la plantilla de la lista? Pues con un include, pero esto y otros detalles sobre los CSS de la plantilla lo dejamos para el próximo post.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-1393009934304241275?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/1393009934304241275/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=1393009934304241275' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/1393009934304241275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/1393009934304241275'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/12/plantillas-en-php-iii.html' title='Plantillas en PHP (III)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-5701807482572348001</id><published>2007-12-13T17:03:00.001Z</published><updated>2007-12-20T16:12:25.263Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='plantillas'/><title type='text'>Plantillas en PHP (II)</title><content type='html'>Hemos visto en el anterior post que no es necesario aprender la sintaxis de ningún lenguaje de plantillas para poder trabajar con ellas. Una sintaxis reducida del PHP será más que suficiente para disfrutar de sus ventajas.&lt;br /&gt;&lt;div class=fullpost&gt;&lt;br /&gt;En este post vamos a definir la clase Template; a través de un objeto de esta clase se carga la plantilla y se le da valores a las variables:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;class Template{&lt;br /&gt;    private $VARS=array();&lt;br /&gt;    private $archivo;&lt;br /&gt;&lt;br /&gt;    function __construct($archivo){&lt;br /&gt;        $this-&amp;gt;archivo=$archivo;&lt;br /&gt;    }&lt;br /&gt;    //establecemos las variables simples de la plantilla&lt;br /&gt;    public function set($nombre,$valor){&lt;br /&gt;        if($valor===NULL) unset($this-&amp;gt;VARS[$nombre]);&lt;br /&gt;        else $this-&amp;gt;VARS[$nombre]=$valor;&lt;br /&gt;    }&lt;br /&gt;    public function setArray($nombre,$valor){&lt;br /&gt;        if(empty($this-&amp;gt;VARS[$nombre])) $this-&amp;gt;VARS[$nombre]=array();&lt;br /&gt;        $this-&amp;gt;VARS[$nombre][]=$tmp;&lt;br /&gt;    }&lt;br /&gt;    public function get($nombre){&lt;br /&gt;        return $this-&amp;gt;VARS[$nombre];&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public function dump($buffer=false){&lt;br /&gt;        if($buffer) ob_start();&lt;br /&gt;        if(!empty($this-&amp;gt;VARS)) foreach($this-&amp;gt;VARS as $variable=&amp;gt;&amp;$valor)&lt;br /&gt;            $$variable=$valor;&lt;br /&gt;        include($this-&amp;gt;archivo);&lt;br /&gt;        if($buffer) return ob_get_clean();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    function __clone() {&lt;br /&gt;        foreach($this-&amp;gt;VARS as $k=&amp;gt;$v)&lt;br /&gt;            if(is_object($v)) $this-&amp;gt;VARS[$k]=clone $this-&amp;gt;VARS[$k];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Veamos como utilizarla. Supongamos que hemos guardado la plantilla del anterior post en el archivo "miPlantilla.phpt" si queremos ponerle el título solo tendremos que hacer:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;$miPlantilla=new Template(&amp;quot;plantillas/miPlantilla.phpt&amp;quot;);&lt;br /&gt;$miPlantilla-&amp;gt;set(&amp;quot;TITULO&amp;quot;,&amp;quot;KROWORK: Anotaciones de PHP&amp;quot;);&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ahora veamos como crear el array $DATOS de la plantilla a partir de una consulta a la base de datos: &lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;$result=mysql_query(&amp;quot;SELECT micampo1 as CAMPO1, micampo2 as CAMPO2 FROM mitabla&amp;quot;);&lt;br /&gt;while($obj=mysql_fetch_object($result)) $miPlantilla-&amp;gt;setArray(&amp;quot;DATOS&amp;quot;,$obj);&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Y por último mostramos los datos:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;@$miPlantilla-&amp;gt;dump();&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Utilizamos @ para ocultar los posibles errores/warnings de la plantilla, ya que va a ser habitual que para simplificar comprobemos la existencia de las varibles con una expresión del tipo: &amp;lt;? if($VAR): ?&amp;gt; ... &amp;lt;? endif ?&amp;gt;. Si no hemos definido $VAR se producirá un warning que de esta forma no se mostrará aunque tengamos el reporte de errores al máximo. Evidentemente mientras probamos la plantilla no pondremos la @ para poder detectar los errores.&lt;br /&gt;&lt;br /&gt;Como dije en el post anterior, no es raro crear plantillas con archivos xml's. La construcción de un xml nodo a nodo a través de la extensión DOM de PHP es  enormemente tediosa. Una forma mucho más fácil de hacerlo es creando una plantilla (ojo: si utilizas short tags deberás hacer uso del truco del post anterior), rellenarla y al final:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;file_put_contents("mi_nuevo_archivo.xml",$miPlantilla-&amp;gt;dump(true));&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Al pasar true al método dump() hacemos que en lugar de mostrarse el resultado se devuelva en forma de string.&lt;br /&gt;&lt;br /&gt;Como vemos las plantillas son muy versátiles, muy fácil de usarlas, de crearlas y al estar escritas en PHP su procesamiento es de lo más rápido que os podais encontrar.  Hasta la próxima.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-5701807482572348001?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/5701807482572348001/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=5701807482572348001' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/5701807482572348001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/5701807482572348001'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/12/plantillas-en-php-ii.html' title='Plantillas en PHP (II)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-4100891373193123925</id><published>2007-11-16T15:08:00.000Z</published><updated>2007-12-13T22:24:27.384Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='problemas'/><category scheme='http://www.blogger.com/atom/ns#' term='plantillas'/><title type='text'>Plantillas en PHP (I)</title><content type='html'>Tras siglos desde mi último post me he decidido a retomar mis escritos con otra serie dedicada a las plantillas. Este primer artículo lo dedicaré a dar una visión general sobre el tema, veremos porqué son útiles y en qué nos ayudan. En los post siguientes propondré una implementación propia de un sistema de plantillas.&lt;br /&gt;&lt;br /&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;Mucha gente, entre la que me incluyo, empezó a programar PHP como un lenguaje de scripting insertado dentro del código HTML. Resultaba muy intuitivo extender las funcionalidades de tu página incluyendo pequeños trozos de código PHP.&lt;br /&gt;&lt;br /&gt;El problema surgió cuando a medida que añadimos más funcionalidades el código de nuestras páginas se convierte en &lt;em&gt;El Laberinto del Minotauro&lt;/em&gt;. Encontrar y corregir errores tanto HTML/JavaScript como PHP se hace enormemente tedioso al tener todo el código mezclado. Este tipo de escritura de código es altamente interdependiente además de compartir lógica y presentación la mismas variables.&lt;br /&gt;Esta situación es mala de cara a la gestión de errores, mala frente a futuras modificaciones, mala porque no podemos aprovechar código de un proyecto a otro y mala porque no podemos dividir el trabajo entre diseñador y programador. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;¿Como hacer código menos interdependiente?&lt;/h4&gt;&lt;br /&gt;Pensemos como sería una pagina HTML con el mínimo código PHP, para representar el típico resultado de una búsqueda en nuestra base de datos:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot content=&amp;quot;text/html; charset=UTF-8&amp;quot; /&gt;&lt;br /&gt;  &amp;lt;title&amp;gt;&amp;lt;?=$TITULO?&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;thead&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;campo 1&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;campo 2&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;/thead&amp;gt;&lt;br /&gt;    &amp;lt;tbody&amp;gt;&lt;br /&gt;&amp;lt;? foreach($DATOS AS $D): ?&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;?=$D-&gt;CAMPO1?&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;?=$D-&gt;CAMPO2?&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;? endforeach ?&amp;gt;&lt;br /&gt;    &amp;lt;/tbody&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Primero, SÍ, utilizo &lt;strong&gt;short tags&lt;/strong&gt;, para activarlas deberás editar tu &lt;em&gt;php.ini&lt;/em&gt; poniendo &lt;em&gt;short_open_tag=1&lt;/em&gt;. Pero, un momento, seguro que habréis visto en más de un sitio que no se deben utilizar las short tag que son la reencarnación del diablo y otras lindeces, veamos porqué:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;No se deben utilizar las short tags porque producen problemas si queremos hacer un include de un xml. Los archivos xml empiezan con &lt;strong&gt;&amp;lt;?&lt;/strong&gt;xml y por lo tanto el PHP (con short tags activadas) interpreta que ahí empieza un bloque PHP. Esto se soluciona si en lugar de empezar de ese modo el xml lo empezamos así: &lt;strong&gt;&amp;lt;&amp;lt;? ?&amp;gt;?xml &lt;/strong&gt;. ¿Supone esto un gran problema para no hacer uso de las short tags? Cada uno tendrá su opinión.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No es raro hacer un include de un xml sobre todo si vamos a utilizar un sistema de plantillas basado en PHP, que en última instancia hará un include de la plantilla, y si ésta es un xml surgirá el problema.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;A mi personalmente no me parece un gran problema si a cambio puedo utilizar &amp;lt;?= ?&amp;gt; que resulta un gran aliado para legibilidad de las plantillas, en todo caso cada uno es libre de utilizar &amp;lt;?php echo.&lt;br /&gt;&lt;br /&gt;Dicho esto diré también que ya tenemos nuestra primera plantilla PHP. Metan ese código en un archivo, guárdenlo en UTF-8 y pónganle una extensión del tipo &lt;strong&gt;.phpt&lt;/strong&gt;. A partir de ahora diferentes scripts podrán utilizar la misma  plantilla o un mismo script utilizar plantillas diferentes. Además, se requieren unos mínimos conocimientos de PHP para hacer una plantilla por lo que fácilmente podrá hacerlas un diseñador mientras nosotros nos dedicamos a la miga de la aplicación y que se pelee él con el JavaScript, el DOM y las CSS (sí teneis la gran fortuna de tener un buen diseñador a mano).&lt;br /&gt;&lt;br /&gt;Pero, ¿como instanciar esa plantilla y rellenar los huecos? paciencia, lo veremos en la próxima entrada.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-4100891373193123925?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/4100891373193123925/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=4100891373193123925' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/4100891373193123925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/4100891373193123925'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/11/plantillas-en-php-i.html' title='Plantillas en PHP (I)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-5962434939659775642</id><published>2007-05-14T14:21:00.000+01:00</published><updated>2007-11-12T19:48:55.707Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos'/><category scheme='http://www.blogger.com/atom/ns#' term='static'/><category scheme='http://www.blogger.com/atom/ns#' term='sesiones'/><title type='text'>Guardar propiedades static en $_SESSION (IV)</title><content type='html'>En esta tercera parte del artículo veremos la clase ClassStore.&lt;br /&gt;&lt;br /&gt;Cada objeto ClassStore va a servir como un contenedor de las propiedades static de cada una de las clases utilizadas durante la ejecución del script. Todos estos objetos se van a guardar en un array indexado por el nombre de la clase: $_SESSION["__statics"][$nombre_de_la_clase]. El método estático __storeStatics (identico al código visto al final del último post) realiza estas acciones llamando a los métodos __getStatics() de las clases declaradas.&lt;br /&gt;&lt;div class=fullpost&gt;&lt;br /&gt;Para ello debemos hacer una lladama a __storeStatics cuando finalice la ejecución del script:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;register_shutdown_function(array('ClassStore','__storeStatics'));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A continuación la clase ClassStore:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;class ClassStore{&lt;br /&gt; private $nombre;&lt;br /&gt; private $statics;&lt;br /&gt; &lt;br /&gt; function __construct($nombreClase,$statics){&lt;br /&gt;  $this-&gt;nombre=$nombreClase;&lt;br /&gt;  $this-&gt;statics=$statics;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; function __wakeup(){&lt;br /&gt;  call_user_func(array($this-&gt;nombre,'__restoreStatics'),$this-&gt;statics);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; static function __storeStatics(){&lt;br /&gt;  $classes=get_declared_classes();&lt;br /&gt; &lt;br /&gt;  foreach($classes as $name){&lt;br /&gt;   $reflejo=new ReflectionClass($name);&lt;br /&gt; &lt;br /&gt;   if($reflejo-&gt;hasMethod('__getStatics')){&lt;br /&gt;    $method=$reflejo-&gt;getMethod('__getStatics');&lt;br /&gt; &lt;br /&gt;    if($method-&gt;getDeclaringClass()-&gt;getName()===$name){&lt;br /&gt; &lt;br /&gt;     if(empty($_SESSION["__statics"]))&lt;br /&gt;      $_SESSION["__statics"]=array();&lt;br /&gt; &lt;br /&gt;     $_SESSION["__statics"][$name]=new ClassStore($name,call_user_func(array($name,'__getStatics')));&lt;br /&gt;  &lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si nos fijamos bien, cada vez que se recupere la sesion con session_start() el array $_SESSION se deserializa y se reconstruyen los objetos que guarda. Después de reconstruidos se llama al __wakeup de todos aquellos que lo tengan definido. De este modo cada unos de los objetos ClassStore devolverá a su valor anterior las propiedades static de cada una de las clases.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;RECORDEMOS&lt;/strong&gt;: en aquellas clases que queramos mantener estas propiedades debemos definir los métodos __getStatics y __restoreStatics como hemos visto. A continuación, en el script de cabecera, dónde tengamos el autoload de las clases y el session_start() registramos la llamada a la función __storeStatics para cuando finalice el script: register_shutdown_function(array('ClassStore','__storeStatics')). &lt;strong&gt;Y voilá, ya se mantienen las propiedades static&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="paginador"&gt; Ir a... &lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-y-su-seriacin-en.html"&gt;[I]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session.html"&gt;[II]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_11.html"&gt;[III]&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-5962434939659775642?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/5962434939659775642/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=5962434939659775642' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/5962434939659775642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/5962434939659775642'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_14.html' title='Guardar propiedades static en $_SESSION (IV)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-9039383824315306224</id><published>2007-05-11T14:31:00.000+01:00</published><updated>2007-11-12T19:48:19.566Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos'/><category scheme='http://www.blogger.com/atom/ns#' term='static'/><category scheme='http://www.blogger.com/atom/ns#' term='sesiones'/><title type='text'>Guardar propiedades static en $_SESSION (III)</title><content type='html'>Como había dicho en mi anterior post, en éste veremos el API de Reflexión con el que viene provisto el PHP 5.&lt;br /&gt;&lt;br /&gt;Nuestro primer contacto con este API lo hemos tenido cuando definíamos la función __getStatics(), recordemos:&lt;br /&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;static function __getStatics(){&lt;br /&gt; $statics=array();&lt;br /&gt; $reflejo=new ReflectionClass(__CLASS__);&lt;br /&gt; $properties=$reflejo-&gt;getProperties();&lt;br /&gt;&lt;br /&gt; foreach($properties as $p) if($p-&gt;isStatic() &amp;&amp; &lt;br /&gt;  $p-&gt;getDeclaringClass()-&gt;getName()===__CLASS__ ) {&lt;br /&gt;&lt;br /&gt;  $nombre=$p-&gt;getName();&lt;br /&gt;  $valor=self::$$nombre;&lt;br /&gt;  if(!is_resource($valor)) $statics[$nombre]=$valor;&lt;br /&gt; }&lt;br /&gt; return $statics;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Como vemos el API nos sirve para obtener información de las clases que hay definidas. En este caso obtenemos el objeto ReflectionClass que representa a la clase en la que está definido éste método. El método getProperties() nos devuelve todas las propiedades en un array de objetos ReflectionProperty que representa a cada una de las propiedades de la clase.&lt;br /&gt;&lt;br /&gt;Este array nos devuelve TODAS las propiedades, incluso las heredadas, por lo que tenemos que hacer una criba y seleccionar únicamente aquellas que están declaradas directamente en la clase, que sean static y no sean un recurso (ya que no tiene sentido guardarlos de una ejecucion a otra).&lt;br /&gt;&lt;br /&gt;Como habíamos dicho éste método debemos definirlo en todas aquellas clases en las que queramos mantener valores static de una ejecución a otra del script, ahora bien debemos ver como llamar a este método de una forma automatizada:&lt;br /&gt;&lt;pre class="prettyprint"&gt;$classes=get_declared_classes();&lt;br /&gt; &lt;br /&gt;foreach($classes as $name){&lt;br /&gt;  $reflejo=new ReflectionClass($name);&lt;br /&gt; &lt;br /&gt;  if($reflejo-&gt;hasMethod('__getStatics')){&lt;br /&gt;    $method=$reflejo-&gt;getMethod('__getStatics');&lt;br /&gt; &lt;br /&gt;    if($method-&gt;getDeclaringClass()-&gt;getName()===$name){&lt;br /&gt; &lt;br /&gt;     if(empty($_SESSION["__statics"]))&lt;br /&gt;      $_SESSION["__statics"]=array();&lt;br /&gt; &lt;br /&gt;     $_SESSION["__statics"][$name]=new ClassStore($name,call_user_func(array($name,'__getStatics')));&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para cada una de las clases declaradas en el script comprobamos cuales de ellas tienen definido el método __getStatics (no heredado). Para cada una de esas clases se crea un objeto ClassStore al que se le pasan el array de valores de las propiedades static. Cada uno de estos objetos se guarda en $_SESSION["__statics"].&lt;br /&gt;&lt;br /&gt;En el siguiente post veremos el objet ClassStore, que automatizará la recuperación de los datos de las propiedades static.&lt;br /&gt;&lt;br /&gt;&lt;div class="paginador"&gt; Ir a... &lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-y-su-seriacin-en.html"&gt;[I]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session.html"&gt;[II]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_14.html"&gt;[IV]&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-9039383824315306224?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/9039383824315306224/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=9039383824315306224' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/9039383824315306224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/9039383824315306224'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_11.html' title='Guardar propiedades static en $_SESSION (III)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-1954128123460309117</id><published>2007-05-10T22:23:00.000+01:00</published><updated>2007-11-12T19:47:53.304Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='soluciones'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos'/><category scheme='http://www.blogger.com/atom/ns#' term='static'/><category scheme='http://www.blogger.com/atom/ns#' term='sesiones'/><title type='text'>Guardar propiedades static en $_SESSION (II)</title><content type='html'>Como contaba en mi anterior entrada al contrario del resto de propiedades de un objeto (almacenado en el array $_SESSION) las static, por pertenecer a la clase y no al objeto, no se recuperan con la llamada a la función session_start(). Exprimiendo un poco el coco llegué a una solución bastante eficiente y poco sangrante.&lt;div class=fullpost&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;¿A que me refiero con poco sangrante?&lt;/h4&gt;Cuando se está buscando un parche, como en este caso, siempre hay que tragar con unas cuantas líneas de código extra. Lo más importante es que éste resulte localizable y que sea fácil de eliminar llegado el caso. El código que propongo se compone de una clase extra que actuará independientemente, y de dos método "mágicos" en cada clase que tenga propiedades static que deseemos mantener en session. Estos métodos son iguales para todas y son muy simples:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;static function __restoreStatics($statics){&lt;br /&gt; foreach($statics as $nombre=&gt;$valor)&lt;br /&gt;  self::$$nombre=$valor;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;static function __getStatics(){&lt;br /&gt; $statics=array();&lt;br /&gt; $reflejo=new ReflectionClass(__CLASS__);&lt;br /&gt; $properties=$reflejo-&gt;getProperties();&lt;br /&gt;&lt;br /&gt; foreach($properties as $p) if($p-&gt;isStatic() &amp;&amp; &lt;br /&gt;  $p-&gt;getDeclaringClass()-&gt;getName()===__CLASS__ ) {&lt;br /&gt;&lt;br /&gt;  $nombre=$p-&gt;getName();&lt;br /&gt;  $valor=self::$$nombre;&lt;br /&gt;  if(!is_resource($valor)) $statics[$nombre]=$valor;&lt;br /&gt; }&lt;br /&gt; return $statics;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h4&gt;¿Por qué son imprescindible estos métodos?&lt;/h4&gt;Sólo un método de la propia clase puede acceder las propiedades private y protected (en las primeras versiones, PHP 5 no era tan estricto). Cualquier posible solución tiene que contar con dos métodos definido en aquellas clases con propiedades static que queramos conservar.&lt;br /&gt;&lt;strong&gt;Ojo&lt;/strong&gt;: estos métodos no pueden ser heredados, hay que definirlos &lt;strong&gt;para cada clase&lt;/strong&gt;. Veamos como funcionan:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;El método __getStatics apollado en un objeto ReflectionClass obtiene los atributos static de la clase (objetos ReflectionProperty). Comprueba que no se trata ni de un atributo heredado ni de un recurso y devuelve un array asociativo indexado por el nombre de cada atributo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;El método __restoreStatics hace lo contrario, se le pasa el array de statics y vuelve establecer los atributos a los valores dados.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;Por lo dicho ya vemos que el método __getStatics debería ser invocado cuando se finalice el script, almacenando el resultado que obtengamos para cada clase. Al contrario, el método __restoreStatics será llamado cuando se inicie la ejecución del script. Si prefieres puedes ver estos dos métodos como dos más de los "métodos mágicos", como __sleep o __wakeup, así no suena tan mal.&lt;br /&gt;&lt;br /&gt;Con estos dos métodos ya casi tenemos solucionado todo el problema. En el siguiente post veremos con más detalle la API de Reflexión que parece va adquiriendo importancia en este problema.&lt;br /&gt;&lt;br /&gt;Hasta el próximo&lt;br /&gt;&lt;div class="paginador"&gt; Ir a... &lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-y-su-seriacin-en.html"&gt;[I]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_11.html"&gt;[III]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_14.html"&gt;[IV]&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-1954128123460309117?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/1954128123460309117/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=1954128123460309117' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/1954128123460309117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/1954128123460309117'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session.html' title='Guardar propiedades static en $_SESSION (II)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-4987791544113820038</id><published>2007-05-10T14:37:00.000+01:00</published><updated>2007-11-12T19:47:22.917Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='problemas'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos'/><category scheme='http://www.blogger.com/atom/ns#' term='static'/><category scheme='http://www.blogger.com/atom/ns#' term='sesiones'/><title type='text'>Guardar propiedades static en $_SESSION (I)</title><content type='html'>Hechas las presentaciones empezamos en esta entrada con la primera de una serie de articulos dedicados a resolver el problema de como guardar las propiedades static de las clases en PHP 5 (OJO: utilizaremos funciones que no existen en PHP4).&lt;br /&gt;&lt;br /&gt;Como es sabido en PHP cuando se finaliza la ejecución de un script el motor PHP seria(serializa) todo el array $_SESSION, para almacenarlo en un fichero; si hay objetos en su interior también los seria, guardando el valor de todas sus propiedades (public, private o protected). El resultado sería el mismo que el que se obtiene con la función serialize():&lt;br /&gt;&lt;br /&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;session_start();&lt;br /&gt; &lt;br /&gt;class Foo{&lt;br /&gt;  static $propiedad;&lt;br /&gt; &lt;br /&gt;  function __construct(){&lt;br /&gt;   self::$propiedad=4;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;$_SESSION['obj']=new Foo();&lt;br /&gt;$datos=serialize($_SESSION['obj']);&lt;br /&gt;echo $datos;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Cuando se vuelve a ejecuta la funcion session_start() se reconstruye el array $_SESSION a partir del fichero. Problema: los cambios producidos en las propiedades static de la clase durante la ejecución anterior del script se pierden. Esto se debe a que sólo se guarda información del objeto y no de la clase.&lt;br /&gt;&lt;br /&gt;Es posible que en futuras versiones de PHP este problema se solucione y quizá este sea el motivo más importante para buscar una solución temporal que nos permita trabajar en el paradigma que utilicemos con PHP6. De este modo podremos desarrollar un mayor potencial en nuestros diseños (podría extenderme sobre los problemas de esta limitación pero si estás leyendo esto seguramente ya te habrás enfrentado a alguno) y si en un futuro se soluciona sólo tendremos que borrar unas pocas líneas de código.&lt;br /&gt;&lt;br /&gt;En la próxima entrada empezaré a discutir mi solución al problema, procuparé no demorarme mucho.&lt;br /&gt;&lt;div class="paginador"&gt; Ir a... &lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session.html"&gt;[II]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_11.html"&gt;[III]&lt;/a&gt;&lt;a href="http://krowork.blogspot.com/2007/05/propiedades-static-seriadas-en-session_14.html"&gt;[IV]&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-4987791544113820038?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/4987791544113820038/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=4987791544113820038' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/4987791544113820038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/4987791544113820038'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/propiedades-static-y-su-seriacin-en.html' title='Guardar propiedades static en $_SESSION (I)'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-6515248660887587577</id><published>2007-05-09T14:18:00.001+01:00</published><updated>2007-05-09T20:16:13.624+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KROWORK'/><title type='text'>¿Para qué este blog?</title><content type='html'>Antes que nada diré que no pretendo dar lecciones de PHP a nadie y no quiero que nadie se sienta agredido si meto la pata o no soy del todo estricto. Soy un programador web que quiere tener un espacio donde dejar sus anotaciones y reflexiones sobre PHP. Si estas anotaciones pudieran servir de algo a alguien será una satisfacción extra.&lt;br /&gt;&lt;br /&gt;Ahora bien, que todo el mundo se sienta libre de hacer sus comentarios, correcciones o críticas, éstas &lt;strong&gt;siempre&lt;/strong&gt; serán bienvenidas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-6515248660887587577?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/6515248660887587577/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=6515248660887587577' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/6515248660887587577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/6515248660887587577'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/para-qu-este-blog.html' title='¿Para qué este blog?'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9182126501089271480.post-6196195143451714430</id><published>2007-05-08T23:26:00.000+01:00</published><updated>2007-05-11T15:26:28.107+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KROWORK'/><title type='text'>¿Por qué KROWORK?</title><content type='html'>Mi primera entrada en este blog creía que debía estar dedicada a explicar su nombre.&lt;br /&gt;&lt;br /&gt;KROWORK es un mantra, un grito de guerra, una palabra mágica, un &lt;strong&gt;palíndromo&lt;/strong&gt;,un trabalenguas, una palabra cacofónica. Las había mejores, pero no eran mías (algún día explicaré por qué). Por lo de pronto fijaros que he remarcado &lt;strong&gt;palíndromo&lt;/strong&gt; (empieza al contrario de como acaba) luego no digais que os cuesta escribirlo bien.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182126501089271480-6196195143451714430?l=krowork.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krowork.blogspot.com/feeds/6196195143451714430/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9182126501089271480&amp;postID=6196195143451714430' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/6196195143451714430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9182126501089271480/posts/default/6196195143451714430'/><link rel='alternate' type='text/html' href='http://krowork.blogspot.com/2007/05/por-qu-krowork.html' title='¿Por qué KROWORK?'/><author><name>Alex</name><uri>http://www.blogger.com/profile/07402704140854701458</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp3.blogger.com/_BDtNNi4Hx6s/SD6uVzm0E-I/AAAAAAAAABs/V9C-V-gqR2k/S220/27062006023.jpg'/></author><thr:total>0</thr:total></entry></feed>
