PHP-Storm kommt aus indexing loop nicht mehr heraus

Manchmal habe ich das Problem, dass der PHP Storm nicht mehr aus dem Index-Loop herauskommt. Die IDE iteriert unablässig über den selben Ordner, welcher von selbiger beliebig bestimmt wurde. Auch die Auswahl von “Mark directory as excluded” des betroffenen Ordners funktioniert nicht, da PHP-Storm dann über einen anderen Ordner loopt.

Lösung

Menüleiste: File -> Invalidate Caches/Restart anklicken und im Dialog “Invalidate and restart” wählen. Die IDE startet neu und baut der Cache neu auf. Nach dieser vollständigen Neu-Indexierung wird sich in der Regel die Endlosschleife auflösen und PHP-Storm beruhig sich endlich.

php unserialize “_php_incomplete_class” namespace

Ich habe in PHP ein unserialize() ausgeführt. Die darin enthaltenen Daten sind valide und die dazugeörige Klasse ist in meinem Framework bzw. in meiner Library enthalten. Dennoch hat das unserialize() nicht funktioniert und führte zu einem Objekt in dem die Klasse _php_incomplete_class vergeben wurde.

Sofern es zu der Zuordnung der Klasse _php_incomplete_class kommt liegt dies daran, dass die Klasse nicht gefunden werden konnte. Daher ist ein require bzw. include der jeweiligen Klasse notwendig. Ggf. sollte auch die Verarbeitung des Autoloaders überprüft werden, sofern die Klasse normalerweise automatisch geladen werden würde.

Free PHP, HTML, CSS, JavaScript editor (IDE) – Codelobster PHP Edition

For valuable work on creation of sites you need a good comfortable editor necessarily. There are many requiring paid products for this purpose, but we would like to select free of charge very functional and at the same time of simple in the use editor – Codelobster PHP Edition .
 

Free PHP, HTML, CSS, JavaScript editor (IDE) - Codelobster PHP Edition

Let us consider some important possibilities and advantages of this program:

 

  • All code highlights depending on a type, the also mixed code is thus supported, so the area of HTML will be highlighted as HTML, PHP as PHP, and Javascript as Javascript in a the same file. Thre is possibility of choice from color schemes, including popular IDEs.
  • Powerful autocompletion for HTML, PHP, CSS and Javascript, including HTML5 and CSS3. For PHP the structure of project is fully recognized, and the complete list of methods falls out in the proper places.
  • HTML/CSS inspector on the type of Firebug, which allows easily to correlate the selected elements of page with a code and proper style.
  • Context help on all supported languages. By pressing F1 key the page with detailed description for current tag, attribute or function will be opened.
  • PHP debugger. PHP debugger allows to execute PHP scripts incrementally, watching the values of all variables in every line.
  • SQL manager allows to produce all necessary actions with a database – to add, delete, edit a structure and records in tables, to export data, execute SQL queries. Highlighting and autocompletion works for SQL files also.
  • Support of FTP allows to work straight with a remote server and to do all necessary changes with files;
  • The portable option allows to use editor without the preliminary installation.
  • Other useful utilities: pair highlighting, possibility of blocks selection, collapsing, tooltips, navigation on descriptions of functions and included files at withholding of the key of CTRL, viewing of structure of files and project, preview in a browser, book-marks, and all other standard possibilities for work with a code.

Also there are special plugins for work with:

 

  • CMS: Drupal, Joomla, Magento
  • PHP frameworks: CakePHP, CodeIgniter, Symfony, Yii, Laravel
  • JavaScript: JQuery, Node.js, AngularJS, BackboneJS, MeteorJS
  • WordPress blogging engine
  • Smarty and Twig template engines
Developer Codelobster Software
Web Site http://www.codelobster.com/
Language English, Russian, German, Spanish, French, Portuguese

Download link:

Free PHP, HTML, CSS, JavaScript editor (IDE) – Codelobster PHP Edition

Debugging in PHP

Debuggen von PHP-Applikationen war für mich in den letzten 14 Jahren stets das Buch mit den sieben Siegeln. Auch kenne ich zahlreiche PHP Entwickler denen es damit genau so geht. Dass PHP nunmal als Interpretersprache nicht von Haus aus Debugging mit der IDE bereitstellt, hat es der Sache daher nie leicht gemacht. Aus diesem Grund habe ich mich in den letzten Jahren mit Debugging nie beschäftigt. Ich tat dies immer wieder als komplexes Hexenwerk ab und knüppelte es als unausgereift nieder. Damit begab ich mich – nur um mich selbst zu beschönigen – stets mit File-Logging und echo bzw. var_dump()-Ausgaben zufrieden.

Jedoch sind die gewonnen Erkenntnisse einer Debugsession unermesslich, da man zur Laufzeit exakt sehen kann welche Werte eine Variable in bestimmten Situationen beinhaltet. Ich habe seit Einrichtung dessen viele Stunden an Mühen mir ersparen können, da die erkannten Abläufe in einer Debugsession deutlich früher zu verwertbaren Resultaten führen.

Das kann nun ein Ende auch für Dich haben, denn die Einrichtung mittels X-Debug und der IDE PhpStorm ist denkbar einfach.

Grundsätzliches

Die hier vorgestellte Konfiguration betrifft erst einmal PhpStorm, jedoch kann ich mir vorstellen, dass diese unter Eclipse sowie den anderen gängigen IDEs mit nur minimal abweichenden Konfigurationseinstellungen vorzunehmen sein sollte. Denn die hier zugrunde liegenden Grundeinstellungen und Konzepte sind für alle die gleichen.

Für die Einrichtung und der Benutzung des Debuggers werde ich zum einen für den Abruf im Firefox-Browser, des weiteren auf der Linux-Konsole sowie abschließend im Rest Client – welcher in PhpStorm als Plugin installiert werden kann – beschrieben. X-Debug wurde als Modul auf einem Linux Server installiert und aktiviert und ich kann die Konfiguration nun in folgende Punkte zusammenfassen:

Servereinrichtung

Um X-Debug auf dem Server einzurichten bedarf es lediglich der Modulaktivierung in der php.ini:

zend_extension = /opt/remi/php73/root/usr/lib64/php/modules/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=0
xdebug.remote_handler=dbgp
;xdebug.remote_host=192.168.1.10 <-IGNORE THIS+USE remote_connect_back
xdebug.remote_connect_back=1
xdebug.remote_port=9000
xdebug.idekey=PHPSTORM
xdebug.remote_log=/tmp/xdebug.log

Durch Aktivierung der Option remote_connect_back wird automatisch IP-Adresse des anfragenden Browsers verbunden. Dies funktioniert in den meisten Fällen wunderbar und kann problemlos in lokalen Netzwerken aktiviert werden.

Einrichtung in PhpStorm

  • Settings öffnen und zu Debugger wechseln
    • XDEBUG PHP-IDE Key setzen: PHPSTORM
    • Port 9000 und 9001 wählen
    • Force break zunächst aktiviert lassen, jedoch im täglich Gebrauch deaktivieren. Man will ja nicht ernsthaft, dass bei jedem Abruf der Debugger in der ersten auszuführenden Zeile anhält
  • Debugger einrichten (Run/Debug Configurations)
    • Neue „PHP Web Application“
      • Neuen Server eintragen: URL und Port 80
      • Start URL: „/“
      • Pathmapping aktivieren
        • Hauptverzeichnis mappen mit dem jeweiligen serverseitigen Pfad
        • Gegebenfalls Unterverzeichnis auf weiteren Pfaden mappen.
      • Es wird eine Einstellung für http und https benötigt, falls https nicht erstellt wurde, macht dies PHP-Storm eigenmächtig, muss jedoch dann auch wie o.g. konfiguriert werden
    • Neue „PHP Remote Debug“
      • Servers hinzufügen („…“ wählen) und neuen Server hinzufügen
        • Servername setzen
        • Hostname setzen
        • Port kann auf 80 gesetzt werden
        • Pathmapping wie o.g. aktivieren
      • Den IDE-Key belegen mit „PHPSTORM“
    • Im Debugger springt PhpStorm in den Standardeinstellungen beim Start einer neuen Debugsitzung immer wieder in die Console. Mit Rechtsklick auf den Tab die Einstellung „Focus on startup“ abwählenPHPStorm

Für den ersten Debug muss entweder ein beliebiger Breakpoint gesetzt werden bei dem der Debugger anhält. Alternativ kann im Menü -> Run die Option “Break at first line in PHP scripts” gesetzt werden. Dies jedoch ist für den alltäglichen Gebrauch nicht geeignet, außer man weiß zu Beginn rein gar nicht wohin der Abruf geroutet wird oder man wissen möchte welche Stellen noch relevant sind für die Ausführung sind.

REST Client (PhpStorm)

  • Header setzen
    • Accept: */*
    • Cache-Control: no-cache
  • Request Parameters XDEBUG_SESSION_START hinzufügen
    • Der Inhalt dieser Variable kann beliebig gesetzt werden und sogar leer bleiben
    • Dieser Wert wird serverseitig zu einem Cookie
  • Request zusammensetzen
    • Methode setzen (GET, PUT, POST, HEAD, DELETE)
    • Host setzen
    • Path mit dem Pfad und dem Zielskript befüllen
  • Debugger starten (Icon mit Telefonhörer)
  • Request absetzen

Firefox Browser

  • Plugin “The easiest Xdebug” installieren
  • IDE-Key eintragen: netbeans-xdebug
  • Debugging durch Seitenabruf initiieren

Einrichtung im Chrome

  • Die App “Header Hacker” über den Chrome Webstore suchen und installieren
  • Unter “Custom Request Headers” einen Eintrag einstellen:
    • Title: X-Debug
    • Header: Cookie
    • Append/&Replace: Append
    • String: XDEBUG_SESSION=PHPSTORM
    • Match String: #LEER LASSEN#
  • Unter „Permanent Header Switches“ ebenfalls einen neuen Eintrag einstellen:
    • Domain: Domain eintragen unter welcher der Header mitgesendet werden soll – z.B. http://debug.moderlak.de
    • Header Switch: Auswählen des oben eingetragenen Wert
  • Nachteil: Der Header muss immer manuell pro Domain konfiguriert werden und er wird immer mitgesendet. Daher schaltet man am besten den Debugger in der IDE ein und aus.

CLI Debugging

Die .bashrc wie folgt konfigurieren

Einrichtung der .bash.rc

Festlegen der CLIENTIP um die Verbindung zur lokalen IDE zu definieren und einen Alias um PHP-Skripte mit den umfassenden Parametern zu starten:

CLIENTIP=$(w|egrep -o "$USER\W*pts/([0-9]{1,3})\W*(([0-9]{1,3}).){3}.([0-9]{1,3}).*" | head -n1 | awk "{print \$3}")
# Alternative wenn anstelle der IP-Adresse der Computername im Netzwerk angezeigt wird - dies funktioniert zuverlässig wenn nur ein Benutzer mit dem Server per SSH verbunden ist:
# CLIENTIP=$(netstat -tn 2>/dev/null | grep :22 | awk '{print $5}' | grep -v :22 | cut -d: -f1 | sort | uniq | sort -nr | head)

alias xphp="XDEBUG_CONFIG=\"idekey=PHPSTORM\" PHP_IDE_CONFIG=serverName=\"$HOSTNAME(CLI)\" php -d \"xdebug.remote_host=$CLIENTIP\" -d \"xdebug.remote_connect_back=0\" -d \"xdebug.remote_port=9000\" -d \"xdebug e_enable=1\""

CLI Debugging lokal unter Windows

Inzwischen wurde ich auch dazu genötigt unter Windows zu debuggen, welches jedoch nicht im Browser, sondern nur auf der Konsole ausgeführt wird. Dies einzurichten und zu nutzen ist allerdings recht einfach und bedarf nur weniger Schritte der Konfiguration.

Hierfür muss zunächst die Extension heruntergeladen und in das Unterverzeichnis von php unter “ext” abgelegt werden. Die DLL erhält man von https://xdebug.org/ aus der Sektion Download.

In der php.ini wird die Extension als “zend_extension” aktiviert mit dem Namen der geladenen DLL-Datei.

Dann legt man lokal für den eigenen Benutzer eine neue Umgebungsvariable wie folgt an:

Name: XDEBUG_CONFIG
Wert: remote_enable=1 remote_mode=req idekey=PHPSTORM

Abschließend wird nun in dem zu debuggenden Skript in der IDE ein Breakpoint gesetzt und das Skript einfach via php aufgerufen. Es sind keine weiteren Parameter notwendig.

Troubleshooting

Jedes beliebige PHP-Skript kann nun mit xphp myscript.php anstelle von php myscript.php gestartet werden. Dabei werden die notwendigen Header dem Skriptabruf angehangen, die das Debugging initiieren und man somit durch den Code navigieren kann.

Wenn es mal nicht so läuft wie gewünscht habe ich mal die typischen Fehlermeldungen zusammengetragen:

  • Nach der Formularabsendung blockiert der Browser und zeigt nur noch den Hinweis: “Fehler: Gesicherte Verbindung fehlgeschlagen“
    • Problem: Debugging im PhpStorm aktiviert und Cookie XDEBUG_SESSION wird vom Browser gesendet. Dies passiert mir besonders häufig mit dem Plugin “The easiest Xdebug”. Mit einem Klick auf das Icon um den Cookie ein/auszuschalten ist nicht ausreichend, da der Cookie nicht mehr entfernt wird.
    • Lösung: Den Listener für Debugging im PhpStorm abschalten und den Cookie XDEBUG_SESSION im Browser explizit entfernen und Seite erneut abrufen.
  • CLI-Modus: PHPStorm antwortet nicht auf Debugrequest obwohl alle Daten korrekt eingegeben
    • Problem: Die lokale IP-Adresse des Clients im xphp-Aufruf unter xdebug.remote_host ist veraltet
    • Lösung: bashrc neuladen mittels: source ~/.bash.rc 

Diese Liste der Fehler wird im Laufe der Zeit gegebenenfalls erweitert.

Fazit

Mein Entwicklerdasein hat sich seit dieser Einführung um 180 Grad gewandelt, denn Probleme kann ich seither viel früher erkennen. Beim Durchlauf des Programms werden Erkenntnisse zu Tage gefördert, welche beim sonst üblichen Komplettdurchlauf nur selten sofort ersichtlich sind.
Auch lassen sich mögliche Fehler hiermit sehr schnell aufspüren und exakt analysieren.

Releasewechsel in PHP

Offensichtlich stellt die Auslieferung ein neuen Releases in einigen PHP-Projekten einen hohen manuellen Aufwand dar, da Dateien über die bestehende Installation mehr oder weniger manuell kopiert werden. Dabei müssen selbstverständlich zu löschende Dateien und Ordner berücksichtigt werden, sowie ist darüber hinaus dieser Vorgang nur vorwärtsgerichtet und kann im Falle eines massiven Fehlers nur zurückgerollt werden sofern eine Komplettsicherung vorliegt.
Zu guter Schluss kann dieser manuelle Vorgang mehrere Minuten bis sogar Stunden in Anspruch nehmen und damit eine längere Downtime der Webseite bzw. des Services einfordern. Je nach Projekt kann dies unerwünscht und in Folge dessen auch noch mit hohen Kosten verbunden sein – zum einen durch Personalkosten sowie zum anderen der Nichtverfügbarkeit und dem damit verbundenen Nutzungsausfall. Wer zur Krönung dann noch eine ganze Farm von installierten Applikationen zu aktualisieren hat wird letztlich seinen Aufwand nochmal um die Anzahl der Hosts multiplizieren dürfen.

In diesem Sinne: Prost Mahlzeit!

Releasewechsel in PHP weiterlesen

isset() Prüfung schlägt fehl

Die Prüfung auf definierte Schlüssel in einem PHP-Array kann wie folgt vorgenommen werden:

$data = array(
    'id' => 4711,
    'value' => NULL
);

if( isset( $data['id'] ) ) {
 echo "id existiert!\n";
}
if( isset( $data['value'] ) ) {
 echo "value existiert!\n";
}

Es kann jedoch vorkommen, dass hinter einem Eintrag der Wert NULL gespeichert ist. Die Funktion isset() wird dann das Vorhandensein des Eintrags dennoch als FALSE werten und damit wird dem Entwickler bzw. dem ursprünglichen Programmfluss weisgemacht, dass der Eintrag nicht vorhanden ist und mit dieser falschen Annahme die Programmausführung fortsetzen und zu unbegreiflichen Ergebnissen führen. isset() Prüfung schlägt fehl weiterlesen

Referenzen in PHP

Wer braucht schon Referenzen in PHP? Wenn man nun alles in PHP elegant via objektorientierter Programmierung erledigt ist diese Frage eigentlich gar kein Thema für den Alltag.

Was aber tun wenn man nun doch damit konfrontiert wird, so stelle ich fest, dass man die Referenzierung sowohl bei der Definition als auch beim Abruf explizit aufzeigen muss. Referenzen in PHP weiterlesen

Umstellung mysql auf mysqli

Mit PHP 5.5.0 wurden die alten mysql-Funktionen als deprecated markiert und seit PHP 7.0.0 gänzlich entfernt. Da inzwischen immer mehr Provider ihr Hostingangebote auf PHP 7 aktualisieren stehen diese Funktionen ab dieser Version dann gar nicht mehr zur Verfügung. Daher muss eine Umstellung dieser in den eigenen Projekten zwingend eingeplant werden. Dafür habe ich an dieser Stelle eine umfängliche Schritt-für-Schritt Anleitung zusammengestellt, welche bei sorgfältiger Abarbeitung einen innerhalb kurzer Zeit ziemlich sicher zum Ziel führt.

MySQL: Das umfassende Handbuch

Die Umstellung der mysql_*-Funktionen auf mysqli_*-Funktionen geht relativ reibungslos vonstatten, sofern man eine zentrale Verarbeitung der Datenbankabfragen implementiert hat. Ist dies nicht der Fall so wird sich der hier aufgeführte Aufwand um die Anzahl der zu behandelnden Stellen zuzüglich der notwendigen Tests in ungefähr multiplizieren.

Umsetzung

Für die Umstellung des eigenen Adapters muss man sich den nachfolgenden Punkten in jedem Einzelfall gesondert widmen und kann dazu wie folgt vorgehen:

  1. Im ersten Schritt ersetzt man alle mysql_ Funktionsaufrufe mit einem mysqli_. Das nachfolgende Suchpattern eignet sich hierfür sehr gut:
    /mysql_([a-z_]+)\(/
  2. In der Funktion mysqli_connect() werden ab dem vierten Parameter Port und Socket erwartet anstelle von link und clients. Sofern diese angegeben wurden müssen diese zunächst entfernt werden. Haben diese Angaben bisher darüber hinaus noch Relevanz gehabt so müssen jene an dieser Stelle gesondert behandelt werden.
  3. Die Funktionen mysqli_query()mysqli_error(), mysqli_escape_string() und mysqli_real_escape_string() benötigen nun zusätzlich die Angabe der Ressource. Dies kann für die beiden zuletzt genannten Funktionen an den Stellen problematisch werden, an denen eine Verbindung möglicherweise noch nicht hergestellt wurde oder die Ressource gar nicht erst verfügbar ist. Hier muss sichergestellt sein, dass diese vor dem ersten Aufruf aufgebaut wurde.
  4. In der Funktion mysqli_select_db() sind von nun an die beiden Parameter für Ressource und DB-Name vertauscht.
  5. Die vier Funktionen mysqli_fetch_assoc()mysqli_fetch_row()mysqli_fetch_object() und mysqli_fetch_array() liefern im Fall eines leeren Ergebnisses nun NULL wo ihre mysql-Pendants  hingegen bisher den Wert FALSE zurückgegeben haben.
  6. Andersherum jedoch liefert die Methode mysqli_stat() fortan FALSE anstelle von NULL sofern die Datenermittlung erfolglos stattgefunden hat.
  7. Prüfungen auf is_resource() sind nicht mehr möglich da der mysqli-Adapter keine PHP Ressourcen mehr darstellen sondern interne Klassenrepräsentationen.
    Konstrukte dieser Art:
    if( is_resource( $this->_link ) {     // ... }
    müssen überarbeitet und ersetzt werden gegen folgende Logik:
    if( $this->_link instanceof mysqli ) {     // ... }
  8. Die Funktion mysql_field_name() kann nicht ersetzt werden, da das entsprechende Pendant nicht existiert. Man muss es durch den nachfolgenden Schnipsel, Umsetzung in einer Klasse vorausgesetzt, ergänzen:
    private function field_name( $offset ) {
       $properties = mysqli_fetch_field_direct( $this->result, $offset );
       return is_object( $properties ) ? $properties->name : null; 
    }
    Anstelle von mysql_field_name( $resource, $offset ) erfolgt der Aufruf nun mit $this->field_name( $offset ).
  9. Der Abruf der Methoden mysqli_stat() und mysql_error() ohne Parameter ist nun nicht mehr zulässig und es muss die Ressource künftig mit angegeben werden.

Fazit

Ich stelle fest, dass eine Umstellung auf mysqli keine zeitaufwändige Angelegenheit ist und mit den wenigen notwendigen Tests innerhalb eines halben Arbeitstages nahezu mühelos erledigt werden kann.

Weiterführende Literatur