Daten verteilt bearbeiten

Ich muss mal eine Lanze brechen für den Cloud-Computing Dienst Dropbox.

Meine Situation derzeit: Ich stehe früh auf (4:30 Uhr), wecke ab 6 die Kinder, bringe die bis halb 8 in den KiGa, versuche bis 8 auf der Arbeit zu sein (was nicht immer hundertprozentig funktioniert), arbeite dann und versuche, bis 16:30 wieder zu Hause zu sein, “Kinderdienst” bis die ins Bett gehen. Bis die dann schlafen und ruhe einkehrt, kann es schonmal 20 Uhr werden, dannach steht dann das Studium an, was dann schon bis Mitternacht gehen kann. Und am nächsten Tag wieder von vorn.

*puh* Da bleibt nicht viel Zeit, um vergessene Dinge zu beschaffen. Warum erzähle ich das?

Okay, jeder, der schonmal studiert hat oder studiert kennt das: Man hat permanent das Gefühl, was nicht gemacht zu haben. Oder man bekommt plötzlich die Erkenntnis, dass an der fertig bearbeiteten Einsendeaufgabe doch noch ein Fehler ist. Nur leider liegt die Datei zuhause auf dem Rechner, die Erkentnis kommt aber auf der Arbeit. Dumm. Oder?

Genau dafür habe ich Dropbox. Dieser Dienst bietet einem im Free-Account Modus 2 GB Platz im Netz, auf die man zugreifen kann. Besonderes “Schmankerl” ist das Desktop-Tool von Dropbox. Installiert man dieses, bekommt man ein “Dropzone” genanntes Verzeichnis und ein Tray-Icon (man merkt, ich arbeite auf Windows, das Tool gibt es aber auch für Mac und Linux). Legt man nun Dateien oder Ordner in diesem VZ ab, so synchronisiert das Programm diese automatisch mit meinem Account. Die neueste Fassung wird automatisch geladen.

Das ist toll, denn nun kann ich meine Einsendeaufgaben zuhause bearbeiten und speichern. Diese liegen in der Dropzone. Von der Arbeit aus kann ich diese abrufen, ändern und hochladen (am einfachsten natürlich auch via Dropzone) und bin immer auf dem aktuellsten Stand. Gleiches gilt für Quelltexte, die mensch im Info-Studium ja auch schreiben muss. Alles liegt auf vielen Rechnern, vor allem zentral “in der Cloud”.

Und auch, wenn mein INet mal nicht läuft, die Dateien selbst liegen ja auf meiner Festplatte, ich kann weitermachen. Es gibt durchaus auch Dienste, die stellen das ganze als Netzlaufwerk zur Verfügung, dieses wäre ohne INet nicht erreichbar – und das wäre in meinem Fall “tödlich”.

Also, auch wenn manch einer nun “Werbung” schreit: Ich finde Dropbox gut. Und wer möchte, bekommt bei der Anmeldung über meinen Link nochmal 250 MB mehr.

Dropbox Homepage: https://www.dropbox.com/referrals/NTE2MzgyNDk

Führungsnull in Excel aus CSV anzeigen

Viele kennen das Problem. Man hat eine CSV Datei, in dieser steht eine Postleitzahl oder eine Telefonnummer, die als erste Stelle eine 0 (Null) hat.

Öffnet man das nun in Excel, ist die Null weg.

Beispiel: Ein Kunde kommt aus Dresden, gibt als PLZ “01307” ein. Exportiert man das ganze dann als “kunden.csv” und doppelklickt es in Excel auf, so erscheint “1307”, was ja nicht ganz richtig ist. Excel ist einfach zu schlau…

Da wir aber klein, trotzig und unwürdig sind, möchten wir trotzdem die führende Null sehen; der Kunde übrigens auch. Da der Kunde König und Excel eh nur eingekauft ist, ist der Weg klar: Die Null muss her!

Wer lange sucht, der findet auch die tollsten Lösungswege. Nicht Excel muss sich an uns, vielmehr müssen wir uns an Excel anpassen; sprich: Nicht einfach per doppelklick öffnen, o nein, gefälligst per Import die Daten einholen und dann als Text formatieren.

Das kann es nicht sein, hier also der Weg des Programmierers!

Unser Vorteil ist, das Excel die Daten pro Spalte nicht nur importiert, sondern auch interpretiert, d.h. wir benutzen eine Funktion aus Excel, die dafür sorgt, dass die Daten korrekt dargestellt werden.

Diese heißt für unseren Zweck: VERKETTEN

Will man also diese Zeile richtig importieren:

“Max”;”01307”;”Dresden”

Dann muss man sowas schreiben:

“Max”;”=VERKETTEN(0;1;3;0;7)”;”Dresden”

Und da Programmierer erwiesenermaßen faul sind, werfe ich gleich mal eine PHP-Funktion dafür in die Runde. Die kann sicherlich noch optimiert werden, aber für’s erste genügt diese den Anforderungen:

function formatForExcel($text) 
{
   $excelText = '=VERKETTEN(';
   for($i=0; $i<strlen($text);$i++)
   {
     if ($i>0) {
       $excelText .= ';';
     }
     $excelText .= $text[$i];
   }   
   $excelText .= ')';
   return $excelText; 
}

Wird nun formatForExcel aufgerufen, dann werden die Daten entsprechend per “Verketten” abgelegt und dann in Excel richtig aufgerufen.

Mathematische Strings mit PHP auswerten

Wer immer einen mathematischen Ausdruck in einem String auswerten bzw. ausrechnen möchte, muss ein wenig in die Trickkiste von PHP greifen.

Aber mal langsam, wir beginnen mit der Aufgabe:

$mystring = „123*1.1“;

Der String selbst kommt von irgendwo z.B. aus einem Formular und soll einen Wert + 10% berechnen. Wie machen wir das in PHP? Ein einfaches

echo $mystring;

reicht da nicht aus.

Nach ein bischen suchen im Handbuch kam ich auf diese Lösung, nicht schön, aber es geht:

eval(‚$ergebnis = ‚.$mystring.‘;‘);
echo $ergebnis;

Auf das Ergebnis kann man nun bequem zurückgreifen.

Okay, hier fehlen noch ein paar Sicherheitsmechanismen (eval is evil), aber der Grundsatz sollte klar sein und solche Funktionen sind schnell nachgerüstet (siehe die Filter-Sektion im Handbuch).

Generell sollte man eval natürlich vermeiden, aber in speziellen Anwendungen – wie in diesem – kann es durchaus Sinn machen, die “böse” Funktion zu nutzen.

Ich bin schon mal froh, diese Funktion zu haben und will diese euch nicht vor enthalten.

Läuft, läuft nicht, läuft nicht immer …

Eine neue tolle Web-GUI, umgesetzt mit jQuery. AJAX, Bilder, Layout und Farben, alles perfekt abgestimmt, mehrmals auf Funktion getestet, auch auch verschiedenen Rechnern.

Alles super.

Also: Freigabe, Bekanntgabe der URL und auf Lob warten.

Kurze Zeit später, der Endbenutzer am Telefon, in Erwartung von (verdientem) Lob gehe ich ran, nur um zu hören: “Geht nicht!”.

Völlig perplex öffne ich die Seite, alles funktioniert.

HTML lädt, CSS: perfekt, Javascript: vorhanden, jQuery: alles roger.

Woran liegt’s dann?

Fehlerkonsole vom Firefox aufgemacht und siehe da: Eine Fehlermeldung: “console nicht bekannt“ in Zeile xyz”

Cool, ein vergessenes Kommando “console.log”, die uns zu debugzwecken Ausgaben in Firebug liefert, führt nun dazu, dass der Endbenutzer unsere schöne GUI nicht bedienen kann, weil der natürlich nicht Firebug installiert hat. Großes Aha!

Kleine Ursache, lange Suche …

jQuery und der HTML-Head Bereich

Habe grade etwas länger zur Lösung dieses Problems verpulvert und möchte damit allen helfen, die ähnliche Probleme haben.

Ziel war es, über eine Suchfunktion mittels AJAX und jQuery ein neues Tab zu öffnen und dort die Suchinfos darzustellen und zwar ebenso, wie schon bereits vorher angezeigte “festen” Infos dargestellt wurden. Dazu gehörte auch, dass ein Klick auf eine Zeile einen jQuery-Dialog öffnet und dort mehr Informationen angezeigt werden.

Nun, die “normalen” Informationen mit dem jQuery-Dialog anzuzeigen war kein Problem, das Problem entstand, als ein neues jQuery-Tab hinzukam, dass die Ergebnisse der Suche als GET-Request darstellte (jQuery-Tab mit URL als Referenz).

Nach der Durchführung einer Suche funktionierte keine jQuery-Funktion mehr, also öffnete sich kein Info-Fenster.

Nun, ich mache es kurz: Die Lösung ist nun, dass in der Antwort des Requests nicht nur die Daten mit Layout enthalten waren, sondern eine komplette HTML-Seite und diese auch inklusive Bereich. Und dort war wiederrum ein Verweis auf jQuery enthalten; allerdings ohne die Datei, die die ganze jQuery-Logik für diese Seite beinhaltet.

jQuery lädt also neu und “kennt” dannach die Logik für die aktuelle Seite nicht mehr; ergo: Keinerlei Funktion mehr auf der Seite.

Evtl. sollte jQuery hier nachbessern und die im Speicher befindlichen Scripte nicht “vergessen”, wenn es sich selbst neu lädt. Am besten, es läßt sich gar nicht mittels eines neuen Aufrufes von neu laden, denn das störte an dieser Stelle das Vorwärtskommen doch enorm.

So, ich hoffe, ich konnte irgendeinem von euch helfen, so daß ihr nicht allzulange braucht, um eure Problem zu lösen.

Homepage für andere sperren

Während man eine Webseite erstellt oder bearbeitet, möchte man natürlich nicht, dass andere einen “Zwischenstand” sehen und man sperrt die Domain. Oder man möchte einfach allein auf seiner Homepage rumsurfen … warum auch immer.

Zuerst braucht Mensch seine IP, dazu gibt es genug AddOns oder Webseiten, auf denen Mensch das rausbekommt.

Dannach braucht es noch zwei Zeilen in der .htaccess; RewriteEngine sollte “on” sein.

RewriteCond %{REMOTE_ADDR} !^IPADRESSE$
RewriteRule ^(.*)$ URL_ZUR_UMLEITUNG [NC,QSA,L,R=302]

Wichtig ist das ! vor der PrüfungsIP-Adresse in der RewriteCond Zeile.

Somit sehen alle anderen Besucher die URL die bei der RULE eingegeben wird, Mensch selbst sieht aber die “normalen” Inhalte.

Kleines Beispiel (Domain ist my-example-web.com)

RewriteCond %{REMOTE_ADDR} !^78.201.9.12$
RewriteRule ^(.*)$ http://example.com [NC,QSA,L,R=302]

Hier greifen alle User auf example.com zu, nur der User von der IP 78.201.9.12 (sollte die eigene sein) greift auf die “echten” Inhalte der Seite zu.

Referenz: Doku zu RewriteCond

Benutzereingaben prüfen: Leere Strings

Ich kenne viele Wege, einen String daraufhin zu prüfen, ob der User

a) überhaupt was eingegeben hat und
b) ob der User außer Leerzeichen was eingegeben hat.

In jeder Sprache gibt es dafür viele Wege, einige gut, viele nicht so gut.

Heute mal ein Beispiel aus der Reihe “not so good”:

if

(strlen($tls_description) > 1 && substr_count($tls_description,“ „) >= (strlen($tls_description) – substr_count($tls_description,“ „)))
{
   $err = true;
}

Mein Ansatz, genauso gut, dafür lesbar und ebenso “effektiv”:

if

(strlen(trim($tls_description))<1)
{
   $err = true;
}

Nicht nur schneller, sondern auch lesbarer und nicht so WTF?

return-path bei php mail() erzwingen

Bei machen Webhostern kann es sein, dass die sendmail Konfiguration einen header Eintrag in der Form von

$header .= „Reply-To: test@example.com\n“;

einfach nicht akzeptiert (Nein, es liegt nicht am fehlenden \r, soviel sei gesagt).

Ursache hierfür ist die Einstellung von sendmail, die solche Einträge mit den eigenen Einträgen überschreibt und heraus kommt dann sowas:

Reply-To: meinpc@localhost

Das ist natürlich Müll.

Allerdings kann man diesen Parameter mit der 5ten Option von PHP’s mail() überschreiben. Dazu fügt man am Ende den ‘-f’ Paramater für sendmail an, das Ganze sieht dann so aus:

mail($zieladresse,$subject,$body,$header,” –f test@example.com”);

Somit wird der Mail der gewünschte return-path verpasst.

MySQL – Den richtigen (Daten)typ kennen

Am Wochenende sah ich mir ein Script eines anderen Programmierers an … der Webmaster des Scriptes hatte eine Frage und zur Beantwortung benötigte ich Zugang zum Script. Nach langen Erklärungen, was denn genau passieren soll und was denn aktuell wirklich passiert, stieß ich auf einige Besonderheiten im Script.

Nun, den Fehler konnte ich beseitigen und der Webbi bat mich dann gleich mal, ob ich denn mal über den Code an sich sehen könnte, “ob man da noch was rausholen kann, so, Geschwindigkeitstechnisch”. “Immer”, denke ich mir und sehe mir das ganze so.

Okay, optimal war der Code nicht, eher genau das Gegenteil. Mein Kommentar war dann, dass, wenn der Webbi das ganze schnell haben will, er sich doch bitte einen _guten_ Programmierer holen soll, der das ganze mal neu macht. Der alte Code wäre dafür nicht geeignet. Der Webbi war nachher froh, dass der alte Code das macht, was er wollte und damit ist die Geschichte erstmal beendet.

Warum schreibe ich das ganze?
Nun, im Code fiel mir auf, dass ziemlich viele Variablen gegen die Datenbank geprüft wurden, nur für den Zweck, ob in einem Datenbankfeld – sinngemäß – ja oder nein steht. Dieses ja-oder-nein wurde dann aber in einem Zahlenfeld in mySQL gespeichert – soweit, so gut – nur eben ein INT(1).

Und nun zum Sinn dieses Postings: Lieber Programmierer, du brauchst in der DB einen Platz um “ja” oder “nein” zu speichern? Dann minimiere “ja” zu 1 und “nein” zu 0, soweit kamst du ja schon. Nun noch die Auswahl des geeigneten DB-Typen und da hast du gepatzt.

Ein INT(1) speichert eben NICHT nur eine Zahl mit der Länge 1 (also 0 bis 9), sondern einen 4 Byte großen Integer Wert, den du mittels “ZEROFILL” dann auf die in den Klammern angegebene Zahl mit 0 auffüllen kannst. Habe ich ein INT(3) Feld und speichere dort die Zahl 4 rein, dann steht da 004; in ein INT(3) kann ich aber auch die Zahl 123456 schreiben und habe kein Problem damit, da ein 4-Byte INT Zahlen von 0 bis 4294967295 (UNSIGNED) oder von –2147483648 bis 2147483647 (SIGNED) speichern kann, egal was in Klammern steht.

Um Speicherplatz zu sparen nimm bitte den Datentyp TINYINT, der speichert nur 1 Byte große Zahlen, also von 0 bis 255 (UNSIGNED) oder –128 bis 127 (SIGNED).

Zur weiteren Info lies dir die folgenden beiden Links durch:
http://dev.mysql.com/doc/refman/5.1/de/numeric-types.html
http://dev.mysql.com/doc/refman/5.1/de/storage-requirements.html