Bilder von Remote laden in WordPress-Entwicklungsumgebung

Eben stolperte ich über einen Blogpost, in dem erklärt wird, wie man in WordPress die Bilder von einem anderen Host als dem aktuellen einbindet. Normalerweise geht WordPress davon aus, dass die hochgeladenen Medien auf dem aktuellen Host unterhalb von /wp-content/uploads/ zu finden sind.

Beispiel: Dieses Blog läuft auf https:/www.marcusjaschen.de/ und die hochgeladenen Bilder sind normalerweise irgendwo unterhalb von https:/www.marcusjaschen.de/wp-content/uploads/ zu finden.

Holt man sich jetzt die WordPress-Installation in eine Entwicklungsumgebung, möchte man unter Umständen nicht alle Bilder und Medien mitkopieren, denn das können je nach Website schnell einige Gigabytes werden. Die Medien sollen aber natürlich trotzdem angezeigt werden.

Der erwähnte Blogpost beschreibt eine Lösung, die darauf beruht, die Basis-URL für das Uploads-Verzeichnis über eine versteckte Config-Option in WordPress zu ändern. WordPress schreibt dann automatisch alle Medien-URLs um, so dass der Browser diese von ihrer originalen Position lädt (oder aus einem CDN).

Diese Config-Option war mir bis eben unbekannt. Ich habe das Problem bisher auf eine andere Art und Weise gelöst. In meinen nginx-Konfigurationen habe ich jeweils eine Rewrite-Regel, die einfach die Requests umschreibt:

location /wp-content/uploads/ {
    rewrite ^(/wp-content/uploads/.*)$ https://www.marcusjaschen.de/$1 last;
}

Der beobachtete Effekt ist bei beiden Lösungen identisch.

Mein erstes veröffentlichtes WordPress-Plugin

Ich habe im Laufe der Zeit unzählige WordPress-Plugins entwickelt, bisher ausschließlich aber für die interne Verwendung in Projekten wie z. B. MTB-News.de.

Eine Veröffentlichung im Plugin-Verzeichnis auf wordpress.org kam bisher nicht in Frage, da die Einsatzzwecke sehr eng an spezielle Setups gebunden waren und die Plugins damit für jede andere Website schlicht nicht von Nutzen wären.

Nun war es an der Zeit, auch mal ein Plugin zu veröffentlichen, welches durchaus weitere Nutzer haben könnte. Es stellt die Verbindung zwischen zwei anderen beliebten Plugins her:

  • Better Internal Link Search verbessert die Suchfunktion beim Verlinken auf bestehende Inhalte
  • WP Subtitle erweitert WordPress-Artikel um eine zweite Überschrift („Subtitle“, „Dachzeile“)

Better Internal Link Search findet bei der Suche keine Artikel, die den Suchbegriff im Subtitle enthalten. Es bietet allerdings an der richtigen Stelle einen Filter-Hook, den ich genutzt habe, um die Suche entsprechend zu erweitern.

Die Suche ohne das Plugin findet keine Ergebnisse, da der Suchbegriff nur in einem Subtitle vorkommt.
Mit aktiviertem Plugin wird der gesuchte Artikel sofort gefunden.

Das Plugin ist momentan bei MTB-News.de, eMTB-News.de und Rennrad-News.de im Einsatz und ich habe mir versichern lassen, dass es eine große Hilfe in der täglichen Arbeit der Redaktion ist.

Alle Infos zum Plugin gibt es im Plugin-Verzeichnis von WordPress. Der Source Code ist bei Github zu finden.

Entwickler oder Entwicklerinnen die sich besonders schlau vorkommen …

… bauen gerne mal Konstrukte der folgenden Art:

$path = ltrim( end( @explode( get_template(), str_replace( '\\', '/', dirname( __FILE__ ) ) ) ), '/' );

Sortiert sieht es dann so aus:

$path = ltrim(
    end(
        @explode(
            get_template(),
            str_replace('\\', '/', dirname(__FILE__))
        )
    ), 
    '/'
);

Zum Kontext: diese Zeile stammt aus einem kommerziellen WordPress-Template und es soll der letzte Teil des Pfadnamens des aktuell ausgeführten Skripts bestimmt werden. Aus /var/www/wordpress/wp-content/themes/valenti/option-tree soll also option-tree werden.

Von innen nach außen:

  • dirname(__FILE__) liefert den Pfadanteil des aktuell ausgeführten PHP-Skriptes; aus /var/www/wordpress/wp-content/themes/valenti/option-tree/ot-loader.php wird also /var/www/wordpress/wp-content/themes/valenti/option-tree
  • str_replace('\\', '/', …) ersetzt den Backslash (vermutlich als Workaround für Windows-Systeme) mit einem Slash, der Pfad bleibt auf einem unixoiden System also erstmal unverändert (es sei denn, er enthält tatsächlich den Backslash)
  • get_template() liefert den Namen des aktiven WordPress-Templates, in diesem Fall valenti
  • explode() trennt den Pfadnamen in einzelne Teile, und zwar an jeder Stelle an der der String valenti vorkommt; man erhält also dieses Array: [0 => '/var/www/wordpress/wp-content/themes/', 1 => '/option-tree']
  • end() liefert den Wert des letzten Elements des Arrays: /option-tree
  • ltrim(…, '/') entfernt zum Schluss den Slash am Anfang des Strings, so dass wir das Ergebnis erhalten: option-tree

Soweit, so gut.

Diese Variante hat unter Umständen einige Probleme, Backslashes im Pfadnamen könnten eines davon sein. Unterdrückte Fehlermeldungen mit dem @-Operator könnte zu weiteren Hässlichkeiten beim Debugging führen.

Aber das Hauptproblem ist, dass der Entwickler oder die Entwicklerin hier eine komplexe Lösung für ein einfaches Problem geschaffen hat. PHP löst die gegebene Fragestellung nämlich mit Bordmitteln viel eleganter und zudem fehlerunanfällig und OS-unabhängig:

$path = basename(__DIR__);

Keine Ursache.

Pipes, oder: eine von vielen Dingen, die mich an Unix begeistern

Oft benötige ich für meine lokale Entwicklungsumgebung die aktuelle Struktur und die Inhalte der Datenbank des Produktivsystems. Ein möglicher Ablauf, um die Daten aus dem Produktiv-Datenbankserver herauszuholen und lokal zu importieren könnte so aussehen:

  1. Einloggen auf dem Server
  2. per mysqldump eine Datei mit allen SQL-Statements zum Erzeugen der Datenbank samt ihrer Daten schreiben
  3. Den Dump mit gzip oder bzip2 komprimieren
  4. Diese Datei mit scp oder rsync auf den lokalen Rechner herunterladen und in die Entwicklungs-Virtual-Machine kopieren
  5. Einloggen auf der Entwicklungs-VM
  6. Entpacken sowie Importieren des Dumps

Oder man macht es einfach als Einzeiler auf der Shell:

ssh server "mysqldump db_name | gzip -c" | ssh vagrant "gzip -dc | mysql db_name"

Wahlweise kann man auch noch pv als Fortschrittsanzeige dazwischenschalten:

ssh server "mysqldump db_name | gzip -c" | pv | ssh vagrant "gzip -dc | mysql db_name"

Mit Hilfe des Pipes-Konzepts lässt sich der Ausgabestream eines Kommandos als Eingabestream eines anderen Kommandos verwenden, ohne dass temporäre Dateien angelegt und herumkopiert werden müssen. Es dürfte sich neben der „Everything is a file“-Philosophie¹ um eines der praktischsten Dinge von Unix sein.

¹ Eine Pipe hat übrigens auch einen file descriptor.

Workaround für PHP Bug #43225

In PHP gibt es einen Bug, der dazu führt, dass die Funktion fputcsv unter Umständen fehlerhaftes CSV generiert, welches dann von Programmen nicht mehr eingelesen werden kann.

Der Fehler tritt auf, wenn in einem Feldwert ein Backslash \ vorkommt, der direkt von einem doppelten Anführungszeichen " („double quote“) gefolgt wird. Ein Beispiel:

$data = [
    'CMXINV',
    '-1001338',
    'Some string data here: "quoted text // highlight string \\\\" and "foo" bar',
    'baz'
];

Hier folgt auf die zwei Backslashes[1] direkt ein doppeltes Anführungszeichen.

Erzeugt man aus dem $data-Array mit fputcsv eine CSV-Zeile, erwartet man folgende Ausgabe:

CMXINV;-1001338;"Some string data here: ""quoted text // highlight string \\"" and ""foo"" bar";baz

Tatsächlich erhält man aber:

CMXINV;-1001338;"Some string data here: ""quoted text // highlight string \\" and ""foo"" bar";baz

Bei genauem Hinschauen erkennt man, dass hinter den beiden Backslashes nur ein doppeltes Anführungszeichen steht, obwohl es zwei sein sollten[2].

Dieses Verhalten ist als PHP Bug 43225 bereits 2007 dokumentiert worden und wurde bis heute nicht korrigiert.

Ich setze fputcsv in meiner Open Source Library für Collmex ein. Jegliche Kommunikation mit der Collmex-API geschieht über das Senden und Empfangen von Nachrichten im CSV-Format. Bei einem Projekt trat nun der Fall auf, dass in einem Feld tatsächlich Backslashes vor doppelten Anführungszeichen standen und Collmex den erzeugten fehlerhaften Datensatz nicht lesen konnte. Ich habe jetzt einen Workaround in der Collmex-Library eingebaut, mit der dieser spezielle Fehler nicht mehr auftritt.

Der Workaround macht nichts anderes als vor dem Aufruf von fputcsv temporär einen String zwischen Backslash und doppeltem Anführungszeichen einzufügen und ihn nach dem Erzeugen der CSV-Daten wieder zu entfernen. Die Details lassen sich in der betreffenden Quelldatei bei Github ansehen.


[1] Es sind hier vier Backslashes zu sehen, weil das Backslash-Zeichen zum „escapen“ benutzt wird und selbst auch escaped werden muss – durch einen weiteren Backslash.
[2] Ähnlich wie bei [1] muss ein doppeltes Anführungszeichen durch ein weiteres doppeltes Anführungszeichen „escaped“ werden, wenn die Feldwerte durch ein doppeltes Anführungszeichen eingeschlossen werden.

UCI-Streifen nur mit CSS bauen

Dank des großartigen CSS-Gradient-Editors von ColorZilla war es ein Leichtes, die UCI-Streifen für einen Element-Hintergrund auf einer Website nur mit CSS zu bauen:

.uci-stripes {

background: -moz-linear-gradient(top, #1e76bd 0%, #1e76bd 20%, #c7203c 20%, #c7203c 40%, #000000 40%, #000000 60%, #f8df00 60%, #f8df00 80%, #35b24a 80%, #35b24a 100%); /* FF3.6-15 */

background: -webkit-linear-gradient(top, #1e76bd 0%,#1e76bd 20%,#c7203c 20%,#c7203c 40%,#000000 40%,#000000 60%,#f8df00 60%,#f8df00 80%,#35b24a 80%,#35b24a 100%); /* Chrome10-25,Safari5.1-6 */

background: linear-gradient(to bottom, #1e76bd 0%,#1e76bd 20%,#c7203c 20%,#c7203c 40%,#000000 40%,#000000 60%,#f8df00 60%,#f8df00 80%,#35b24a 80%,#35b24a 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */

}

(Direktlink zum Editor)

UCI-Streifen

make – der bessere Task-Runner für das Web Development

Fast im Wochentakt kann man das Erscheinen neuer Task-Runner-Systeme beobachten – sie alle versprechen weniger Bloat, leichteres Erstellen der Tasks und immer dreimal besser zu sein als die Konkurrenz. Heutzutage basieren diese System meist auf Node.js, da es hier mittlerweile einen riesigen Fundus an Tools gibt, die für die einzelnen Aufgaben eines Task-Runners für das Web Development benötigt werden.

Ich habe einige dieser Systeme (z. B. Grunt, Gulp) auch produktiv benutzt. Mittlerweile wird aber von mir wieder das selbe Werkzeug für diese Aufgaben eingesetzt wie bereits vor über zehn Jahren: make.

make ist ein Build-Management-Programm und kann beliebige Kommandos in Abhängigkeit von bestimmten Bedingungen ausführen. Der Ansatz unterscheidet sich grundlegend von dem der modernen Task-Runner.

Am einem Beispiel lässt sich das Konzept erklären: Ich möchte alle für eine Website benötigten Javascript-Dateien in eine einzige Datei zusammenfassen und davon dann eine minifizierte Version erstellen, die danach deployed werden kann.

Einem Task-Runner würde man in etwa sagen: „Nimm diese Liste von Dateien, hänge sie aneinander und speichere das Ergebnis als Datei. Danach nimm diese Datei, minifiziere sie und speichere sie ebenfalls ab.“

Mit make geht es eleganter: Statt einer Liste von abzuarbeitenden Kommandos gibt man einerseits die Voraussetzungen (Prerequisites) an, die erfüllt sein müssen, um die Zieldatei (Target) zu erzeugen. Zum anderen spezifiziert man die Kommandos, welche nach der Erfüllung der Voraussetzungen die Zieldatei erzeugen. Make wird dann zuerst rekursiv alle Voraussetzungen erfüllen, um zum Schluss die Zieldatei zu erzeugen. Klingt kompliziert, ist es aber nicht. Ein Beispiel:

assets/site.js: resources/jquery.js \
resources/app.ux.js \
resources/app.comments.js
	cat $^ > $@

Diese Datei nennt sich im make-Jargon Makefile und wird auch unter diesem Dateinamen gespeichert. Im Makefile ist ein sogenanntes Target samt seiner Prerequisites sowie die Kommandos zur Erstellung der Zieldatei definiert.

Das Target lautet hier assets/site.js und steht vor dem Doppelpunkt. Darauf folgend sind die Prerequisites in der selben Zeile aufgezählt (bzw. in aufeinanderfolgenden Zeilen die mit dem escapten Newline  \ enden, wie im Beispiel zu sehen). Das oder die Kommandos stehen mit jeweils einem Tabulator-Zeichen (!) eingerückt unter dem Target.

Die Voraussetzungen für das Erzeugen der Datei assets/site.js sind in Form von Dateinamen aufgezählt und lauten resources/jquery.js resources/app.ux.js resources/app.comments.js. Das Kommando erzeugt das Target durch einfaches Aneinanderhängen der Prerequisite-Dateien mit dem Unix-Kommando cat. Hierbei kommen zwei Variablen zum Einsatz, die von make automatisch gefüllt werden: $^ ist die Liste der Prerequisites und $@ ist das Target. Ausgeschrieben lautet das Kommando:

cat resources/jquery.js \
resources/app.ux.js \
resources/app.comments.js > assets/site.js

Der Aufruf von make assets/site.js baut jetzt diese Javascript-Datei. Clever dabei: make wird die Datei nur erzeugen, wenn sie noch nicht existiert oder mindestens eine der Prerequisites zwischenzeitlich geändert wurde. Ruft man das Kommando zweimal nacheinander auf, wird make beim zweiten Mal sagen, dass es nichts zu tun gibt, da die Zieldatei schon aktuell ist.

Ein zweites Target könnte dann die minifizierte Variante der Javascript-Datei erzeugen:

assets/site.min.js: assets/site.js
    uglifyjs $< --mangle --comments > $@

Update: Steffen wies mich per E-Mail darauf hin, dass obiges Make-Target unter Umständen zu Problemen führen kann, nämlich dann, wenn in dem Beispiel `uglifyjs` fehlschlägt. Die Ausgabedatei wird sofort durch die Shell erzeugt – und zwar unabhängig davon, ob das Kommando erfolgreich ist oder mit einem Fehler beendet wird. Im Fehlerfall liegt dann eine leere Zieldatei vor ohne dass irgendeine Fehlerbehandlung durchgeführt wurde oder man den Fehler überhaupt bemerkt. Besser ist es also, das Target folgendermaßen zu definieren:

assets/site.min.js: assets/site.js
    uglifyjs $< --mangle --comments > $@ || { rm -f $@ ; exit 2 ; }

So bekommt man sofort mit, wenn irgendetwas schief läuft und verarbeitet nicht aus Versehen eine leere Datei weiter.

Man sieht, dass jetzt die eben erzeugte Datei assets/site.js als Prerequisite für die minifizierte Datei dient. Die Variable $< steht dabei für die erste Prerequisite aus der Liste; in diesem Fall wird sie durch assets/site.js ersetzt.

Wenn jetzt make assets/site.min.js aufgerufen wird, stellt make sicher, dass zuerst assets/site.js erzeugt wird (siehe oben, dort ist das Target assets/site.js definiert) und führt dann das Kommando zur Minifizierung aus. Auch hier wird make nur tätig, wenn das Ziel noch nicht existiert oder sich eine der Quelldateien zwischenzeitlich geändert hat.

Mit diesem Prinzip kann man jetzt alle benötigten Assets für eine Website erzeugen, von Image-Sprites über robots.txt-Dateien bis hin zu Konfigurations-Dateien und vieles andere mehr, von sehr simpel bis beliebig komplex.

Die größten Vorteile von make sind meines Erachtens:

  • die Geschwindigkeit: bei meinen Websites ist make im Durchschnitt dreimal schneller als Gulp (inkl. der langsamen Tasks wie JavaScript Minifying usw.). Der Unterschied zwischen zehn Sekunden und drei Sekunden Build-Dauer ist nicht zu vernachlässigen. Vor allem wenn man das zig Mal pro Tag macht.
  • die Verfügbarkeit: make ist auf so ziemlich jedem unixoiden Betriebssystem dabei bzw. lässt sich aus Paketquellen sofort installieren
  • die Einfachheit: make ist eine einzige ausführbare Datei vom kaum 200 KiB Größe (Linux, x86_64). Moderne JavaScript-Task-Runner haben viele Abhängigkeiten, die man mit npm installieren muss – was aber erst geht, wenn man npm selbst installiert hat, für welches man wiederum erst mal Node.js installieren muss…[1]
  • make folgt der Unix-Philosophie: anstatt das Rad jedes Mal neu zu erfinden, nutzt man mit make die Möglichkeiten, die Unix bietet, z. B. Pipes und Redirections, mit denen simple Werkzeuge verknüpft werden um komplexe Aufgaben zu lösen.
  • die klarere Strukturierung der Anweisungen: ein Makefile ist üblicherweise leichter lesbar als die Anweisungen für einen JavaScript-Task-Runner, da make selbst auf komplexe Funktionialitäten, wie zum Beispiel Closures verzichtet.
  • make macht nicht mehr als es wirklich tun muss: anstatt z. B. die kompletten Assets bei jedem Aufruf neu zu bauen, wird make nur die Targets ausführen, deren Prerequisites sich auch wirklich geändert haben. Ändert man etwas am CSS, wird make nicht auch die JavaScript-Assets bauen, da es weiß, dass dieses bereits aktuell sind. Sind alle Targets aktuell, wird make das auch direkt so mitteilen: `make: Nothing to be done for ‚assets’`.

make gibt es in verschiedenen Versionen, ich setze GNU make ein: Homepage.


[1] Zugegeben, das ist nicht ganz fair, da Programme wie uglifyjs üblicherweise ebenfalls per npm installiert werden. npm und Node.js sind also unter Umständen doch Voraussetzung.

PHP-Entwicklung: Full-blown IDE vs. Text-Editor

Das Entwickeln von PHP-Applikationen ist die Tätigkeit, mit welcher ich die meiste Zeit des Tages beschäftigt bin. Das ist Grund genug, ständig nach Dingen zu suchen, die mir diese Arbeit erleichtern.

Das zentrale Tool für die Entwicklung ist dabei das Programm, in welchem ich Code eingebe, ändere, suche, ersetze, verwalte und vieles mehr. Gerade hier ist über die Jahre eine Menge passiert, vieles aber doch gleich geblieben. Anfangs – noch als Windows-Nutzer – habe ich Editoren wie z. B. SciTe, Notepad++, UltraEdit o. Ä. zum Coden benutzt. Da er bei der Arbeit auf Servern zu den wichtigsten Tools gehörte und allgegenwärtig war, lernte ich später auch Vim und nutzte ihn dann in der grafischen Version GVim als meinen primären PHP-Editor.

Mit dem Umstieg auf OS X rutschte Vim als Alltagseditor etwas aus dem Fokus, was auch daran lag, dass es damals noch keine anständige Umsetzung für den Mac gab (diese wurde dann in Form von MacVim um 2007 oder 2008 veröffentlicht). Zwischenzeitlich wechselte ich – wie vermutlich fast jeder zu dieser Zeit – auf TextMate, welcher mit seinen Plugins (im TextMate-Sprech Bundles genannt) unfassbar leistungsfähig war.

Hin und wieder wagte ich den Blick über den Tellerrand und schaute mir integrierte Entwicklungsumgebungen mit PHP-Support an. Es gab zwar durchaus einige (mir fallen spontan NetBeans, Komodo, Eclipse PDT und Zend Studio ein) aber nichts konnte mich überzeugen. Ich ließ mir aber ein fertig konfiguriertes NetBeans liegen, welches ich zum Step-by-Step Debuggen nutzte – das war das einzige wichtige Feature, das mir TextMate nicht bieten konnte.

Die IDE-Welt wurde dann mit dem Erscheinen von JetBrains PhpStorm hart durchgerüttelt. PhpStorm wuchs gerade in den letzten beiden Jahren zum defacto-Standard der PHP-IDEs heran. Nach und nach verlagerte ich meine PHP-Entwicklung auch komplett nach PhpStorm. JetBrains legt in einer unglaublichen Geschwindigkeit neue Features nach, auch die Unterstützung neuer PHP-Versionen und Tools wie Composer ließen nie lange auf sich warten.

Auch ein Grund, mit dem mich JetBrains überzeugen konnte, jedes Jahr etwas Geld auszugeben um die Lizenz zu verlängern, war der Umstand, dass PhpStorm für eine riesige Java-Desktop-Applikation ausreichend schnell war.

Leider hat sich das zuletzt geändert. Auch auf neuen Rechnern fühlt sich PhpStorm nicht mehr flüssig an, es ruckelt mittlerweile an allen Ecken und Enden. Dieser Umstand führte in letzter Zeit dazu, dass ich wieder öfter zum Text-Editor greife, statt PhpStorm zu booten.

Zum Glück ist der Markt der Text-Editoren lebendig wie nie zuvor. TextMate kommt seit einiger Zeit in Version 2 (Beta) daher und ist immer noch wunderbar zum Entwickeln von PHP-Applikationen mit allem was dazu gehört geeignet. Github hat mit Atom einen nagelneuen Editor entwickelt, auch wenn dieser konstruktionsbedingt (basiert auf dem Chromium-Browser) ein paar Nachteile hat. Seit einigen Jahren ist allerdings Sublime Text der Platzhirsch der Code-Editoren. Sublime Text bietet wie auch TextMate Unterstützung für Plugins und kann so auf den eigenen Bedarf angepasst werden und ist auch bei großen Projekten unfassbar schnell. Grund genug, dass ich seit einiger Zeit vermehrt Sublime Text als Editor statt PhpStorm zum Entwickeln nutze.

Gerade zuletzt musste ich sehr viele kleinere Änderungen in vielen Projekten in kurzer Zeit durchführen – die Geschwindigkeit von Sublime Text (in allen Belangen: Projekte öffnen, suchen über das gesamte Projekt, ersetzen usw.) hat das alles überhaupt erst erträglich gemacht.

Alles in allem ist es interessant zu sehen, wie sich der Kreis schließt und schlussendlich doch wieder der einfache Text-Editor das Tool meiner Wahl wird wenn es ums Coden geht.

Weiterleitung für WordPress-URLs bei Permalink-Änderung

Ich habe eben die URLs der Blog-Posts hier im WordPress geändert. Das geht an sich ganz einfach – in den Permalink-Settings von WordPress kann man sich den URL-Pfad für die Blog-Posts fast beliebig zusammenstellen.

Das Problem an der Sache ist, dass die Links zu bereits veröffentlichten Blog-Posts ungültig werden. Man möchte also für die alten Links einen Redirect einrichten.

Die alte Permalink-Struktur sah so aus:

https://www.marcusjaschen.de/fahrt-in-den-sommerlichen-sonnenuntergang/

Nach der Änderung sind die URLs etwas anders aufgebaut:

https://www.marcusjaschen.de/blog/2015/fahrt-in-den-sommerlichen-sonnenuntergang/

Um jetzt nicht alle Weiterleitungen per Hand anlegen zu müssen, habe ich mir die Arbeit vereinfacht und die fertigen Redirect-Direktiven für die Apache-Konfiguration direkt per SQL ausgeben lassen:

SELECT 
    CONCAT(
        'RedirectPermanent /',
        `post_name`,
        ' ',
        'https://www.marcusjaschen.de/blog/', 
        DATE_FORMAT(`post_date`, '%Y'), 
        '/', 
        `post_name`
    ) 
FROM 
    `wp_posts` 
WHERE
    `post_status` = 'publish'
    AND `post_type` = 'post'
ORDER BY `post_date` ASC

Da fällt dann z. B. so etwas heraus:

RedirectPermanent /kopf-hoch-lenin https://www.marcusjaschen.de/blog/2015/kopf-hoch-lenin
RedirectPermanent /airport-berlin-brandenburg-international https://www.marcusjaschen.de/blog/2015/airport-berlin-brandenburg-international
RedirectPermanent /fahrt-in-den-sommerlichen-sonnenuntergang https://www.marcusjaschen.de/blog/2015/fahrt-in-den-sommerlichen-sonnenuntergang

Es reicht die Ausgabe in die Apache-Konfiguration oder, falls vorhanden, in die .htaccess-Datei zu kopieren um alle bisherigen Links auf die geänderten URLs weiterzuleiten.