Beiträge der Kategorie default

Redirect von URLs mit .html auf /

Vor TYPO3 9 und dem Routing im Core war RealURL sehr gnädig, was URLs anging. So konnte eine Seite mit .html Suffix und auch mit / aufgerufen werden (mein Empfinden). In TYPO3 10 funktioniert diese Verhalten nur in eine Richtung. Konfiguriert man eine .html Endung über den PageSuffix, ist die Seite weiterhin mit Trailing Slash aufrufbar. Es ist eigentltich gut, dass entweder das eine oder das andere geht. Wenn sie jemand die URL mit .html Endung gebookmarked hat und dann statt der Seite 404 bekommt, ist es ärgerlich.

Dank dieses sehr guten Beitrags auf stackoverflow hier mein Redirect-Schnipsel für die htaccess-Datei.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\.html$ /$1/ [L,R=302]

Als Tipp stand in dem Beitrag, dass man während des Testings den Fehlercode 302 verwenden sollte (found) und erst wenn es final ist, dann 301, weil dieser vom Browser gecached wird.

Sport

Dieser Blogbeitrag beschäftigt sich mit meiner zweiten Leidenschaft neben TYPO3 – dem Sport. Ich beschreibe meine Sport-Karriere und wie sich das ganze im letzten Jahr pandemie-geschuldet verändert hat.

(mehr …)

Ddev, neues Modem (FritzBox) und DNS_PROBE_FINISHED_NXDOMAIN

Ich habe mir ein neues Modem (konkret eine FritzBox) zugelegt. Auf den ersten Blick schien alles so zu funktionieren wie vorher. Heute ist Montag, Zeit zu arbeiten: ddev gestartet und festgestellt, dass meine .ddev.site Domain mit der Meldung DNS_PROBE_FINISHED_NXDOMAIN nicht angezeigt wird. Beim ddev start gab es keine Fehlermeldungen, die Datenbank ist da und auf die Seite kann ich mit einer IP-Adresse zugreifen. Damit bleibt nur noch die Vermutung, dass die DNS-Auflösung die Ursache ist.

Nachdem ich die ddev-Troubleshooting-Seite und ein paar Foren durchsucht habe, stieß ich auf den entscheidenden Hinweis.

Die FritzBox hat ein Feature, das DNS-Antworten unterdrückt, die aufs eigene Netzwerk verweisen (DNS-Rebind-Schutz). Man muss die ddev.site dort unter Ausnahmen eintragen, damit die DNS-Auflösung funktioniert. Diese Option findet man unter Heimnetz > Netzwerk > Netzwerkeinstellungen.

FritzBox Einstellungen

Unable to load dynamic library ‚memcached.so‘

Ich habe lokal unter Windows 10 ddev mit Ubuntu 20.04. aufgesetzt. Nach dem Login per SSH (ddev ssh) und dem Ausführen fast jeden Befehls (composer dump-autoload) kam die folgende Warnung:

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php/20190902/redis.so' (tried: /usr/lib/php/20190902/redis.so (/usr/lib/php/20190902/redis.so: undefined symbol: igbinary_serialize), /usr/lib/php/20190902//usr/lib/php/20190902/redis.so.so (/usr/lib/php/20190902//usr/lib/php/20190902/redis.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
PHP Warning: PHP Startup: Unable to load dynamic library 'memcached.so' (tried: /usr/lib/php/20190902/memcached.so (/usr/lib/php/20190902/memcached.so: undefined symbol: igbinary_serialize), /usr/lib/php/20190902/memcached.so.so (/usr/lib/php/20190902/memcached.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0

Erstmal hatte ich mich auf den „Unable to load“ block fokussiert. Sind die Dateien da? – ja. Ist der Pfad richtig? – ja. Ist das Modul installiert? – ja. Es gab viele „Lösungsvorschläge“ im Netz. Und es ist so unglaublich frustrierend, wenn das Problem als gelöst gilt („That solved it, thanks“) und es bei mir immer noch da ist. Ich habe sogar den ddev Installationsvorgang fast komplett neu gemacht. Immer noch die gleiche blöde Warnung, die mir die Konsole zumüllt.

Dann habe ich eher auf den zweiten Teil der Meldung geschaut und danach gesucht: „undefined symbol: igbinary_serialize“.

Lösung: Die aktuellere Version von redis (wohl auch memcached) setzt voraus, dass die Bibiothek igbinary bereits geladen ist. An einer Stelle stand, dass es theoretisch der Fall sein müsste, denn die Bibliotheken werden alphabetisch geladen und i kommt wohl vor r. Wenn man im Ordner .ddev/php eine Konfigurationsdatei ablegt, dann wird diese beim Starten des Containers geladen. Um das igbinary vor den anderen Bibliotheken zu laden, reicht es aus, wenn man eine leere Datei namens 10-igbinary.ini in diesem Ordner ablegt. Da alle anderen Biblitheken eine 20 als Priorität haben, wird die Datei mit 10- früher berücksichtigt.

Vielleicht ist ja jemand irgendwann genauso verzweifelt wie ich und diese „Lösung“ hilft ihm/ihr. Lasst es mich wissen…

Eigene Fehlermeldungen für Extbase-Validatoren

(Custom error message for extbase validators)

Da ich auf die schnelle nichts gefunden habe und es mir selbst zusammengereimt hab, schreibe ich es hier besser auf. Um die Standard-Fehlermeldungen der Extbase-Validatoren zu ändern, schreibt man folgendes ins Setup:

config.tx_extbase._LOCAL_LANG.default {
    validator.notempty.null = This is a custom error message 1
    validator.notempty.empty = This is a custom error message 2
}

Damit werden die Fehlermeldungen global für die Sprache geändert. Den Key (validator.notempty.null) findet man im Validator:

class NotEmptyValidator extends AbstractValidator
{
	protected $acceptsEmptyValues = false;
 
	public function isValid($value)
	{
		if ($value === null) {
			$this->addError(
				$this->translateErrorMessage(
					'validator.notempty.null',
					'extbase'
				), 1221560910);

Geschrieben in default | Kommentare deaktiviert für Eigene Fehlermeldungen für Extbase-Validatoren

Laravel – erster Eindruck

Soeben bin ich fast fertig mit einer Applikation, mit der ich Playlisten für meine Les Mills Kurse erstellen kann. Ich habe mich entschieden, die Applikation in Laravel zu schreiben, weil es spannend ist, mal was neues kennenzulernen (Laravel ist beliebste PHP-Framework im Moment) und weil ich TYPO3 dafür zu viel fand.

Als Einstieg in Laravel habe ich mir „Laravel From Scratch“ Tutorials angeschaut. Die Videos fand ich echt gut, auch wenn der Entwickler verdammt schnell tippt und Fenster wechselt. Ich musste immer wieder mal stoppen und sortieren, wo er gerade ist. Mir hat gut gefallen, dass er ziemlich schnell eine Ausgabe erzeugt, auch wenn es nicht immer der eleganteste Weg ist. In den späteren Tutorials passt er es auch an und zeigt einen besseren Weg. z.b. werden am Anfang die Ausgaben direkt in die Routing-Datei geschrieben. Später erzeugt er auch View, Models und Controller.

Etwas verwirrend an Laravel finde ich die Migrations. Zum einen das Wording, zum anderen, dass man Felder nicht nach dem Erstellen der Tabelle hinzufügen kann. Wenn ich also bereits eine Tabelle angelegt und befüllt habe, brauche ich eine neue Migration, die ein Feld zu der Tabelle hinzufügt. Alternativ kann ich durch Rollback meine Tabelle löschen, die Migration anpassen und neu erstellen.

Gut gefällt mir das Routing. Gerade dann, wenn man mit Route::resource() automatisch Routen mit einem Controller verknüpfen kann. Zusammen mit CRUD kann man so schnell Funktionen fürs Erstellen und Bearbeiten implementieren. Ebenfalls positiv finde ich Blade-Templates. Mein Lieblings-Templating-Framework ist nach wie vor Flow, mein Horror ist Smarty. Blade ist ein guter Kompromiss zwischen „sieht aus wie HTML“ und „PHP verwendenen in Templates“. In den Tutorials schreibt Jeffrey seine Formulare mit <form ...> in die Templates. Dann fand ich einige Beispiele mit Form::open, was mir natürlich besser gefällt. Seit Laravel 5.5 ist der Form-Helper ausgelagert worden. Nachdem ich das herausgefunden hatte, schrieben sich die Formulare noch schneller. Wenn man das Prinzip mit den View-Helpern verstanden hat, kann man relativ schnell eigene implementieren. So brauchte ich z.B. einen View-Helper, der mir aus meinem Rating (1 bis 5) Sternchen malt. Wäre auch mit einem Include gegangen, ist aber so noch eleganter.

Ebenfalls gut lassen sich Relationen abbilden. Mit hasMany, belongsTo kann man die Verknüpfungen zwischen Models definieren. Ebenfalls eine gute Idee sind die Scopes. Man definiert im Model einen Scope mit einer Einschränkung und kann im Controller oder von einem anderen Model auf den Scope zugreifen. So habe ich in meiner Applikation Scopes für Tracks definiert (Standard mit bonus=0 und Bonus mit bonus=1) und kann die Tracks in der Release-Einzelansicht in zwei verschiedenen Bereichen ausgeben.

Der Vorteil eines gut durchdachten Frameworks ist, dass man relativ schnell eine funktionierende Applikation bekommt. Auch wenn ich mich erst seit 2 Wochen mit Laravel beschäftige, habe ich meine Plan umsetzen können und die Applikation funktioniert hervorragend. Fazit: TYPO3 bleibt nach wie vor mein Steckenpferd, Laravel hat mir jedoch gut gefallen und ich könnte mir vorstellen, mich bei Bedarf da weiter einzuarbeiten.

Geschrieben in default | Kommentare deaktiviert für Laravel – erster Eindruck

LesMixer – Playlists für LesMills Kurse

Schon von ca. einem Jahr hatte ich die Idee zu einer (für mich sinnvollen) Anwendung. Als Hobby unterrichte ich Kurse im Fitnessstudio: BODYPUMP und BODYCOMBAT. Beides sind Fitnessprogramme von Les Mills. Das besondere: sie sind vorchoreografiert. Alle 3 Monate gibt es eine neue Release (neue Musik und neue Bewegungen), diese lerne ich dann und unterrichte sie. Nach ca. 6 bis 8 Wochen sorge ich für Abwechslung in den Kursen, in dem ich „mixe“, d.h. ich ersetze Tracks aus dem aktuellen Programm durch ältere Tracks. Beim Austauschen den Tracks gibt es einiges zu beachten, da der programmtypische Stundenablauf beibehalten werden soll. Jeder Track hat eine Funktion. So ist bei BODYPUMP der 2.Track immer Squats (d.h. es werden die Beine trainiert). Beim Austauschen des Tracks kann ich dann nur einen Squat-Track aus einer älteren Release verwenden. Dann sollten die ausgetauschten Lieder gemeinsam auch musikalisch Kontraste bilden und die Länge aller Lieder sollte zusammen eine bestimmte Zeit nicht überschreiten.

Bis vor kurzem mixte ich „manuell“. Ich überlegte mir, welche Lieder ich machen könnte, hörte kurz rein (klickte mich vorher durch Ordner) und überprüfte die Gesamtlänge der Auswahl. Also dachte ich mir, da kann ich doch eine kleine Anwendung schreiben, die mir die Liedauswahl erleichtert. Zunächst braucht man eine Datenbasis: ich muss bisherige Releases einpflegen können. Danach wäre es noch praktisch, diese Daten durchsuchen zu können: nach Künstler, Musiktitel oder Bewegungen.

Ich hätte es auch in TYPO3 implementieren können. Manchmal möchte ich meinen Horizont erweitern und ein neues Framework oder eine neue Anwendung kennenlernen. Das geht am besten mit Learning-by-Doing. Von einigen habe ich schon gehört, wie toll Laravel ist und wollte es selbst ausprobieren. Nachdem ich mir einen kurzen Überblick über Laravel verschafft habe (Video-Tutorials), ging es an die Umsetzung meiner Applikation names „LesMixer“.

Um mir die Datenpflege zu erleichtern, habe ich einige sinnvolle Funktionen eingebaut. Da ich die Musik in Ordner abgelegt hatte, konnte ich automatisch beim Auswählen eines Programms und einer Release die Mp3-Dateien im Ordner einlesen und zur Auswahl anbieten. Sobald eine Datei ausgewählt wird, werden Künstler, Titel und Länge (Mp3-Metadaten) und in die entsprechenden Felder eingesetzt. d.h. Tracks für eine neue Release einzupflegen ist denkbar einfach. Sobald die Tracks eingepflegt sind, kann man sie direkt in der Applikation abspielen. Die Suche oben durchsucht Künstler und Track-Titel.

Eine Playlist (Mix) zu erstellen, ist einfach. Sobald man ein Programm ausgewählt hat, werden die Tracktypen gelistet (der Ablauf ist ja immer gleich) und man kann für jeden Tracktyp einen konkreten Track auswählen. Irgendwann möchte ich diesen Vorgang automatisieren. Da ich ein Rating eingebaut habe, könnte ich mir vorstellen, in Zukunft eine Playlist generieren zu lassen unter Berücksichtigung bestimmter Einschränkungen.

Geschrieben in default | Kommentare deaktiviert für LesMixer – Playlists für LesMills Kurse

Datum in Sublime umformatieren

Für ein Projekt brauchte ich ein paar Demo-User, die ich mir mit dem Fake Name Generator habe erstellen lassen. Das Format für Geburtsdatum in der Datei ist dd/mm/yyyy, meine Datenbank erfordert aber yyyy-mm-dd. Da ich mit Sublime entwickele und es dort die Möglichkeit gibt, Suchen und Ersetzen auch mit regulären Ausdrücken durchzuführen, kann man es so machen.

Suchen und Ersetzen, dann RegEx aktivieren.
Find What: (\d{1,2})/(\d{1,2})/(\d{4})
Replace With: ${3}-${2}-${1}

Geschrieben in default | Kommentare deaktiviert für Datum in Sublime umformatieren

Bilder mit PHP gemäß EXIF-Daten drehen

Nachdem ich ein Gästebuch-Plugin für WordPress implementiert hatte, bei dem Besucher Bilder hochladen können, ist aufgefallen, dass Bilder gedreht im Gästebuch dargestellt werden, was man anhand des Motivs erkennen kann. Sobald man das Bild separat aufruft, werden sie im Browser zwar richtig rum dargestellt, sind aber verzerrt. Auf dem iPhone werden die Bilder auch im Gästebuch in der „korrekten“ Ausrichtung dargestellt.

Wenn die Bilder mit dem iPhone gemacht werden (gefühlt betrifft das heutzutage ca. 80% aller Bilder), wird in den EXIF-Daten des Bildes die Ausrichtung gespeichert. Der iPhone-Besitzer bekommt nichts davon mit, lädt das Bild ins Gästebuch hoch und wundert sich dann, warum es falsch ist.

Als Lösung habe ich mich entschlossen, die Bilder beim Upload zu drehen (und zu skalieren). Mit der Funktion exif_read_data kann man die EXIF-Daten entsprechend auslesen. Das Bild wird auf maximal 800 Pixel Breite oder Höhe skaliert.

$image = imagecreatefromstring(file_get_contents($_FILES['picture']['tmp_name']));
$exif = exif_read_data($_FILES['picture']['tmp_name']);
if(!empty($exif['Orientation'])) {
	switch($exif['Orientation']) {
		case 8:
			$image = imagerotate($image,90,0);
			break;
		case 3:
			$image = imagerotate($image,180,0);
			break;
		case 6:
			$image = imagerotate($image,-90,0);
			break;
	}
}
 
// scale image
$ratio = imagesx($image)/imagesy($image); // width/height
if($ratio > 1) {
	$width = 800;
	$height = round(800/$ratio);
} else {
	$width = round(800*$ratio);
	$height = 800;
}
$scaled = imagecreatetruecolor($width, $height);
imagecopyresampled($scaled, $image, 0, 0, 0, 0, $width, $height, imagesx($image), imagesy($image));
 
imagejpeg($scaled, $targetFilePath);
imagedestroy($image);
imagedestroy($scaled);

Tags:

Geschrieben in default | Kommentare deaktiviert für Bilder mit PHP gemäß EXIF-Daten drehen