<?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>dixso.net &#187; PHP</title>
	<atom:link href="http://dixso.net/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://dixso.net</link>
	<description>Desarrollo web</description>
	<lastBuildDate>Fri, 05 Feb 2010 08:09:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Variables en CSS</title>
		<link>http://dixso.net/php/variables-en-css/</link>
		<comments>http://dixso.net/php/variables-en-css/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 11:00:19 +0000</pubDate>
		<dc:creator>Julio</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://dixso.net/?p=201</guid>
		<description><![CDATA[Esta técnica es sencilla, la idea es que Apache redirija cualquier hoja de estilo a un script PHP. Este script abrirá la hoja de estilos y leerá línea por línea para buscar y reemplazar cualquier variable que hayamos definido anteriormente. Por último, el contenido se analiza y se muestra como CSS, además, los navegadores no [...]]]></description>
			<content:encoded><![CDATA[<p>Esta técnica es sencilla, la idea es que Apache redirija cualquier hoja de estilo a un script PHP. Este script abrirá la hoja de estilos y leerá línea por línea para buscar y reemplazar cualquier variable que hayamos definido anteriormente.<br />
Por último, el contenido se analiza y se muestra como CSS, además, los navegadores no notarán la diferencia.<br />
También veremos cómo procesaremos este script en cache para evitar el mal uso de memoria en la CPU.</p>
<p>Requisitos:<br />
    * Apache con Rewrite mod on (Activado).<br />
    * PHP 5<br />
<span id="more-201"></span><br />
<strong>Paso 1 &#8211; Crear el Proyecto</strong><br />
Añadimos html simple en nuestra hoja que la llamaremos &#8216;index.html&#8217;:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;title&gt;Variables en CSS... Si, es posible!&lt;/title&gt;
    &lt;link href=&quot;css/styles.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;Variables en las hojas de estilo&lt;/h1&gt;
    &lt;p&gt;Es posible!&lt;/p&gt;
    &lt;p&gt;Con PHP / Apache y URL Rewrite Mod&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Ahora creamos la hoja de estilos:</p>
<pre class="brush: css;">
$font:arial, sans-serif;
$main-color:#3D7169; $secondary-color:#000;

h1 {
    font: 200% $font;
    color:$main-color;
}
p {
    background:$secondary-color;
    color:$main-color;
    font-family:$font;
    padding:10px;
}
</pre>
<p><strong>Paso 2 &#8211; Redireccionar los ficheros CSS a nuestro script PHP</strong><br />
Añadimos en nuestro fichero .htaccess lo siguiente:</p>
<pre class="brush: xml;">
RewriteEngine on
RewriteRule ^(.*\.css)$ enhanced_css.php?css=$0
</pre>
<p>Estas líneas que hemos insertamos en nuestra hoja ‘.htaccess’ cogerá la URL con extensión .css y la re-direccionará al fichero enhanced_css.php</p>
<p>Por ejemplo:<br />
/css/styles.css </p>
<p>Va a redirigir a:<br />
enhanced_css.php?css=/css/styles.css</p>
<p>Nota:<br />
En algunos proveedores de hosting no están permitidos los .htaccess por cuestiones de seguridad, si se da este caso habrá que editar manualmente la llamada a la hoja de estilos, es decir, cambiar esto:</p>
<pre class="brush: xml;">
&lt;link href=&quot;css/styles.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
</pre>
<p>Por esto otro:</p>
<pre class="brush: xml;">
&lt;link href=&quot;enhanced_css?css=css/styles.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
</pre>
<p><strong>Paso 3 &#8211; Analizar el archivo CSS con PHP</strong><br />
Dado que los archivos CSS se redirigen a nuestro script PHP, vamos a construir una clase llamada &#8220;Enhancedcss&#8221; para leer, buscar y reemplazar las variables y, a continuación, mostrar el contenido CSS.<br />
Nuestra clase se instancia mediante la aprobación de $_GET['css'].</p>
<pre class="brush: php;">
if (isset($_GET['css'])) {
    $css = new EnhancedCss($_GET['css']);
    $css-&gt;display();
}
</pre>
<p>La aplicación básica de la clase se compone de cuatro métodos. Más tarde, añadiremos un método de almacenamiento en caché.</p>
<pre class="brush: php;">
class EnhancedCss {
    public $values;
    public $cssFile;

    public function __construct($cssFile) {
        // Comprueba que la hoja de estilos existe.
    }

    private function parse() {
        // Abre la hoja de estilos y comprueba línea a línea .
        // Utilizando el método findAndReplaceVars
    }

    private function findAndReplaceVars($line) {
        // Encuentra las variables definidas, almacena los valores.
        // Remplaza las variables definidas.
    }

    public function display() {
        // Muestra el nuevo contenido analizado.
    }
}
</pre>
<p><strong>El contenedor</strong><br />
Comprobamos si el archivo CSS existe, si no, la secuencia de comandos devuelve un error HTTP 404.<br />
La ruta de la hoja de estilos se mantiene en la propiedad &#8216;$this->cssFile&#8217; que se utiliza para calcular el nombre del archivo en la caché más tarde.</p>
<p><strong>Analizamos el método</strong><br />
Este método abre el archivo CSS y lee línea por línea.</p>
<pre class="brush: php;">
private function parse() {
    $content = '';
    $lines = file($this-&gt;cssFile);
    foreach($lines as $line) {
        $content .= $this-&gt;findAndReplaceVars($line);
    }
    return $content;
}
</pre>
<p>La función que se utiliza está <a target="_blank" href="http://php.net/manual/es/function.file.php">aquí</a>. Lo cierto es que puede ser útil, ya que abre un archivo y devuelve el contenido en una array.</p>
<p><strong>El método &#8216;FindAndReplace&#8217;</strong><br />
Este método es el principal, busca las variables definidas.  Cuando encuentra una variable y tiene valor, entonces, la substituye.</p>
<pre class="brush: php;">
private function findAndReplaceVars($line) {
    preg_match_all('/\s*\\$([A-Za-z1-9_\-]+)(\s*:\s*(.*?);)?\s*/', $line, $vars);
    $found     = $vars[0];
    $varNames  = $vars[1];
    $varValues = $vars[3];
    $count     = count($found);    

    for($i = 0; $i &lt; $count; $i++) {
        $varName  = trim($varNames[$i]);
        $varValue = trim($varValues[$i]);
        if ($varValue) {
            $this-&gt;values[$varName] = $this-&gt;findAndReplaceVars($varValue);
        } else if (isset($this-&gt;values[$varName])) {
            $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this-&gt;values[$varName].'\\1', $line);
        }
    }
    $line = str_replace($found, '', $line);
    return $line;
}
</pre>
<p>Revisamos el código paso a paso:</p>
<pre class="brush: php;">
private function findAndReplaceVars($line) {
    preg_match_all('/\s*\\$([A-Za-z1-9_\-]+)(\s*:\s*(.*?);)?\s*/', $line, $vars);
</pre>
<p>En este sentido, aplicamos una expresión regular en la línea actual. Esta expresión concuerda con los patrones y extrae como $variable:$value; (y algunas variantes) o $variable en la línea actual. Las expresiones regulares son un tema complejo que merece un tutorial de los suyos. <a href="http://es2.php.net/manual/es/function.preg-match-all.php" target="_blank">Aquí</a> tenéis más información al respecto.</p>
<p>Por ejemplo, la tercera línea de la hoja de estilos:<br />
$main-color: #3D7169; $secondary-color: #000;</p>
<p>Devolverá esta array:</p>
<pre class="brush: php;">
$vars =&gt; Array
(
    [0] =&gt; Array
        (
            [0] =&gt; $main-color: #3D7169;
            [1] =&gt; $secondary-color: #000;
        )

    [1] =&gt; Array
        (
            [0] =&gt; main-color
            [1] =&gt; secondary-color
        )

    [2] =&gt; Array
        (
            [0] =&gt;  : #3D7169;
            [1] =&gt;  : #000;
        )

    [3] =&gt; Array
        (
            [0] =&gt;  #3D7169
            [1] =&gt;  #000
        )
)
</pre>
<p>Supongamos que $vars[0] contiene todo, $vars[1] contiene los nombres de las variables y $vars[3] contiene los valores.</p>
<pre class="brush: php;">
$found     = $vars[0];
$varNames  = $vars[1];
$varValues = $vars[3];
</pre>
<p>Concretamente así:</p>
<pre class="brush: php;">
$found =&gt; Array
        (
            [0] =&gt; $main-color: #3D7169;
            [1] =&gt; $secondary-color: #000;
        )
$varNames =&gt; Array
        (
            [0] =&gt; main-color
            [1] =&gt; secondary-color
        )
 $varValues =&gt; Array
       (
           [0] =&gt;  #3D7169
           [1] =&gt;  #000
       )
</pre>
<p>Contamos el número de variables que se han encontrado en la línea actual.</p>
<pre class="brush: php;">
$count = count($found);
</pre>
<p>Hacemos la condición:</p>
<pre class="brush: php;">
for($i = 0; $i &lt; $count; $i++) {
    $varName  = trim($varNames[$i]);
    $varValue = trim($varValues[$i]);            

    // ...
}
</pre>
<p><strong>Definiciones de las variables</strong><br />
Si $varValue no está vacía, tenemos una variable definida. Así que se almacena en $this->values property.</p>
<pre class="brush: php;">
if ($varValue) {
    $this-&gt;values[$varName] = $this-&gt;findAndReplaceVars($varValue);
} else if ...
</pre>
<p>Hay que tener en cuenta que se pasa el valor de la variable en el método ‘findAndReplaceVars’. De este modo, otras variables también podrán ser procesadas.<br />
Los valores se almacenan en $this->values array con el nombre de variable clave.</p>
<pre class="brush: php;">
Array
(
	[font] =&gt; arial, sans-serif
	[main-color] =&gt; #3D7169
	[secondary-color] =&gt; #000
)
</pre>
<p><strong>Aplicaciones de las variables</strong><br />
Comprobamos que esta variable existes en los valores de la array. Si es así, reemplaza la variable por su valor.</p>
<pre class="brush: php;">
} else if (isset($this-&gt;values[$varName])) {
    $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this-&gt;values[$varName].'\\1', $line);
}
</pre>
<p>Esta sustitución podría parecer demasiado complicada. En realidad no, esta sustitución se hace cargo de $variable solo si es seguido por un carácter o un final de línea. </p>
<p>Por último, procesa la línea y es devuelta.</p>
<pre class="brush: php;">
    $line = str_replace($found, '', $line);
    return $line;
}
</pre>
<p><strong>El método</strong><br />
Este método analiza la hoja de estilo para ser mostrado al navegador, la cabecera se establece en: text/css content type.</p>
<pre class="brush: php;">
public function display() {
    header('Content-type: text/css');
    echo $this-&gt;parse();
}
</pre>
<p><strong>Paso 4 &#8211; El resultado caché</strong><br />
Sus funciones:<br />
- Leer el archivo en caché si es que existe.<br />
- Crear y almacenar los resultados prestados.<br />
- Actualizar los existentes si el archivo CSS no ha sido ha sido modificado.</p>
<pre class="brush: php;">
private function cache($content = false) {
    $cacheFile = &quot;cache/&quot;.urlencode($this-&gt;cssFile);
    if (file_exists($cacheFile) &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; filemtime($cacheFile) &gt; filemtime($this-&gt;cssFile)) {
        return file_get_contents($cacheFile);
    } else if ($content) {
        file_put_contents($cacheFile, $content);
    }
    return $content;
}
</pre>
<p>El nombre del archivo en caché se calcula a partir del original, es decir, de  nuestra hoja de estilos. La función que utilizamos para calcularlo es <a target="_blank" href="http://php.net/manual/es/function.urlencode.php">urlencode</a>.</p>
<p>Este tutorial está sacado de <a href="http://net.tutsplus.com" target="_blank" title="http://net.tutsplus.com">net.tutsplus.com</a>, concretamente de <a title="How to Add Variables to Your CSS Files" target="_blank" href="http://net.tutsplus.com/tutorials/html-css-techniques/how-to-add-variables-to-your-css-files/">aquí</a>.<br />
Podéis ver un ejemplo <a title="Variables en CSS" target="_blank" href="http://dixso.net/wp-content/examples/php/variables-css/">aquí</a>.<br />
Podéis descargar el ejemplo <a title="Variables en CSS" target="_blank" href="http://nettuts.s3.amazonaws.com/185_varsInCSS/demo.zip">aquí</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dixso.net/php/variables-en-css/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
