In PHP geschriebene Templatesprachen sind eine Sackgasse der Evolution
Veröffentlicht: August 1, 2010 Einsortiert unter: PHP, Programmieren, Webentwicklung | Tags: templateengine, templatesprachen 3 Kommentare »Wer sich mit PHP beschäftigt wird früher oder später auf Personen treffen, die Befürworter von sogenannten Templatesystemen sind (z.B. Smarty, Fluid, uvm.). Es gibt auch viele Personen, die eigene Templateengines schreiben. Nahezu jedes in PHP geschriebene Content Management System (CMS) verfügt über eine eigene Implementierung oder nutzt ein Templatesystem.
Es will mit einfach nicht in den Kopf, warum die das machen. Ich meine PHP ist eine Templatesprache. Warum zur Hölle sollte man eine Templatesprache in einer Templatesprache schreiben? OK, man versucht eine Trennung zwischen Businesslogik und Darstellung zu erreichen, und behauptet dann auch noch das Model-View-Controller Pattern zu verwenden, was ja State-Of-The-Art ist. (Wer das nicht benutzt ist ein Höhlenmensch, der seit dem Altpaläolithikum jeglichen Fortschritt verschlafen hat!)
Merken diese Leute denn nicht, was für einen riesigen Ballast sie sich damit an Board holen? Man muss nämlich eine weitere Sprache lernen, die in den meisten Fällen zwar an PHP angelehnt ist, aber gerade für Schleifen und If-Then-Else Konstrukte meist unbenutzbar ist. Die Templates werden mit Hilfe von PHP geparst, um dann mühsam wieder HTML-Code daraus zu generieren. Das ist langsam und ineffizient. PHP kann das seit Version 1.0 und macht es zuverlässig und schnell. Um Logik und Darstellung zu trennen braucht es nicht einer künstlichen Barriere, die jedesmal mit viel Aufwand überwunden werden muss, sondern einfach nur etwas Disziplin beim Programmieren. PHP kennt nämlich so tolle Konzepte wie Funkionen und Klassen. Damit kann man ganz prima verschiedene Codebereiche voneinander trennen.
“Aber die Sicherheit”, schreien dann einige, “mit PHP kann ich ja alles machen. Bei einer eigenen Templatesprache kann ich mir sicher sein, dass ein Template keinen Unfug anstellen kann.” Zugegeben, das klingt auf den ersten Blick einleuchtend. Wenn ich eine eigene Templatesprache habe, die nur Variablen ausgeben, aber keine beliebigen Befehle ausführen kann, dann reisst mir das keine Sicherheitslöcher in die Applikation.
Aber das ist nur die halbe Wahrheit. Nahezu alle CMSs können per Plug-In (Add-On, Extension, …) erweitert werden. Diese sind sowieso in PHP geschrieben und können beliebigen Scheiß anstellen. Gelten die Sicherheitsbedenken dafür denn nicht? Und mal ganz ehrlich: Alle Templates die ich bislang genutzt habe waren entweder die Beispieltemplates der Applikation, oder ich hab sie selbst geschrieben. Und wenn ich die Dinger selbst schreibe, dann bin ich ja auch selbst dafür verantwortlich, oder?
Ich hab jetzt viel geschrieben. Manchmal hilft es einen Standpunkt nieder zu machen, um ihn besser zu verstehen. Aber in diesem Fall bin ich überzeugter denn je, dass in PHP geschriebene Templatesprachen unsinnig sind. Eine Sackgasse der Evolution, sozusagen.
jQuery: The ‘charCode’ property of a keydown event should not be used.
Veröffentlicht: März 28, 2010 Einsortiert unter: Webentwicklung | Tags: charCode, jQuery, keyCode Schreibe einen Kommentar »Warning: The ‘charCode’ property of a keydown event should not be used. The value is meaningless.
Source File: http://example.com/
Line: 0
Wenn du diese Meldung bekommst, dann hast du vermutlich Code geschrieben, der event.keyCode oder event.charCode benutzt:
$(document).keydown(function(event) { if (event.keyCode == 37) { // do something } if (event.charCode == 37) { // do something } }
Diese beiden Variablen sind unschön. KeyCode zum Beispiel gibt nur den Code der Taste an, aber man kann nicht zwischen a und A unterscheiden, weil beide auf derselben Taste liegen.
Lösung
Du solltest das von jQuery hinzugefügte event.which nehmen, das versucht diese beiden zu normalisieren.
$(document).keydown(function(event) { if (event.which == 37) { // do something } }
JavaScript Dateien effizient übertragen mit GZIP, PHP und Apache
Veröffentlicht: März 13, 2010 Einsortiert unter: Howto, PHP, Webentwicklung | Tags: apache, gzip, javascript, PHP 4 Kommentare »Wenn man diese schönen JavaScript Bibliotheken, wie z.B. jQuery, nutzt, dann steht man schnell vor dem Problem, dass man ein Dutzend JavaScript Dateien laden muss, um die Seite korrekt angezeigt zu bekommen. Wenn man dann den Webserver falsch konfiguriert hat werden die Dateien alle unkomprimiert übertragen. Ausserdem muss der Browser für jede Datei den Webserver fragen. Und wenn man dann auch noch das Caching falsch konfiguriert hat, dann werden für jeden Seitenaufbau alle JS Dateien neu geholt.
Ob man sein System richtig Konfiguriert hat lässt sich sehr schön mit dem Firefox Plugin Firebug beobachten. Wie das geht bleibt dem geneigten Leser als Übung überlassen, denn mir geht es hier hauptsächlich um die Lösung dieses Problems.
Nach Monaten intensiver Recherchen und langen Versuchsreihen bin ich auf folgende Lösung gestoßen: Anstatt die JS Dateien direkt herunterzuladen, kopiere ich einfach den Inhalt von allen Dateien on-the-fly in eine Große. Diese wird dann hübsch komprimiert und mit den notwendigen HTTP Headern ausgestattet, damit das Caching auch funktioniert. Irgendwann hat sich folgendes PHP Script als optimal herauskristallisiert:
<?php // License: none (public domain) /* * Dieses Script concateniert mehrere Dateien und schickt sie gzip * komprimiert an den Browser. * Ausserdem wird ein Etag gesetzt, der nötig ist, um das Cachen der * Javascript Datei zu ermöglichen. Der Etag ändert sich jedesmal, wenn * eine der Dateien geändert wird, oder eine hinzu-/weggenommen wird. */ header('Content-Type: text/javascript'); header("Expires: ".gmdate("D, d M Y H:i:s", time() + 3600*24)." GMT"); /* * Hier die JavaScript Dateien angeben: */ $files = array( "jquery-1.4.2.min.js", "ui.core.js", "ui.dialog.js", "ui.draggable.js", "ui.resizable.js", "jquery.textarearesizer.compressed.js" ); $md5 = ''; foreach ($files as $file) { $md5 .= md5_file($file); } $etag = md5($md5); header("Etag: $etag"); if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) { header('HTTP/1.1 304 Not Modified'); } else { if ( isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false ) { ob_start("ob_gzhandler"); } else { ob_start(); } foreach ($files as $file) { echo file_get_contents($file); } } ?>
Vorgehensweise:
Lege eine Datei ‘js.php‘ in dem Ordner mit den JavaScript-Dateien an. Kopiere obigen Code in die Datei. Ändere das $files Array so, dass deine JavaScript-Dateien da drin stehen. Füge folgenden Script-Tag in deinen HTML-Code ein:
<script src="/path/js.php" type="text/javascript"></script>
Das ganze funktioniert natürlich auch mit CSS-Dateien, wobei man dann den Content-Type auf text/css ändern muss.
Javascript: delayed method call
Veröffentlicht: November 29, 2009 Einsortiert unter: Webentwicklung | Tags: delayed task, javascript, timeout Schreibe einen Kommentar »Sometimes you want to delay an action (e.g. an AJAX call) until the user finishes or pauses her input. This is usefull for any typeahead actions. So you want to call a function when the user types into a field, but you only want to call that function once even if the user types two characters at once, or a hole word within a short period of time.
AFAIK Javascript does not provide a method that handles this use case conveniently.
Here is a function that can be called on every keystroke. It sets a timeout to call the function which handles the input. If the method is called again while the timeout has not been elapsed, then the first timeout will be cancelled and a new timeout is set.
var timeout = null;
function delayTask(methodToCall, delayInMilliseconds)
{
if (timeout != null)
{
clearTimeout(timeout);
}
timeout = window.setTimeout(methodToCall, delayInMilliseconds);
}
Viele Links für Webentwickler
Veröffentlicht: Februar 24, 2009 Einsortiert unter: Java, Webentwicklung Schreibe einen Kommentar »Eine Seite die viele nützliche Seiten rund um Webentwicklung verlinkt: http://www.elementiks.com/web_resources.php. Und eine rund um Code Analyzer für Java: http://java-source.net/open-source/code-analyzers
Google erlaubt das Angeben einer Canonical URL
Veröffentlicht: Februar 17, 2009 Einsortiert unter: Webentwicklung Schreibe einen Kommentar »Wie Heise verbreitet kann man nun für eine Seite angeben unter welchem Link man sie gerne indiziert haben möchte.
Greasemonkey-Script: Timestamp to Date
Veröffentlicht: Januar 4, 2009 Einsortiert unter: Webentwicklung | Tags: Greasemonkey Schreibe einen Kommentar »Ich arbeite häufiger mit Programmen die Unix Timestamps verwenden. Für debug-Ausgaben ist es dann immer ziemlich nervig den Timestamp ersteinmal in menschenlesbare Form umzuwandeln. Darum habe ich mir ein Greasemonkey-Script geschrieben, dass dies für mich erledigt. Ein Doppelklick auf eine Zahl > 1000000000 wandelt diese in eine Zeitangabe um und zeigt sie in einem kleinen div links oben in der Ecke an. Ein Klick auf den div lässt ihn wieder verschwinden.
// ==UserScript==
// @name Timestamp to Time
// @namespace andi
// @description Ein Doppelclick auf einen Timestamp und schon erscheint ein DIV, der die Zeit in menschenlesbarer Form anzeigt
function showUnixtime()
{
var selection = window.getSelection();
if (1000000000 < selection )
{
var date = new Date(selection * 1000);
//alert(date);
var myDiv = document.createElement("div");
myDiv.style.position = "fixed";
myDiv.style.top = "0";
myDiv.style.left = "0";
myDiv.style.border = "solid black 2px";
myDiv.style.background = "white";
myDiv.style.padding = "1em";
var t1 = document.createTextNode(""+date);
var br = document.createElement("br");
var t2 = document.createTextNode(""
+ date.getFullYear() + "."
+ (date.getMonth()+1) +"."+date.getDate()
+ " " + date.getHours() + ":"
+ date.getMinutes() + ":" + date.getSeconds());
myDiv.appendChild(t1);
myDiv.appendChild(br);
myDiv.appendChild(t2);
document.body.appendChild(myDiv);
myDiv.addEventListener('click', function(evt) {
document.body.removeChild(myDiv)
},
false);
}
}
document.body.addEventListener(
'dblclick',
function (evt) { showUnixtime(); },
false);
// ==/UserScript==