Archiv der Kategorie: PHP

PHP: includes

Mit PHP stellt sich von Zeit zu Zeit die Frage, warum includes nicht funktionieren. Einige Möglichkeiten zur Problemlösung:

Mit folgendem Script den aktuellen Kontext ausgeben, in dem man sich befindet:

<?php
dirname($_SERVER["SCRIPT_FILENAME"])
?>
Das gibt das Verzeichnis des ausführenden Scripts. Das ist einzig relevent, nicht die Datei, welche den Include macht.
Bei Fehlermeldungen bezüglich fehlender Berechtigung (permission denied) ist folgendes zu beachten:
– Die Datei, die eingebunden werden soll, muss das R-Flag (Berechtigung Lesen) besitzen
– Alle über der einzubindenden Datei liegende Verzeichnisse müssen das X-Flag (Berechtigung Ausführen) besitzen
Damit sollten die Fragen geklärt sein 🙂

Passwort als Hash: Salt beachten

Problem: beim Erstellen der Datenbank-Tabellen soll gleich ein Benutzer mit einem (komplizierten) Standard-Passwort erstellt werden. Der mit der mySQL-Funktion SHA1() erzeugte Hash ist jedoch ein anderer, als CakePHP beim Login generiert (und damit die Berechtigung überprüft).

Lösung: standardmässig wird noch ein sog. Salt-Wert mit dem Passwort verwendet. Dieser ist im Konfigurationsfile core.php definiert. Um nun den Hash des Passworts zu erzeugen ist folgender PHP-Aufruf nötig:

sha1($salt.’password‘)

wobei $salt dem Salt-Wert entspricht 🙂

Opfer der Wirtschaftskrise: Zookoda

Untenstehender Screen hat mich beim Besuch von Zookoda begrüsst. Ich habe den Dienst zwar nie verwendet, per Zufall aber wieder einmal darauf gestossen. Ich denke, die wirtschaftliche Realität wird noch einige Unternehmen an den Rand der Existenz bringen. Wenn keine richtige Strategie vorhanden ist, wie Geld verdient wird, kann ein kostenloser Service auf Dauer m.E. nicht betrieben werden. Werbung dürfte nur bei wirklich grossen oder speziellen Diensten ausreichend  sein. Bei Twitter frage ich mich schon länger, wie bzw. wie lange das (noch) gut gehen kann.

zookoda

PHP Notice on line 0: Mailbox is empty

Kürzlich hat mich folgende PHP-Meldung verunsichert:

Notice: Unknown: Mailbox is empty (errflg=1) in Unknown on line 0

Die Meldung erscheint am Ende des Scripts, nachdem die Verbindung zur Mailbox getrennt wurde. Die Zeilennummer ist nicht wirklich aussagekräftig. Ursache: beim Trennen der Verbindung mit der Mailbox werden noch alle nicht ausgegebenen Fehler (?) verarbeitet und ausgegeben. Wenn man davor den Befehl imap_errors() aufruft, wird diese notice nicht ausgegeben.

Warum kann ich mir nicht schlüssig  erklären, es wird auch auf http://ch.php.net/manual/de/function.imap-errors.php (siehe Kommentar) nicht exakt beschrieben. Vielleicht hat jemand eine bessere Erklärung?

WordPress: seltsame Sicherheitsschlüssel

WordPress ist schon sehr suspekt. Ich habe mich ja noch nie näher mit dem Code befasst. Aber wenn in der config vier Sicherheitsschlüssel definiert werden müssen, kann doch etwas nicht stimmen. Wie gesagt, ich kenne den Sinn dieser Schlüssel nicht und habe mich auch nicht damit befasst. Aber ich kann mir nicht erklären, was das soll.

Nun bin ich hier auf eine Meldung gestossen, dass in einer deutschen WordPress-Version eine dieser Schlüssel fehle. Die Konsequenz könne ein gehacktes Blog sein. Von der Anwenderfreundlichkeit bezüglich dieses Schüsselhandlings sage ich jetzt nichts. Diese Schlüssel habe ich auf allen Blogs natürlich gleich überprüft und die Schlüssel gesetzt. Trotzdem frage ich mich, was an dieser Software falsch sein muss, dass die Sicherheit an einer solch lausigen Konstante hängt. Vielleicht kann mir das mal jemand, kurz und knapp in zwei Sätzen erklären? Ich nehme mir vor, dieser Sache bei Gelegenheit einmal nachzugehen. Denn es beunruhigt schon irgendwie.

T3: tw_rssfeeds reloaded

Bereits früher habe ich Verbesserungen für diese TYPO3-Extension erläutert (https://gebloggt.ch/?p=368). Nun wurde die Extension völlig „nutzlos“, da mit ausgeschaltetem allow_url_fopen von PHP nichts mehr funktionierte.

Ich zitere das problematische Stück code aus der Datei pi1/class.tx_twrssfeeds_pi1.php:

function xml_file($file) {
if (!($fp = @fopen($file, „r“)))
$this->error(„Kann XML-Datei <b>“.$file.“</b> nicht öffnen“);

while ($data = fread($fp, 4096)) {
if (!(xml_parse($this->parser, $data)))
$this->error(„XML-Output: „.xml_error_string(xml_get_error_code($this->parser)));
}

xml_parser_free($this->parser);
}

Natürlich geht das mit der erwähnten PHP-Option nicht. Verbessert (ich weiss, wieder etwas workaround-mässig):

function xml_file($file) {
require_once(„HTTPRequest.php“);
$httpReq = new HTTPRequest($file);
$data = $httpReq->DownloadToString();

if (!(xml_parse($this->parser, $data))) {
$this->error(„XML-Output: „.xml_error_string(xml_get_error_code($this->parser)));
}

xml_parser_free($this->parser);

}

Die Klasse HTTPRequest.php ist etwas ähnliches wie die entsprechende PEAR-Klasse, jedoch etwas einfacher zu benutzen. Und man kann damit den Inhalt externer URLs abrufen, ohne dass allow_url_fopen auf true gesetzt sein muss. Quelle der Klasse: http://www.php-resource.de/forum/showthread/t-65376.html

Ich hab die Klasse auch schon bei anderen Applikationen gebraucht, um externe Files mit PHP zu öffnen. Hat bisher sehr gut funktioniert. Für eine schöne Lösung müsste man dies ev. in die Extension einbauen, da so eine externe Datei nicht so elegant ist.

Ausserdem hat der im Beitrag zitierte Code noch einen kleinen Bug. Die Variable response (in der Funktion DownlaodToString() wurde nicht deklariert und initialisiert. Das

$response.= fread(…)

erzeugt dadurch einen Notice von PHP.

Also kurz:

  1. pi1/class.tx_twrssfeeds_pi1.php anpassen, hochladen
  2. HTTPRequest.php erstellen und ins selbe Verzeichnis hochladen (ggf. $response noch deklarieren).

Damit sollte die Extension wieder funktionieren. Bei mir läuft die Sache prima.

Pagination mit CodeIgniter

Seit einiger Zeit verwende ich das PHP-Framework CodeIgniter zur Erstellung einer Web-Applikation. CodeIgniter bringt für das sog. Pagination (zeigt sowas ähnliches wie

« First < 1 2 3 4 5 > Last »

zum Darstellen grosser Listen auf mehrern Seiten) eine coole Library mit.

Kurzes Tutorial zur Verwendung der Pagination-Library mit zusätzlichen Argumenten (sort order, sort direction):

1. Erstellen der Links:

$this->load->library(‚pagination‘);
$config[‚base_url‘] = base_url().’/controller/index/‘.$data[’sortCol‘].’/‘.$data[’sortDir‘].’/‘;
$config[‚uri_segment‘] = 5;
$config[‚total_rows‘] = $this->model->getNofRecords($id);
$config[‚per_page‘] = $this->config->item(‚itemsPerPage‘);
$this->pagination->initialize($config);
$data[‚links‘] = $this->pagination->create_links();

Damit wird in $data [‚links‘] die Links für das Navigieren gespeichert. In base_url wird die URL angegeben, an die anschliessend das Pagination-Argument (=start index) angehängt wird. Nach der Variable sortCol und sortDir wird eine Zahl angehängt, welche den Startindex darstellt. uri_segment muss in diesem Fall 5 sein, da dieser Startindex das 5. Segment sein wird (controller ist 1.). total_rows wird aus der Datenbank gelesen (insgesamte Anzahl Datensätze), per_page wird aus der Konfiguration gelesen.

2. Konstruktor des Controllers

Der Konstruktor des Controllers nimmt 3 Argumente auf: sortCol, sortDir und startIndex. Alle drei haben Default-Werte, müssen also nicht zwingend mitgegeben werden. Insebesondere das letzte Argument (startIndex) sollte einen Default-Wert haben, da auf der 1. Seite die Pagination-Library keinen Wert mitgibt:

function index($sortCol=’vehicle.carNumber‘,$sortDir=’ASC‘, $startInd=0){…

Die Parameter werden in internen Variablen gespeichert bis zur Verwendung.

3. Verwendung:

Dem Model werden die obigen drei Parameter mitgegeben. Der Aufruf sieht folgendermassen aus:

$data[‚data‘] = $this->model->getList($id, $this->sortColumn, $this->sortDirection, $this->startIndex);

4. Das Model

Im Model wird die Query mit dem Limit-Operator angereichert:

$this->db->select(‚field‘)->from(‚table‘)->Where(‚user_id‘, $user_id)->order_by($sortColumn, $sortDirection)->limit($this->config->item(‚itemsPerPage‘), $startIndex);

PHP Frameworks

Kürzlich wurde ein neues PHP-Framework vorgestellt, auf dem TYPO3 5.0 basieren wird. Es hat den Namen flow3.

Persönlich habe ich meinen Entscheid bereits vor einigen Wochen getroffen. Die Wahl ist auf CodeIgniter gefallen. Die durchgehend vorhandene MVC-Architektur gefällt mir sehr. Meine erste grössere Webapplikation damit ist in Arbeit. Einige Tipps und Anfangs-Hürden werde ich in einem späteren Post beschreiben.

Hinter CodeIgniter steht die Firma  EllisLab Inc.. Doch die Software ist OpenSource und wird auch weiterentwickelt. Erst gerade (Ende Januar) wurde die neue Version 1.6 des Frameworks veröffentlicht. Von CodeIgniter gibt es jedoch auch einen Fork. Das Framework heisst kohanaPHP und ist noch ziemlich ähnlich wie CodeIgniter. Grosse Unterschiede sehe ich auf den ersten Blick nicht. Zurzeit ist CodeIgniter noch besser dokumentiert. Als Grund für die Abspaltung wird übrigens die Schirmherrschaft von EllisLab angegeben. kohanaPHP soll ein „echtes“, von der Community entwickeltes Framework werden. Ich finde: Konkurrenz hat noch nie geschadet. Und diese Entwicklung zeigt gerade das Potential und Anhängerschaft, die hinter diesen beiden Frameworks stehen.

Ich werde die Entwicklung der PHP-Frameworks interessiert weiterverfolgen. Und ich kann mir auch jederzeit vorstellen, für neue Projekte andere Frameworks einzusetzen, wenn es die Anforderungen verlangen. Für die „grossen“ (symfony und cakePHP) habe ich zurzeit noch keinen Bedarf, da CodeIgniter meine Bedürfnisse gut abdeckt.

Wer übrigens eine Übersicht von PHP-Frameworks sucht, dem sei folgender Link empfohlen: http://www.masterbootrecord.de/blog/… Wenn man CodeIgniter noch hinzunimmt, ist die Auflistung beinahe komplett 😉