PHP Class: StylesheetParser

Watch out: this post was written (long) before CSS preprocessors like LESS or SASS were cool. Just ignore the PHP class presented here but keep in mind what futuristic ideas I had at that time ;)

Bei größeren Projekten stehe ich immer wieder vor dem Problem, wie ich mein CSS so strukturiere, dass ich 1. den Überblick nicht verliere und 2. möglichst wenig Aufwand habe. Einerseits kann ich ein paar große Dateien verwenden, durch die ich mich dann aber immer durchscrollen/-suchen muss, andererseits kann ich mit vielen kleineren Dateien pro “Sektion” arbeiten. Die muss ich aber auch irgendwie einbinden, was dann wieder zum Verwaltungsaufwand wird, weil ich das, sobald eine neue Datei dazukommt, irgendwo definieren muss.

Aus diesem Grund habe ich mit eine kleine PHP-Klasse namens StylesheetParser geschrieben, die mir genau diese Arbeit abnehmen soll. Ergänzend dazu bietet die Klasse die Möglichkeit, Platzhalter zu definieren, die dann im CSS verwendet werden können. Letzteres ist überaus nützlich, um sich z.B. Farben zu definieren, oder einfach um ein Stylesheet dynamisch zu gestalten, ohne mit PHP und CSS in einer Datei herumfummeln zu müssen.

Verwendung

Ich habe meistens diese Verzeichnisstruktur: einen Ordner css, in dem meine PHP-Dateien liegen, die StylesheetParser verwenden. In einem Unterordner liegen dann die eigentlichen CSS-Dateien (in den Beispielen nenne ich den Unterordner res).

1: Stylesheets manuell hinzufügen

Hier wird ein neues Objekt erstellt, manuell ein paar Stylesheets hinzugefügt und das Resultat ausgegeben. Der zweite, optionale Parameter der Methode addStylesheet setzt einen Titel für das Stylesheet, der dann im CSS als Kommentar eingefügt wird.

<?php
// include the class file
require_once('../lib/stylesheetparser.class.inc.php');

// create a new object
$style = new StylesheetParser();

// add some stylesheets
$style->addStylesheet('res/01_reset.css', 'reset HTML');
$style->addStylesheet('res/02_htmlbody.css', 'basic html and body');
$style->addStylesheet('res/03_typo.css', 'typography');
$style->addStylesheet('res/04_layout.css', 'general layouting');
$style->addStylesheet('res/05_mainmenu.css');
$style->addStylesheet('res/05_submenu.css');
$style->addStylesheet('res/06_searchform.css');
$style->addStylesheet('res/06_commentform.css');

// render the result
$style->Render();
?>

2: Stylesheetordner hinzufügen

Nehmen wir an, wir haben die selben 8 Stylesheets wie oben, möchten diese aber nicht manuell einbinden. Sobald ein neues Stylesheet in dem Ordner landet, soll dieses ebenfalls miteingebunden werden. Dafür gibt es die Methode addStylesheetDir. Die Methode hat einen zweiten optionalen Parameter $recursive. Ist dieser auf true gesetzt, werden Unterverzeichnisse ebenfalls miteinbezogen. Die Methode sortiert alle Dateien/Verzeichnisse alphabetisch, es bietet sich hier also an, Dateien je nach Priorität mit einer Nummerierung zu versehen (wie in Beispiel 1).

<?php
// include the class file
require_once('../lib/stylesheetparser.class.inc.php');

// create a new object
$style = new StylesheetParser();

// add a directory to scan for stylesheets
$style->addStylesheetDir('res');

// add another directory to recursively scan for stylesheets
$style->addStylesheetDir('res2', true);

// render the result
$style->Render();
?>

3: Platzhalter

Wie weiter oben angesprochen, bietet die Klasse die Möglichkeit, Platzhalter zu setzen. Damit werden Stylesheets 1. dynamisch, ohne dass man mit Programmcode in den CSS-Dateien arbeiten muss und 2. leichter wartbar, weil man Variablen setzen kann, die dann beliebig oft verwendet und zentral verwaltet werden können.

<?php
// ...

// add placeholder values
$style->addValue('fontcolor', '#333');
$style->addValue('linkcolor', '#ccc');

// add placeholder value depending on request parameter
if(isset($_GET['headerimage']) && !empty($_GET['headerimage']))
{
    $headerimage = $_GET['headerimage'];
}
else
{
    $headerimage = 'default';
}

$headerimage = '../img/headers/'.$headerimage.'.jpg';
$style->addValue('headerimage', $headerimage);

// ...
?>

Alternativ kann man auch mehrere Platzhalter gleichzeitig setzen, indem man ein Array und die Methode addValues verwendet.

<?php
// ...

// add placeholder values
$values = array(
    'fontcolor' => '#333',
    'linkcolor' => '#ccc'
);

$style->addValues($values);

// ...
?>

Diese Platzhalter sind dann in den eingebundenen Stylesheets im Format {{platzhaltername}} verwendbar:

#content p
{
    color: {{fontcolor}};
    ...
}

#content a
{
    color: {{linkcolor}};
    ...
}

/* headerimage from first example */
#header
{
    background: #555 url({{headerimage}}) no-repeat top left;
}

Verhalten beinflussen

Standardmäßig verwendet StylesheetParser die Platzhalter-Trennzeichen {{ und }} und gibt bei Aufruf der Methode Render das Stylesheet mit dem content-type header text/css aus. Dieses Verhalten kann auch beeinflusst werden.

Um die Platzhalter-Trennzeichen zu ändern, gibt es die Methode setDelimiters. Diese erwartet als ersten Parameter das linke Trennzeichen und als zweiten das rechte.

<?php
// ...

// set placeholder delimiters
$style->setDelimiters('[[', ']]');

// ...
?>

Die Methode Render hat einen optionalen Parameter $return, der, sofern er auf true steht, bewirkt, dass das Ergebnis zurückgeliefert und nichts ausgegeben wird. Dies könnte nützlich sein, wenn man die Ergebnisse im Nachhinein nochmal manipulieren möchte.

<?php
// ...

// save results to a variable
$mystyle = $style->Render(true);

// add some additional content
$mystyle .= "nn /* -- end of stylesheet -- */";

// set correct header
header('Content-type: text/css');

// show the results
echo $mystyle;
?>

5. Ausgabe strukturieren oder komprimieren

Standardmäßig wird der Code unkomprimiert ausgegeben und für jede Datei ein Kommentarheader in folgender Form eingefügt:

/* --------------------------------------------------------------

files_screen/02_00_mainmenu.css

-------------------------------------------------------------- */

Dieses Verhalten kann man mit $showSections beeinflussen:

$style->showSections = false;

Neu hinzugekommen ist die Möglichkeit, den Code zu komprimieren (alle Kommentare und Leerzeilen entfernen). Dafür gibt es 3 Variablen:

bool $compressAll
der gesamte Code wird komprimiert
array $compressPatterns
ein Array mit regulären Ausdrücken für die Filenamen, die komprimiert werden sollen
array $nonCompressPatterns
das Gegenteil von $compressPatterns. Wird bevorzugt, sprich der Code der passenden Dateien bleibt trotz $compressAll oder $compressPatterns unkomprimiert

Achtung: die regulären Ausdrücke werden direkt an preg_match übergeben, müssen also gültig sein.

<?php
// compress all
$style->compressAll = true;

// override compress setting for debug files
$style->nonCompressPatterns = array('~^files/debug~');
?>
<?php
// compress framework files
$style->compressPatterns = array('~files/framework~');
?>

Anmerkungen

Die Methode Render setzt, sofern sie nicht mit dem Parameter $return aufgerufen wird den korrekten content-type mittels header(). Es ist daher darauf zu achten, dass vor dem Aufruf der Methode nichts im Script ausgegeben wird, da es sonst mit einem Fehler beendet wird.

StylesheetParser funktioniert nur unter PHP5

Download