Archiv der Kategorie: PHP

Get started with PHP + MariaDB on Windows

Even the longest journey starts with the first steps…

– Some wise guy

Welcome

Hej you 👋, you want to start your developer career with php and you have no clue how to start and you do not want to pay hundreds or more dollars to start?

No problem, welcome to this post.

First: You do not have to pay anything to get started and make your first steps. All you need is a computer with windows (for this tutorial) and an internet connection (you can read this, you sure have one 😉). And some time …. time is your currency to get into this developer thing.

PHP

To install php, you need to download it from the windows download section of the php homepage. Go to https://windows.php.net/download/ and choose your desired version. I recommend using the latest x64 „threat safe“ version – in most cases, this is the second option to download. You will propably learn about „thread safe“ and „non-thread safe“ in the future, but for starting, choose the „thread safe“ one 😉.
Download the ZIP file!

Once downloaded, unzip it to a destination you like. I do have my php in „d:\php“ but the coise is up to you. Once you unzipped it, remember the file path to your php.

Now, you have downloaded php and unzipped it, but you will not be able to work with it properly. We have to setup the „path“ variable to your installation.

⚠ I assume you to be on at least Windows 10 for the next steps, for older versions locations may differ.

Open your system settings by pressing `Win` (the windows logo key) and `i` the same time. In the search field, type `path` and chose `edit system variables`. Chose the middlest tab called „Advanced“ and on the bottom there, click on „System variables„.

You see a new dialog, in the lower one search for „PATH“ and double-click that. Say „New“ and insert the path to your php installation. After that click on „Ok“ and close all dialogs with „Ok“. A reboot might be required (never had that, maybe you need to do it, just saying).

You can test it simply by opening your console (right click onto the windows-logo and chose „PowerShell“) and type `php -v`. You should get a result like this:

If you get an error, check the path you entered in your `path` variable; maybe you are the one who needs the reboot!

So, php is installed and ready to run 👏.

MariaDB

The next thing you will need is a local database. For this MariaDB is a very good choise. It’s a fork of MySQL and full compatible with it … and on top: it’s free for you as learner 😉.

Go to https://mariadb.org/download and choose your favorite. I recomend using the default (latest version, x64, Windows, MSI Package) for this is the easiest to start with.

After downloading, installed it as normal. The installer will ask you to setup a passwort for the `root` user … for this is a local installtion you can also leave it empty; in all cases, you will need this password in your code often, so choose one you do remember!

Ok, MariaDB is also installed now 👏

If you courious how to start it: In the installtion you hopefully set it up as service, so just hit your windows-key, type „service“ and start the „services“ app, there you will find a service called „MariaDB“ and you can start/stop/reload it from there.

Connecting to MariaDB from php

When ever you want to connect from your php to your MariaDB and you let the setup use all as default, your database is reachable with

Host 127.0.0.1
Username root
Passwort whatever you setup
Port 3306

Simple as that.

Next steps?

Now, you are ready to develop great things with php and a database. Let’s finish this post with another quote:

Build something great!

– Some other wise guy

How to fix „SSL certificate problem: unable to get local issuer certificate“ on Windows

Du weißt bestimmt, dass ich auf Windows entwickle. Im Gegensatz zu vielen, die auf Macs oder Linux schwören, bleibe ich hartnäckig auf Windows – auch wenn dies bedeutet, dass ich Probleme sehe, die für andere unsichtbar sind. Ich sehe da allerdings die Chance, mehr zu lernen.

Eins dieser „mehr lernen“ Erfahrungen hatte ich heute. Meine phpunit tests laufen automatisch bei github und travis durch, keine Fehlermeldungen, alles gut.
Bis ich dann eben die Tests auf meiner Konsole ausführen wollte:

Anstelle des Erwarteten Fehlers SSL: no alternative certificate subject name matches target host name 'domain.xyz' erwartet mich:

SSL certificate problem: unable to get local issuer certificate

Wie seltsam … jetzt starte ich phpunit mal in meiner WSL Umgebung und siehe da, die Tests laufen alle durch. Das wieder so ein „Typisch Windows“ Problem.

Die Ursache liegt darin, dass du bei Windows-PHP-mit-Curl keine Zertifikatsinformationen per default eingestellt hast … das kann jetzt gut und schlecht sein, auf jeden Fall führt das zu dem Fehler.

Es gibt dazu allerdings auch eine Lösung und die funktioniert recht einfach:

1. Downloade gültige Zertifikatsinformationen von https://curl.se/ca/cacert.pem
2. Benenne die Datei um in curl-ca-bundle.crt
3. Kopiere die Datei, wo du sie gut verwalten kannst, bei mir liegt die in D:/www
4. Editiere deine php.ini. Du musst folgende Einträge ändern:
4.1. curl.cainfo = D:/www/curl-ca-bundle.crt
4.2. openssl.cafile=D:/www/curl-ca-bundle.crt
5. Speichern und Apache neu starten

Und nun laufen auch meine Tests durch 💪

 

Zend Framework, Windows und das Model

Wer unter Windows entwickelt hat es oft nicht leicht, obwohl es eigentlich unter Windows alles leichter sein sollte. Aber gerade diese „alles ist leichter“ Sachen machen es einem Entwickler manchmal schwer. Schwer, den Fehler zu finden.

Beim Zend Framework (v1.x) hat man gewisse Namenskonventionen einzuhalten. Ist einfach so. Eine dieser Konventionen betrifft die Möglichkeit, Klassen automatisch zu laden. Dazu müssen diese einem bestimmten Namensmuster folgen und in einem bestimmten Verzeichnis liegen. Der Entwickler spart sich dann das lästige „require…„. Nettes Feature.

Unter Windows aber bitte aufpassen!
Schnell kommt es zu einem „Fatal Error„, weil die Datei nicht gefunden werden konnte, obwohl diese eigentlich im richtigen Verzeichnis liegt. Und im lokalen Development-System funktioniert doch alles. Server kaputt? Mitnichten!

Aufbasse: Unter Windows ist es völlig egal, welchen „case“ die Verzeichnisse und Dateinamen haben. Ein Verzeichnis „model“ ist für Windows das gleiche wie ein Verzeichnis „Model„. Das ZF würde in einem Windows-Server in beiden Fällen problemlos dein Model finden (mal vorausgesetzt, der Rest entspricht den Namenskonventionen), ein Linux-Server (und das ist der Normalfall) findet bei „model“ dein Model aber eben nicht.

Lösung: Nenn das VZ „Model„, lösch das alte VZ „model“ auf dem Server und achte nächstes Mal gut darauf. Vor allem du, Sascha 😉

Von phpUnit zu Codeception wechseln

Codeception-LogoWenn du vom klassischen phpUnit zu Codeception wechseln möchtest, musst du erschreckend wenige Sachen beachten. Dafür bekommst du am Ende dann die vielen Vorteile von Codeception. Ob sich das für dich und dein Projekt lohnt, musst du latürnich (sic!) selbst für dich und dein Projekt entscheiden. Mir fiel die Wahl leicht…

Wie ich schon sagte, es braucht erschreckend wenig, damit Codeception die Tests übernimmt, da sich der „unit“ Teil nicht sooo stark von phpUnit unterscheidet. Ganz im Gegenteil ruft Codeception auch phpUnit unter der Haube auf. Du hast nur den Vorteil einer einheitlichen Test-Strategie und -Sprache und musst nicht eine Vielzahl von Dialekten behalten (phpUnit, Selenium, wtf, …).

Ich nehme mal an, dass deine unit-tests bereits funktionieren und dass diese im verzeichnis „tests“ liegen. Falls nicht, das „tests“ Verzeichnis solltest du schnell mal anlegen und deine Tests von dort aus starten 😉 Dann wird’s leichter.

Also los, die ersten Erfolge sind schnell gemacht:

  • Codeception „installieren“
    Sprich, die „codecept.phar“ ins root deines Projektes kopieren.
  • Per Konsole (phpStorm hat die ja eingebaut, sehr praktisch)
    „php codecept.phar bootstrap“
    Nun werden Grundlegende Sachen im Verzeichnis „tests“ angelegt.
  • Kopiere deine alten tests mit einer Sinnvollen Verzeichnisstruktur in das Verzeichnis „tests/unit“
  • benötigte Datenbank-Dumps kommen erstmal in „tests/_data/dump.sql“
  • Deine „tests/unit.suite.yml“ sollte in etwa so aussehen:
    class_name: CodeGuy
    modules:
     enabled: [Unit, CodeHelper, Db]
     config:
      Db:
       populate: true
       cleanup: false
  • In der „codecept.yml“ trägst du die Datenbankzugangsdaten für die tests ein, dann brauchst du die nicht in der „unit.suite.yml“ eintragen und die gelten somit codeception-weit, was später die Function- und Acceptance-Tests vereinfacht.
  • In deinen Tests musst du nun noch folgende Anpassungen machen, damit alles reibungslos funktioniert:
    • Die Testdatei fängt immer mit
      use Codeception\Util\Stub;

      an.

    • Die Tests erweitern nun
      \Codeception\TestCase\Test

      also

      class myWhateverTest extends \Codeception\TestCase\Test {
       // ...
      }
    • Die Methoden „setUp()“ und „tearDown()“ werden zu „_before()“ und „_after()“. Denkt auch an den Aufruf parent::_before() und parent::_after() in den Methoden!
  • Eure bisherige „bootstrap.php“ muss in „tests/_bootstrap.php“ oder ihr passt die „codecept.yml“ einfach an.

Damit steht nun das Grundgerüst und ihr könnt via

php codecept.phar run

eure Tests ausführen.

In meinem konkreten Fall konnte ich damit die Tests einer ZF1 Application mit Anlegen und Füllen einer Testdatenbank (MySQL) um den Faktor 8 beschleunigen. Zusätzlich kann nun recht einfach neue Tests in Codeception einfügen und die Ergebnisse stehen mir ebenfalls für Jenkins und Co zur Verfügung, teilweise mit sehr viel höherer Aussagekraft.

Viel Erfolg…

Sonderzeichen im UTF-8 CSV Export für Excel

Wer schon mal CSV Daten geschrieben hat kennt sicher das Problem, dass die Sonderzeichen meist nicht richtig angezeigt werden, wenn man in UTF-8 exportiert.

Wer das vermeiden will muss einfach den richtigen Unicode-Header mitsenden, dieser lautet:

echo pack("CCC",0xef,0xbb,0xbf);

Dieses Kommando sendet ihr am besten nach den „header“ Kommandos, aber noch vor den Daten, dann zeigt Excel auch die richtigen Daten per Doppelklick an.

P.S. LibreOffice / OpenOffice sind von Haus aus schlau genug und stellen die Daten ohnehin richtig dar, das Problem existiert also wirklich nur für Excel.

No input file specified.

Codeigniter kann einen in den Wahnsinn treiben mit dieser Meldung:

No input file specified.

Sonst nix.

Hier für alle, vor allem für mich, der „fix“ dazu:
In der .htaccess hinter dem „index.php“ aber noch vor dem „/“ ein „?“:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

Zumindest bei meinen Projekten funktioniert dann wieder alles wie es soll.

Hat YAGNI ausgedient?

Ich las eben einen interessanten Artikel im phpMagain online. In „Abwärtskompatibilität vs. langfristiges Planen“ geht es über einen Blogbeitrag von Anthony Ferrara, in der dieser u.a. darüber schreibt, dass er die Optionen seiner Funktionen als array anlegt, obwohl das ja teilweise gar nicht sein müsse. In die Zukunft gesehen macht es aber Sinn, da ja bald neue Optionen hinzukommen werden, da sich jede Software weiterentwickelt und seine Funktion somit flexibel ist und ihre Signatur sich nicht weiter ändern muss.

Allerdings, und das steht ja auch im Artikel des phpMagazins, wiederspricht dies dem YAGNI Prinzip, das – vereinfacht – besagt, dass du alles, was du aktuell nicht brauchst, auch nicht entwickeln sollst.

Ich finde, dass passt dann nur auf Software, die du einmal entwickelst und die dann einfach vor sich hin altert. Software, die du vorher im Detail planst und dann nie wieder ansiehst. Kurz, Software, die hoffentlich heute in der Form nicht mehr gebaut wird.

Heute verändert sich Software stetig und ständig, „und das ist auch gut so“, denn sonst würden wir alle niemals Updates installieren müssen. Aber im Gegenteil müssen wir heutzutage so viele Updates installieren, dass manchen Hersteller gar nicht mehr nervt fragt, sondern uns ganz bequem mit „Silent updates“ auf dem neuesten Stand hält.

IMHO werden Anwendungen und Webseiten heute um ein vielfaches schneller und öfter aktualisiert wie noch vor wenigen Jahren. Und Software, die aktualisiert wird, wird oft auch erweitert. Es werden ja nicht nur Sicherheitslücken geschlossen oder Bugs gefixed, es kommen oft auch neue Features und Funktionen hinzu, altbekanntes fällt manchmal weg, kurz: Die Software verändert sich und damit auch ihr Code, ihre Funktionen und dessen Signaturen.

Was hat das nun mit YAGNI zu tun? Nun, YAGNI würde besagen, dass man eine Funktion minimalst aufbauen soll, ein Beispiel, eine Funktion liefert uns Benutzerdaten aus einer Datenbank:

public function getUser() {
//...
}

Diese Funktion würde alle User zurückliefern. Im Laufe des Lebens der Anwendung merken wir, dass ein Filter auf „getUser()“ wohl sinnvoll wäre, also ändern wir die Signatur:

public function getUser($id)

liefert nun genau einen User mit einer speziellen Id.

public function getUser($id = -1, $name)

kann nun auch einen User nach Namen liefern, wenn wir id auf -1 setzen.

public function getUser($id = -1, $name, $nameAsLike)

kann nun auch – bei $nameAsLike=true und id=-1 – einen Namen „teilweise“ liefern.

Diese Liste ließe sich nun bestimmt weiter fortsetzen, ihr kennt das sicher alle. Sicher entspricht dies dem YAGNI Prinzip, denn im Laufe der Versionen der Software kam immer nur genau so viel dazu, wie unbedingt erforderlich war. Aber war das gut so?

Vorausschauender wäre es gewesen, sich kurz Gedanken zu machen und dann zu entscheiden

public function getUser(array $options=array())

Nun kann dort auch jeder der obigen Evolutionsschritte der Software eingebracht werden, die Signatur der Funktion braucht allerdings dazu nicht geändert zu werden und damit gibt es auch weniger potentielle Fehlerquellen im Rest des Codes.

Vielleicht müssen wir vom starren YAGNI weg, hin zu einem YDNNI, einem „You Defenitly Not Need It“, einem Paradigma, dass es erlaubt, vorausschauend zu Entwicklen, dass einem aber trotzdem untersagt, völlig Sinnfreie oder sogar Kontraproduktive Dinge zu entwickeln.

Die Sache mit dem array scheint sich langsam aber sicher dank oder trotz YAGNI zur „Best Practice“ durchzusetzen. Setzt ihr Optionen auch als array um oder benutzt ihr da völlig andere Wege?

 

PHP – foreach „greift“ nicht, keine Iteration

Kleiner Hinweis: Wenn bei euch eine „foreach“ Schleife nicht greift, obwohl alles richtig zu sein scheint – das array ist da, Werte sind drin, sogar die richtigen 😉 – und trotzdem keine Iteration über das array stattfindet, dann sucht mal vor Ausführung des foreachs nach array-Iterations Funktionen, die das komplette Array durchlaufen, z.B.: array_map, array_walk, usw.

Die Ursache ist: Durch den kompletten Durchlauf des Arrays steht der interne Pointer (wir erinnern uns dunkel, PHP ist in C/C++ geschrieben) immer noch auf dem letzten Element, die foreach-Schleife kann also nicht loslaufen, weil Sie – rein technisch – schon am Ende ist und „überspringt“ das foreach.

Die Lösung ist trivial: Nach der Iterationsfunktion oder direkt vor dem foreach setzt ihr

reset($myArray);

Das reset setzt euer Array intern wieder auf das erste Element und schon funktioniert eure foreach-Schleife wieder – die C/C++ und Java-Entwickler kennen das Problem 😉