24
mar

Variables en CSS

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 notarán la diferencia.
También veremos cómo procesaremos este script en cache para evitar el mal uso de memoria en la CPU.

Requisitos:
* Apache con Rewrite mod on (Activado).
* PHP 5

Paso 1 – Crear el Proyecto
Añadimos html simple en nuestra hoja que la llamaremos ‘index.html’:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Variables en CSS... Si, es posible!</title>
    <link href="css/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <h1>Variables en las hojas de estilo</h1>
    <p>Es posible!</p>
    <p>Con PHP / Apache y URL Rewrite Mod</p>
</body>
</html>

Ahora creamos la hoja de estilos:

$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;
}

Paso 2 – Redireccionar los ficheros CSS a nuestro script PHP
Añadimos en nuestro fichero .htaccess lo siguiente:

RewriteEngine on
RewriteRule ^(.*\.css)$ enhanced_css.php?css=$0

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

Por ejemplo:
/css/styles.css

Va a redirigir a:
enhanced_css.php?css=/css/styles.css

Nota:
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:

<link href="css/styles.css" rel="stylesheet" type="text/css" />

Por esto otro:

<link href="enhanced_css?css=css/styles.css" rel="stylesheet" type="text/css" />

Paso 3 – Analizar el archivo CSS con PHP
Dado que los archivos CSS se redirigen a nuestro script PHP, vamos a construir una clase llamada “Enhancedcss” para leer, buscar y reemplazar las variables y, a continuación, mostrar el contenido CSS.
Nuestra clase se instancia mediante la aprobación de $_GET['css'].

if (isset($_GET['css'])) {
    $css = new EnhancedCss($_GET['css']);
    $css->display();
}

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é.

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.
    }
}

El contenedor
Comprobamos si el archivo CSS existe, si no, la secuencia de comandos devuelve un error HTTP 404.
La ruta de la hoja de estilos se mantiene en la propiedad ‘$this->cssFile’ que se utiliza para calcular el nombre del archivo en la caché más tarde.

Analizamos el método
Este método abre el archivo CSS y lee línea por línea.

private function parse() {
    $content = '';
    $lines = file($this->cssFile);
    foreach($lines as $line) {
        $content .= $this->findAndReplaceVars($line);
    }
    return $content;
}

La función que se utiliza está aquí. Lo cierto es que puede ser útil, ya que abre un archivo y devuelve el contenido en una array.

El método ‘FindAndReplace’
Este método es el principal, busca las variables definidas. Cuando encuentra una variable y tiene valor, entonces, la substituye.

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 < $count; $i++) {
        $varName  = trim($varNames[$i]);
        $varValue = trim($varValues[$i]);
        if ($varValue) {
            $this->values[$varName] = $this->findAndReplaceVars($varValue);
        } else if (isset($this->values[$varName])) {
            $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this->values[$varName].'\\1', $line);
        }
    }
    $line = str_replace($found, '', $line);
    return $line;
}

Revisamos el código paso a paso:

private function findAndReplaceVars($line) {
    preg_match_all('/\s*\\$([A-Za-z1-9_\-]+)(\s*:\s*(.*?);)?\s*/', $line, $vars);

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. Aquí tenéis más información al respecto.

Por ejemplo, la tercera línea de la hoja de estilos:
$main-color: #3D7169; $secondary-color: #000;

Devolverá esta array:

$vars => Array
(
    [0] => Array
        (
            [0] => $main-color: #3D7169;
            [1] => $secondary-color: #000;
        )

    [1] => Array
        (
            [0] => main-color
            [1] => secondary-color
        )

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

    [3] => Array
        (
            [0] =>  #3D7169
            [1] =>  #000
        )
)

Supongamos que $vars[0] contiene todo, $vars[1] contiene los nombres de las variables y $vars[3] contiene los valores.

$found     = $vars[0];
$varNames  = $vars[1];
$varValues = $vars[3];

Concretamente así:

$found => Array
        (
            [0] => $main-color: #3D7169;
            [1] => $secondary-color: #000;
        )
$varNames => Array
        (
            [0] => main-color
            [1] => secondary-color
        )
 $varValues => Array
       (
           [0] =>  #3D7169
           [1] =>  #000
       )

Contamos el número de variables que se han encontrado en la línea actual.

$count = count($found);

Hacemos la condición:

for($i = 0; $i < $count; $i++) {
    $varName  = trim($varNames[$i]);
    $varValue = trim($varValues[$i]);            

    // ...
}

Definiciones de las variables
Si $varValue no está vacía, tenemos una variable definida. Así que se almacena en $this->values property.

if ($varValue) {
    $this->values[$varName] = $this->findAndReplaceVars($varValue);
} else if ...

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.
Los valores se almacenan en $this->values array con el nombre de variable clave.

Array
(
	[font] => arial, sans-serif
	[main-color] => #3D7169
	[secondary-color] => #000
)

Aplicaciones de las variables
Comprobamos que esta variable existes en los valores de la array. Si es así, reemplaza la variable por su valor.

} else if (isset($this->values[$varName])) {
    $line = preg_replace('/\\$'.$varName.'(\W|\z)/', $this->values[$varName].'\\1', $line);
}

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.

Por último, procesa la línea y es devuelta.

    $line = str_replace($found, '', $line);
    return $line;
}

El método
Este método analiza la hoja de estilo para ser mostrado al navegador, la cabecera se establece en: text/css content type.

public function display() {
    header('Content-type: text/css');
    echo $this->parse();
}

Paso 4 – El resultado caché
Sus funciones:
- Leer el archivo en caché si es que existe.
- Crear y almacenar los resultados prestados.
- Actualizar los existentes si el archivo CSS no ha sido ha sido modificado.

private function cache($content = false) {
    $cacheFile = "cache/".urlencode($this->cssFile);
    if (file_exists($cacheFile) &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; filemtime($cacheFile) > filemtime($this->cssFile)) {
        return file_get_contents($cacheFile);
    } else if ($content) {
        file_put_contents($cacheFile, $content);
    }
    return $content;
}

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 urlencode.

Este tutorial está sacado de net.tutsplus.com, concretamente de aquí.
Podéis ver un ejemplo aquí.
Podéis descargar el ejemplo aquí.

Bookmark and Share
aaa

Ningún comentario

Aún no hay comentarios.

Tienes que estar conectado para publicar un comentario.

Comentarios RSS Feed   TrackBack URL