PHP Skripte auf der Commandline

Wieder mal ein kleines Projekt brachte mich dazu ein PHP Skript auf Commandline bzw im Terminal ausführen zu wollen.
Zum einen sollte es schnell gehen und keine WebOberfläche benötigten zum anderen wollte ich auch einfach mal wissen wie es funktioniert. Im Endeffekt gar nicht schwer, das Zauberwort heißt getopt(). Mit dieser PHP Methoden lassen sich übergebene Argumente auf Commandline ebene abfragen.

PHP Code:

<?php
    $arguments = getopt("f:t:");
    var_dump($options);
?> 

CommandLine

php bsp.php -f -t

In diesem Fall werden die Parameter einfach übergeben, getopt gibt hier ein Array zurück mit der Hinterlegten Option und dem zugehörigen Wert. Wenn kein Wert übergeben wird, wird FALSE zurückgegeben.

Wenn wir den Aufruf nun ändern zu:

CommandLine

php bsp.php -f hello -t world

bekommen wir durch optget() ein Array mit den Optionen f -> hello und t -> world zurückgeliefert.

jQuery resize

Kleines (quick and dirty) Beispiel für die jQuery Resize Funktion
In einem Projekt musste ich ein genau hinter einem Logo ein Hintergrund-Bild starten lassen, welche dann dann horizontal den Rest des Bildschirms ausfüllen sollte… Wie ein Strahl der aus dem Logo kommt.
Auf Grund der bestehenden CSS/HTML Struktur und natürlich zu wenig Zeit ist diese kleine Javascritp Lösung entstanden.

bgposition = function(){
    var left = $('a.logo').position().left;
    left = Math.ceil(left);
    $('.containerMitCSSBackgroundImage').css('background-position', left+'px 0');
  }
    bgposition()
  $(window).resize(function(){
    bgposition();
  });

Die Funktion bgposition() wird beim Start der Seite aufgerufen und die Position des Logos abgefragt, dieser Wert wird gerundet und dann dem Container mit dem background-image als Hortizontale „Start“ Position mitgegeben.

Wenn das Fenster nun verkleinert oder vergrößert wird, greift die die resize() Funktion von jQuery und die Funktion wird erneut ausgeführt. Schnell, klein, praktisch das mag ich an jQuery.

Sqlite3 und PDO

Ich habe heute für ein kleines Projekt eine Datenbank benötigt und habe mich dann recht schnell für Sqlite entschieden.
Da ich damit allerdings noch nie gearbeitet habe hier ein paar Punkte zur Erinnerung:

Sqlite DB erstellen bzw öffnen
// bei PDO anfragen zumindestens den Connect immer in einen try catch Block setzen
// wenn DBs mit Benutzer und Passwort abgefragt werden, da bei einem Fehlgeschlagenen
// Versuch sonst alles inklusive User und PWs als Fehler ausgegeben werden

try{
	$dbh = new PDO("sqlite:mydatabase.sdb");	
}
catch (PDOException $e)
{
	echo $e->getMessage();
}

Sqlite Datentypen:
Die sind hier relative einfach gehalten, da Sqlite dynamic typing nutzt.

SQLite uses dynamic typing. Content can be stored as INTEGER, REAL, TEXT, BLOB, or as NULL.

Quelle: sqilte.org

wie erstelle ich ein Auto Increment Feld

Short answer: A column declared INTEGER PRIMARY KEY will autoincrement.

Quelle:
sqilte.org

ErrorMode setzen:

//direkt nach dem öffnen der DB
	/*** set the error reporting attribute ***/
   $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

simple Abfrage und Ausgabe

/*** The SQL SELECT statement ***/
    $sql = "SELECT * FROM entries";

    /*** fetch into an PDOStatement object ***/
    $stmt = $dbh->query($sql);

    /*** echo number of columns ***/
	foreach ($stmt as $row){
		echo $row['uid'] . '<br>';
		echo $row['header']  . '<br>';
		echo $row['bodytext']  . '<br>';
	}

Sonstige Quellen:
http://henryranch.net/software/ease-into-sqlite-3-with-php-and-pdo/
http://www.phpro.org/tutorials/Introduction-to-PHP-PDO.html und weil alle guten Dinge 3 sind sqlite.org

Symlinks für Windows am Beispiel TYPO3

Wenn ich eine neue TYPO3 Installation aufsetze nutze ich immer die Möglichkeit der Symlink Nutzung.
hat einfach den großen Vorteil, wenn eine neue TYPO3 Version rauskommt, reicht es auch einen Symlink zu ändern und die Installation ist mit einer Frischen Version versorgt… danach natürlich noch die üblichen Update Schritte durchlaufen.
Den noch größeren Vorteil sehe allerdings darin, schnell wieder zurück zu wechseln. Bei einer größeren Seite musste ich die Möglichkeit auch schon mal in Anspruch nehmen, nach dem Switch gab es einfach eine weiße Seite und vom Frontend keine Spur mehr, schnell sysmlink wieder auf die alten TYPO3 core Dateien geändert und alles wieder da.

Bisher nutze ich immer die empfohlene Kombination

source/ <---- typo3_src-4.x/
www/   <--- Installation

www/typo3_src <--> ../source/typo3_src-4.x/
www/typo3 <--> typo3_src/typo3/
www/t3lib <--> typo3_src/t3lib
www/index.php <--> typo3_src/index.php

Bei Unix wird es umgesetzt mit folgendem Befehl

// immer das Ziel und dann den Symlink Namen
ln -s ../source/typo3_src-4.x/ typo3_src
ln -s typo3_src/typo3 typo3
ln -s typo3_src/t3lib t3lib

Also als erstes wird ein Symlink typo3_src gesetzt, dieser weißt als einziger Link auf den aktuellen Source-Ordner, die andern Symlinks bauen dann auf diesen Link auf. Bei einem Update muss dann nur dieser eine Symlink angepasst werden.

In Windows (an Vista) sieht es dann so aus:
Start -> in der suche CMD eintippen und dann auf dem Ergebniss mit Rechtsklick „Als Administrator ausführen“
dann folgendes eingeben

// hier ist es genau umgekehrt zu Unix, erst den Symlink Namen dann das Ziel
// wenn Ordner auf diese Weise geschriee
mklink /J typo3_src ..\source\typo3_src-4.x\
mklink /J typo3 typo3_src\typo3\
mklink /J t3lib typo3_src\t3lib\

// Dateien
mklink index.php typo3_src\index.php 

Damit ist auch ein Testen mit XAMPP oder ähnlich auch gut zu bewerkstelligen

Genutzte Quelle:
http://www.windows7home.net/use-mklink-command-in-windows-7/

SSH Public/Private Key zum Login nutzen

SSH Keys nutzen um sich am Terminal anzumelden:

als erstes ssh Private und Public Key erzeugen

ssh-keygen -t rsa

Speicherort mit Enter bestätigen und danah bei Wunsch ein Passwort setzen.
man erhält nun die Dateien ida_rsa (Private Key) und ida_rsa.pub (Public Key)
Die ida_rsa.pub Datei auf den Server verschieben in den Ordner .ssh
Falls dieser noch nicht existiert,anlegen und auf chmod 700 setzen.
Danach die Datei hochladen und auf chmod 600 setzen (ansonsten werden die Keys nicht genutzt), danach Datei umbenennen in authorized_keys.
Nun sollte der Login schon ohne Password klappen.

Um noch einen Schritt weiter zu gehen, verschieben wir nun unseren Private Key in einem verschlüsselten Container oder auf einen USB-Stick. Nun legen wir auf dem Client im Verzeichnis .ssh eine Datei mit dem Namen config an und darin notieren wir folgende Sachen

Host 	kurzerServerName
Hostname kompletter.server.name.de
IdentityFile /path/to/usb-stick/id_rsa
User	benoetigterLoginName-fuer-den-Server

(kann auch genutzt werden um mehrere Private-Keys zu verwalten)

Bei DF sieht ein Login immer wie folgt aus

ssh ssh-123123-1@meinedomain.de

Wenn alles erfolgreich eingerichtet ist kann ich statt dessen

ssh kurzerServerName

nutzen um mich anzumelden.

Wenn der USB-Stick oder der TrueCrypt Container allerdings nicht vorhanden sind, funktioniert der Login auch nicht

Wenn man ein PW vergibt sollte man es auch ab und durch ein neues ersetzen, dafür nutztman

ssh-keygen -p

Danach wird man nach dem Ort des Private Key gefragt und muss zweimal das neue PW eingeben

Quelle:
http://stackoverflow.com/questions/2419566/best-way-to-use-multiple-ssh-private-keys-on-one-client,
http://www.phpecho.de/git/deployment-einfach-gemacht-mit-git-hooks-1326.html
und
http://www.guyrutenberg.com/2007/10/05/ssh-keygen-tutorial-generating-rsa-and-dsa-keys/

Custom Event in JQuery

In einem Projekt wird asyncron eine JSON Abfrage gemacht und die Daten verarbeitet, das Ganze ist ausgelagert in eine separate JavaScript Datei.  Jetzt möchte ich gerne die Anzahl der zurück gegebenen Elemente auf der Seite ausgeben, dafür nutz ich der Einfachheit halber ein jQuery Schnipsel und füge die Zahl hinter einem bestimmten Element ein. Um diesen Individuellen Schnipsel jetzt allerdings nicht die Ablauf Logik der JSON Abfrage unterzubringen habe ich einen individuellen Trigger integriert und reagieren in einer anderen JavaScript Datei darauf und kann somit beiden „sauber“ von einander trennen.

$.getJSON(this.url, function (data) {
  // ... data verarbeiten

  // wenn fertig diesen CustomTrigger aufrufen
  // für bessere Zuordnung einen individuellen Namenspace nutzen
  // und dann noch die Anzahl derDaten übergeben
  $(document).trigger('AppNameSpace/ItemsCountReady', data.length );
});

In der anderen  JavaScript Datei frage ich dieses Event ähnlich einem Click-Event ab und verarbeite die übergebenen Daten.

(function(){
	$(document).on('AppNameSpace/ItemsCountReady', function(e, results){
		$('h1').after($('<p />').text( results + ' items'));
	});
})();

Quelle:
http://tutsplus.com/lesson/custom-events-and-the-observer-pattern/

Git auf df

Ich habe gerade im Zusammenhang mit df ein git gebraucht und hier einmal die Schritte step by step.

Update: 06.05.2012  htaccess Rules für .gitignore hinzugefügt

Es wird zurest lokal ein Repository angelegt was dann online verfügbar gemacht wird


git + df

auf dem lokalen Rechner ein neues Projekt anlegen

// git repository erstellen
git init

// wenn git noch nicht eingerichtet wurde
// wird beim Commit genutzt
git config --global user.name "Mein Name"
git config --global user.email meine@email.de

//kontrollieren mit
git config --list

.gitignore erstellen:
Wie man Temp Verzeichnisse behandelt
In Webprojekten hat man oft Temp Verzeichnisse. Die Inhalte dieser möchte man natürlich nicht in seinem Repository haben, aber die Verzeichnisse sollen trotzdem angelegt werden wenn man einen neuen Clone anlegt. Dies kann man mit den folgenden Zeilen in der .gitignore bewerkstelligen.

# tmp verzeichnisse
app/tmp/smarty/compile/*
app/tmp/cache/*
!.gitignore

Das /* am Ende bewirkt das nur Dateien in den Verzeichnissen ignoriert werden und nicht das Verzeichnis an sich. Da Git aber keine leeren Verzeichnisse tracken kann, legt man eine leere .gitignore in die Verzeichnisse und die letzte Zeile !.gitignore ist eine Ausnahme für diese Dateien. Die .gitignore in den Temp Verzeichnissen werden also zum Repo hinzugefügt und damit wird bei einem neuen Clone das Verzeichnis angelegt. Tipp: Wenn man Funktionen hat die Temp Verzeichnisse leeren, sollte man hier eine Ausnahme für .gitignore Dateien hinzufügen. 🙂

Quelle:http://www.phpecho.de/git/git-repository-erstellen-und-mit-den-git-server-verbinden-1300.html

// alle Dateien lokal hinzufügen
git add .

// und einchecken
git commit -m "Erster import"

// repository online schieben
// zuerst in den übergeordneten Ordner wechseln

cd ..

// ein "bare clone" erstellen (nur in ein solches soll man pushen)
git clone --bare meinAngelegtesProjekt/.git meinAngelegtesProjekt.git

//den erstellen Ordner nun auf den Server schieben
// zum Beispiel per scp (console) oder winscp(gui)

//
git remote add origin ssh://sshuser@myserver.com/kunden/xxxxxx_123456/repos/meinAngelegtesProjekt.git

//---------------
# löschen eines eingetragenen remote repos, git remote rm
$ git remote rm origin

# anzeigen welche remote repos eingetragen sind
$ git remote
//---------------

// push un pull nun per
git pull origin master
git push origin master

// bzw :
//---------------
Damit man den Namen und den Branch nicht bei jedem push/pull angeben muss, kann man seine Standards in die git config eintragen. Dann reicht ein einfaches "git push" bzw. "git pull".
view source
print?
$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master
$ git pull
$ git push
//---------------

// erreichbar auf einem anderen Rechner

git clone ssh://sshuser@myserver.com/kunden/xxxxxx_123456/repos/meinAngelegtesProjekt.git meinOrdner

Als Grundlage habe ich folgende Seiten genutzt (wirklich sehr lesenswert):
http://www.phpecho.de/git/git-repository-erstellen-und-mit-den-git-server-verbinden-1300.html

und

http://www.railshosting.de/hilfe/git

Update: 06.05.2012
Wenn die Seiten über das Web Erreichbar sind sollten die .git Ordner und dit .gitignore Files nicht erreichbar sein. Dazu folgendes in die htaccess einfügen

 <Files ~ "^\.git">
Order allow,deny
Deny from all
Satisfy all
</Files>

Quelle auch hier:
http://www.phpecho.de/git/deployment-einfach-gemacht-mit-git-hooks-1326.html

Mit cURL Short-Urls auflösen

Ich nutze gern mein Smartphone um RSS-Feeds zu abbonieren und hier und da mal ein paar Artikel zu lesen. Einige davon finde ich so gut, das ich Sie später unbedingt noch zu Ende lesen will oder daraus  etwas ausprobieren möchte. Da man mit dem Smathphone schnell und einfach Mails versenden kann, dachte ich mir das wäre ein Ansatz. Also wenn eine E-Mail bei einer bestimmten Adresse ankommt, wird sie auf einer Internetseite angezeigt, hier wollte ich allerdings keine Short-Urls mehr und da kam cURL ins Spiel.


public function getLocationHeaderFromUrl($url){

	$newUrl = '';
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_HEADER, TRUE);
	curl_setopt($ch, CURLOPT_NOBODY, TRUE); // remove body
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
	$head = curl_exec($ch);
	curl_close($ch);

	$header_lines = explode("\r\n", $head);

	foreach ($header_lines as $key => $header_line) {
		list($header, $value) = explode(':',$header_line,2);
		if($header == 'Location'){
			$newUrl = trim($value);
		break;
		}
	}

	return $newUrl;
}

Bilder invertieren mit Canvas

Für ein kleines Fun Projekt wollte ich auf einer Internetseite die Bilder von Personen  invertieren und habe dafür ein wenig mit dem Canvas Element rumgebastelt.

Bei einem Click auf einen Link wird eine zufällige Person aus dieser Liste ausgewählt, die Pixel des Bildes werden invertiert und dann wieder als dataUri zurückgegeben.

Raus gekommen ist dabei folgendes:

var person = all.eq(Math.floor(Math.random() * 5));
// bei der Erstellung des Canvas Elementes mit
// jQuery wurde die Größe nicht korrekt übernommen,
// daher auf dem "klassichem" Wege
var $canvas = document.createElement("canvas");
$canvas.width = 210;
$canvas.height = 98;
var ctx = $canvas.getContext('2d');
var img = person.get(0);
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, $canvas.width, $canvas.height);
var imageData = ctx.getImageData(0, 0, $canvas.width, $canvas.height);
var pixels = imageData.data;
var numPixels = imageData.width * imageData.height;
for (var i = 0; i < numPixels; i++) {
	pixels[i * 4] = 255 - pixels[i * 4];
	pixels[i * 4 + 1] = 255 - pixels[i * 4 + 1];
	pixels[i * 4 + 2] = 255 - pixels[i * 4 + 2];
};
ctx.putImageData(imageData, 0, 0);
// Daten wieder zurückschreiben
person.attr('src', $canvas.toDataURL('image/jpeg'));

Als Grundlage habe ich mich auf diese fantastischen Tutorials gestütz:
http://css.dzone.com/articles/html5-image-effects-sepia
http://net.tutsplus.com/tutorials/javascript-ajax/canvas-from-scratch-pixel-manipulation/