CodeIgniter: “The model name you are loading is the name of a resource that is already being used”

Es gibt im Internetz verschiedene Ansätze für dieses Problem; die meisten basieren auf einem eigenen Loader. Meiner Erfahrung anch funktionieren die alle nicht (in allen Situationen), und leider scheint die einzige echte Alternative zu sein, alle Models ohne Namen zu laden. Also lieber

statt

🙁

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(

CodeIgniter: Applikationsseitiges Datenbank-Caching

CodeIgniter hat eine “Database Caching”-Klasse, aber die habe ich auf die Schnelle nicht verstanden – und es musste schnell gehen 🙂

CodeIgniter hat auch einen generischen Cache, und der ist schnell verstanden. Zu beachten: Datenbank-Queries sind nicht cachebar, “nur” deren Result-Sets. Das sieht dann bsplw. so aus (hier als filebasierter Cache):

Danke, Marcel!

UPDATE:

Für schnelleres Austauschen des Caching-Mechanismus scheint sich das Folgende anzubieten – allerdings gibt es einen Bug: Wenn der Adapter (im Beispiel unten APC) nicht verfügbar ist, wird nicht der Fallback genommen m(

Deshalb: Entweder vorher checken, welche Treiber installiert sind – oder bei filebasiertem Caching bleiben, das scheint das zuverlässigste.

Unabhängig davon ist diese Methode der Treiberwahl natürlich insbesondere dann am flexibelsten, wenn ein Treiber nicht (mehr) verfügbar ist, und der erwähnte Bug zuschlägt.

UPDATE:

Es kann eine gute Idee sein, die Erstellung des Caches in einen eigenen Controller auszulagern. Auf die Art vermeidet man, dass die Anwendung für denjenigen hängt, der das Pech hatte, auf eine veraltete Cache-Datei zugreifen zu wollen.

Ich habe in der App die oben beschriebene Logik implementiert, allerdings mit einer TTL von 15 Min. Parallel rufe ich per Cron alle 10 Min den Controller auf (mit “-m 540”, also max 9 Min Laufzeit), der die Cache-Dateien erstellt – wobei ich in meinem Fall davon ausgehe, dass das Erstellen etwa 5 Minuten max dauert.

So findet die Anwendung immer aus Ihrer Sicht aktuelle (weil < 15 Min alt) Cache-Dateien vor, fällt aber gleichzeitig nicht um, wenn der Cron mal ausfällt.

Codeigniter: “Undefined index: REMOTE_ADDR” über CLI

Ich habe eine Route

und einen zugehörigen Controller

Das hat die ganze Zeit funktioniert – jetzt bekomme ich

Message:  Undefined index: REMOTE_ADDR

So weit, so klar: Eine Remote-IP habe ich nur, wenn der Aufruf auch von Remote kommt. Jetzt könnte man auf PHP schimpfen, warum der Index nicht trotzdem da ist, bsplw. mit 0.0.0.0, dem leeren String oder meinetwegen NULL gefüllt. Aber viel interessanter finde ich die Frage, warum das plötzlich nicht mehr geht. Wenn man sich den Controller oben ansieht, dann wird das erst mal nicht klar: Die IP wird nicht direkt abgefragt – klar, sonst hätte es auch nicht so lange funktioniert. Es wird aber auch keine Custom Klasse verwendet. Nicht mal indirekt, wie sich herausstellt, denn:

Die Session-Library ist der Übeltäter, die hatte ich vor Kurzem in die Autoload getan. Nun möchte ich an der Framework-Klasse CI_Session nicht herumdoktern, deshalb sieht mein aktueller Hack in der autoload.php so aus:

Irgendwelche besseren Vorschläge?

CodeIgniter: Model laden

Das im Forum beschriebene Verhalten* besteht auch in Version 1.7.1 des PHP-Frameworks CodeIgniter: Die Klasse eines Model darf zB BlogModel heißen – so lange ihre Datei blogmodel.php heißt. CamelCase ist nicht erlaubt – auf einigen Servern. Offenbar ist das auf das jeweilige OS zurückzuführen… wer also unwillkommene Überraschungen vermeiden will, sollte von vornherein darauf achten.

Achtung, auch eingebunden wird das Model in LowerCase:

hth

*UPDATE 2016: Der Link ist inzwischen tot.