utf8mb4 auf uberspace

Es war vor gut zwei Jahren, dass mir das Thema utf8mb4 auffiel. Ein Thema, das auch meinen Hoster uberspace betrifft, denn dort kommt – CentOS 6 sei “Dank” – MySQL 5.1.73 zum Einsatz, und utf8mb4 gibt es erst ab 5.5.3. Was ich leidvoll feststellen musste, als WordPress einen Post nur bis zu einem eingefügten Emoji gespeichert hat, alles darüber hinaus war (stillschweigend!) flöten. Damals wurde ich auf CentOS 7 vertröstet, das das dann können sollte.

Am 16.2. dieses Jahres kam dann der erlösende Blogpost: uberspace unterstützt MariaDB, und zwar in der “zu MySQL 5.5 kompatiblen” Version 10.0 – trotz CentOS 6:

eine Übergangslösung, die nur für Leute gedacht ist, die zwingend hier und jetzt unbedingt MySQL 5.5 bzw. etwas dazu Kompatibles brauchen.

“Hier und jetzt”, eh, ja. In dem Zusammenhang:

Sobald unsere CentOS-7-Hosts am Start sind […]

Dazu gibt es immer noch keinen Zeitplan, Stand 8. April 2016. Aber zurück zum Thema: Das Wiki sagt

Mit dem Befehl uberspace-setup-mariadb kannst du dir eine Datenbank auf dem Host anlegen. Die Zugangsdaten werden in ~/.my.mariadb.cnf abgelegt.

, was bei mir zuerst nicht geklappt hat:

Nachdem der Support tätig wurde, war der Fehler zwar weg, aber erwähnte .my.mariadb.cnf leer. Inzwischen läuft das aber rund (Danke an den Support an dieser Stelle für die schnelle Reaktion), deshalb hier die vollständige Migration:

Et voilà: Von 💩 zu 👍 in fünf einfachen Schritten! 😊 Dasselbe jetzt noch für meinen Feedreader! 💪

UPDATE

Meh: Fever “kann” das nicht. Erstens ist utf8 dort hart im Code verdrahtet, zweitens ist bsplw. der Titel eines Eintrags ein varchar(255) – und ein Key:

255 mal 4 Byte (wie in utf8mb4) sind aber mehr als 1000 Byte, und das ist das Limit für einen Schlüssel m( Change Request bei Fever läuft.

UPDATE

Ich empfehle Super Emoji Plus+!

UPDATE

uberspace zum Thema “CentOS uberspace 7″ und Zeitplänen – für solche Ansagen mag ich die Jungs 😉

MySQL vs. UTF-8 (vs. CodeIgniter)

MySQL kann UTF-8… falsch. Besser gesagt: Ungenau. MySQL kann UTF-8, aber das heißt da anders:

Ein Zeichen in UTF-8 ist (bis zu) vier Bytes lang, “UTF-8” in MySQL kann aber nur bis zu drei. Deswegen fällt der Unterschied oft gar nicht auf, oder erst beim ersten Zeichen, das vier Bytes braucht. Will man echtes UTF-8, muss man einiges umkonfigurieren; in Kurzform:

  1. SQL muss in der Version 5.3.3+ vorhanden sein, siehe Link oben
  2. Jede Datenbank, jede Tabelle (ggf. jede Spalte) müssen auf “CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci” umgestellt werden
    • Dabei zu beachten: InnoDB kann wohl nur 767 Bytes pro Index Schlüssel. Wenn man vier (statt drei) Bytes pro Zeichen rechnet, sind das bsplw. nur 191 (statt 255) Zeichen!
    • Das gilt auch für Typen wie TINYTEXT, die wohl nur 255 Bytes = 63 Zeichen bei 4 Byte/Zeichen speichern können. Ggf. ist hier ein anderer Typ zu wählen
  3. ggf. Server, Client, etc. umstellen (dabei hilft “SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';“)
  4. ggf. Datenbank reparieren und optimieren (war bei mir nicht nötig, ich habe alle Tabellen neu angelegt):

bzw.

Insbesondere bei Punkt 3 hängt es bei CodeIgniter, btw. Wenn man in der Datenbank-Config

 stehen hat, dann ist das ebenfalls nicht das echte UTF-8. Stattdessen korrekt ist:

Update

Das Problem betrifft auch mysqldump: Will man die eine utf8mb4-Datenbank dumpen, muss man das explizit sagen, denn mysqldump nutzt per Default nur utf8 (Quelle):

Das ist so tief verankert, dass auch Dumps über Tools wie Sequel Pro nur utf8 nutzen m(

PHP: PDFs erstellen mit FPDF

FPDF ist ein gutes Tool, um mit PHP recht einfach PDFs zu erstellen. Hier meine gesammelten Learnings nach der ersten Anwendung:

  • Eigene Fonts werden mit MakeFont() in für PHP verständliche Form gebracht (gibt’s auch als Online-Tool)
  • Die Einbindung eigener Fonts geschieht mittels AddFont(), wobei die “Font Family” der String ist, der in der mit MakeFont() erzeugten PHP-Datei $name heißt
  • Text, der mit Write() geschrieben wird, bricht die Seite nicht um
  • Text im Header bricht die Seite nicht um, Text im Footer bricht die Seite nicht um. Mir erschien es zuerst etwas uneinsichtig, wo ich den Content erzeuge – es gibt Header() und Footer(), aber kein Content() oder Body(). Der Grund: Header() und Footer() werden von AddPage() aufgerufen, und damit auch bei automatischem Page-Break. Sprich: Jedesmal; deshalb sind sie ausgelagert. Der Content dagegen wird nur ein mal hinzugefügt. In den Beispielen meistens von außen, aber es geht auch im Konstruktor.
  • Text bricht dann die Seite automatisch um, wenn er mit Cell() (man beachte Parameter “ln”) oder MultiCell() hinzugefügt wird
  • Text in Cell() bricht selbst nicht um, nur in MultiCell()
  • t scheint nicht zu funktionieren, n dagegen schon

Und schließlich, nicht direkt zu FPDF: Wenn es UTF8-Probleme mit Texten aus der Datenbank gibt, kann es daran liegen, dass der Text nicht UTF8-kodiert aus gelesen wird. Ein

hilft dann.