Will man wissen, welchen Browser und Version (und weitere Infos) ein Besucher nutzt und vielleicht Browser-Weichen in den PHP-Code einprogrammieren, dann kann Joomla helfen. Die Detektion ist längst nicht perfekt (Vivaldi wird beispielsweise als Chrome erkannt), jedoch vollkommen ausreichend für Grobes und Alltägliches. Wer mehr will, muss halt so was integrieren und verwenden: hisorange / browser-detect

Gemecker

Der Internet-Explorer 11 - teils Müll

Geschrieben 2019! Mittlerweile (2021) hat sich die Zahl der IE-11-Nutzer natürlich weiter zugunsten des Edge-Browsers (Chromium-Version) weiter reduziert und mein Gemecker unten ist in großen Teilen hinfällig. Da es in diesem Beitrag ja nicht nur um den IE11 geht, sondern generell um die Möglichkeit Browserdaten in Joomla zu detektieren, bleibt der Beitrag drinnen. Er bekam nur einen allgemeineren Titel.

Der Webbrowser Internet Explorer, auch die "aktuelle" Version 11, ist endgültig ein alter Schuh und lästig, wenn man modernere Technologien, flex-basierte Grid-CSS-Bibliotheken oder Vanilla-JavaScripte (ohne JQuery) in der eigenen Webseite verwenden will. Klar kann man alles zeitintensiv hinbiegen, aber in meiner eigenen Internetseite lade ich manche Dinge einfach nicht mehr, wenn ein IE daherkommt.

Zwar habe ich den ganz radikalen Schritt auch noch nicht gemacht, den Internet Explorer 11 komplett zu vernachlässigen, weil er allen Legenden zum Trotz weiterhin so zahlreich verwendet wird, dass ich als Kleinst-Unternehmer Besucher meiner Webseite, nur, weil sie ihren Wunsch-Browser verwenden, nicht einfach so arrogant wie zum Beispiel Joomla 4 (und viele andere) wegignorieren kann, aber es gibt einzelne Code-Stellen, wo ich aufgrund von Inkompatibilitäten das eine oder andere Nebensächliche einfach nicht lade, anstatt weitere Zeit in diesen altersschwachen Dinosaurier-Browser zu investieren. Deshalb verwende ich auch weiterhin JQuery (in aktuellster Version) statt zeitaufwendig auf aktuellere Vanilla-JavaScripte wie ECMAScript 6 (ES6) umzusteigen.

Arrogant, vielleicht auch nur inkonsequent, ist in diesem Zusammenhang aber auch Microsoft, die sich seit Jahren weigern, wenigstens offensichtliche Bugs im CSS-Bereich zu beseitigen. Wohl als Druckmittel, damit die Nutzer den Nachfolger des IE verwenden, den Edge-Browser.

Klar muss aber auch sein, dass man als Programmierer meines Erachtens ältere und potenziell unsichere Software (da nicht mehr vom Anbieter unterstützt), wie z.B. IE8, IE9 und vieles andere, grundsätzlich wegignorieren sollte, wenn da etwas nicht funktiniert. Joomla 3 hat da seinerzeit einen Riesenfehler gemacht beim Versprechen bestimmte PHP-, Browser-Versionen etc. bis ans "Joomla-3-Lebensende" (End OF Life, EOL) zu unterstützen. Da sind Software-Versionen dabei, die schon lange keine Sicherheits-Updates mehr bekommen. Das verleitet Webseiten-Betreiber und Internet-Surfer eben auch zur Bequemlichkeit, was Aktualität der Software anbelangt. Ich bin da skrupelloser ;-)

Was will ich? Beispiel-Szenario

  • Den IE-Nutzer beim Besuch einmalig oder mehrmalig darauf hinweisen, dass meine Webseite seinen Browser nicht vollumfänglich unterstützen könnte. Dafür verwende ich "Bootstrap-Toasts" in einem eigenen Modul (nicht Thema in diesem Beitrag).
  • Bestimmte Code-Bereiche überspringen, die z.B. JavaScripte laden, die vom Entwickler nicht explizit ausgewiesen sind als "IE11-kompatibel".
  • Vielleicht gelegentlich alternative Skripte (JS, CSS) speziell für IE laden.
  • Dafür brauche ich eine PHP-Weiche, die den Browser-Typ ermittelt und im besten Fall direkt mit Joomla-Mitteln und ohne weitere Last in Form von "Detect-Bibliotheken", die zwar viel mehr können, was ich aber gar nicht brauche.

PHP-Konstanten der Klasse WebClient

Muss man nicht, aber tue ich hier der Vollständigkeit wegen: Wenn man einen Blick in die o.g. PHP-Klasse WebClient wirft, die Joomla beigepackt hat (in Version 3.9.25 hier) wirft, sieht man zu Beginn eine Reihe von Konstanten die für Browser-Typen UND Geräte-Typen bzw. Betriebssystem definiert werden. In kommenden Versionen der Klasse können weitere hinzukommen.

const WINDOWS       = 1;
const WINDOWS_PHONE = 2;
const WINDOWS_CE    = 3;
const IPHONE        = 4;
const IPAD          = 5;
const IPOD          = 6;
const MAC           = 7;
const BLACKBERRY    = 8;
const ANDROID       = 9;
const LINUX         = 10;
const TRIDENT       = 11;
const WEBKIT        = 12;
const GECKO         = 13;
const PRESTO        = 14;
const KHTML         = 15;
const AMAYA         = 16;
const IE            = 17;
const FIREFOX       = 18;
const CHROME        = 19;
const SAFARI        = 20;
const OPERA         = 21;
const ANDROIDTABLET = 22;
const EDGE          = 23;
const BLINK         = 24;
const EDG           = 25;

In Zeile 48 finden wir den Internet-Explorer mit Konstante IE und Wert 17. Den Wert müssen wir uns nicht merken, aber die Konstante.

Der Edge-Browser steht in Zeile 54. Wollten wir den identifizieren, müssten wir uns also die Konstante EDGE merken. Wollen wir aber nicht.

Man sieht aber auch, dass z.B. der Vivaldi-Browser nicht berücksichtigt wird (kommt vielleicht noch?), auch nicht im späteren Code der Klasse. Da er die Chrome-Engine verwendet, wird man ihn damit Pi-Mal-Daumen mit Konstante CHROME voridentifizieren können, aber wird wohl nicht darum herum kommen, eigenen Code (Prüfen des so genannten UserAgent) aufschalten zu müssen. Auch den kann man übrigens recht leicht mit unten beschriebenen Client-Eigenschaften in Joomla auslesen (wer weiterdenkt).

Kurz: Nicht perfekt, die WebClient-Klasse, aber interessiert uns ja im Moment auch gar nicht. Was sie kann, reicht uns für unser Anliegen.

Den Internet Explorer und anderes erkennen

Theorie für interessierte `Spielkinder`

(Nahezu) überall in Joomla-Codes kann man auf das so genannte Application Object zugreifen. Das bringt mannigfaltige Informationen (ohne Umwege) mit, darunter auch eine Eigenschaft client, die Informationen beinhaltet über Browser, Betriebssystem, ob es sich um ein Mobilgerät handelt oder eine Suchmaschine (Robot)... Aber nicht per se! Joomla befüllt diese Eigenschaft erst bei Bedarf mit Werten.

Folgende Debug-Zeilen geben mir also je nach Zeitpunkt, wann ich sie in MEINEM Joomla verwende, ein mehr oder weniger uninformatives Ergebnis aus:

$app = Factory::getApplication();
echo '<pre>' . print_r($app->client, true) . '</pre>';exit;
Der Code gibt aus
Joomla\Application\Web\WebClient Object
(
    [platform:protected] => 
    [mobile:protected] => 
    [engine:protected] => 
    [browser:protected] => 
    [browserVersion:protected] => 
    [languages:protected] => Array
        (
        )

    [encodings:protected] => Array
        (
        )

    [userAgent:protected] => Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0
    [acceptEncoding:protected] => gzip, deflate, br
    [acceptLanguage:protected] => de-DE,de;q=0.8,en-GB;q=0.6,en-US;q=0.4,en;q=0.2
    [robot:protected] => 
    [detection:protected] => Array
        (
            [robot] => 1
        )

    [headers:protected] => 
)

Ein paar Eigenschaften sind mit Werten belegt, aber browser (Zeile 6) z.B. nicht und den brauchen wir ja. Hmm... Außerdem kommt man doch an die Eigenschaften gar nicht dran, weil die alle protected sind, oder?

Eine Eigenschaft befüllen

Nehme ich jetzt den obigen Code plus einer zusätzlichen Zeile 2 und lass mir das client erneut ausgeben, sehe ich, dass browser und browserVersion Werte bekommen haben (Firefox in Version 70.0), andere aber nicht.

$app = Factory::getApplication();
$app->client->browser;
echo '<pre>' . print_r($app->client, true) . '</pre>';exit;
Der Code gibt aus (gekürzt)
Joomla\Application\Web\WebClient Object
(
...
    [browser:protected] => 18
    [browserVersion:protected] => 70.0
...
)

Man muss also explizit Eigenschaften anfragen, damit die "Application" sie "zwischenspeichert".

Aber wie gesagt, alles nur erklärende Hintergrundgeschichten, weil es gibt ja noch...

Die Praxis

Vorarbeit. Wichtig für alle folgenden Code-Beispiele!
Entweder

In allen Joomla-Dateien befindet sich ja am Anfang eine Zeile der Art defined('_JEXEC') or die;. Unterhalb dieser Zeile setzen wir in der Datei, die weiter unten gezeigten Code verwenden will, die Zeile use Joomla\Application\Web\WebClient;, falls noch nicht vorhanden.

<?php
defined('_JEXEC') or die;

use Joomla\Application\Web\WebClient;
Oder

Sie verwenden unten im Code statt WebClient::IE das hier: Joomla\Application\Web\WebClient::IE

Internet Explorer erkennen

Wir haben uns oben die Konstante IE gemerkt, die für Internet Explorer ist bzw. genauer: alle Browser, die in Ihrem UserAgent ein "MSIE" drinnen haben. Da die Konstante in der Klasse WebClient definiert wurde, bekommen wir ihren numerischen Wert, indem wir im Code WebClient::IE verwenden und mit $app->client->browser abgleichen.

Meine Internet-Explorer-Weiche (Condition) sieht dann so aus:

$app = Factory::getApplication();

if ($app->client->browser === WebClient::IE)
{
   // TU SACHEN FÜR DEN INTERNET EXPLORER. IM ZWEIFELSFALL HÖR AUF, IRGENDWAS ZU MACHEN.
}
else
{
    // TU SACHEN FÜR ANDERE BROWSER
}
Ausführung beenden für Suchmaschinen (Robots) und Internet Explorer kleiner Version 10

Es gibt z.B. JavaSkripte für "optischen Firlefanz", die nur Last wären für Suchmaschinen und/oder die IEs kleiner 10 nicht abkönnen. Geht alles über Eigenschaft bzw. Objekt $app->client und mach ich so:

$app = Factory::getApplication();

if (
   $app->client->robot
   || ($app->client->browser === WebClient::IE
	   && explode('.', $app->client->browserVersion)[0] < 10)
){
   return;
}

Anmerkung: Zeile 6 für Versionsabgleich ginge wahrscheinlich eleganter mit PHP-Methode version_compare.

In der index.php des Templates für IE10+ ein anderes CSS laden

Da es seit IE10 die altbewährten Conditional Comments nicht mehr gibt, wäre das eine Möglichkeit, eine Weiche in Joomla-Templates einzubauen:

$app = Factory::getApplication();

if (
 $app->client->browser === WebClient::IE
 && explode('.', $app->client->browserVersion)[0] >= 10)
){
 // IE10/IE11 laden template-ie-10.css.
 HTMLHelper::_('stylesheet',
  'template-ie-10.css',
  array('version' => 'auto', 'relative' => true)
 );
}
else
{
 // Andere Browsers laden template.css.
 HTMLHelper::_('stylesheet',
  'template.css',
  array('version' => 'auto', 'relative' => true)
 );
}

Der Vollständigkeit halber: In CSS-Datei Internet Explorer 10 und 11 gezielt ansprechen

Da es Kunden gibt, die nach wie vor Wert darauf legen, dass diese beiden IE-Versionen auch unterstützt werden und ich nicht immer Lust habe für IE eigene CSS-Dateien anzulegen, kann man mit folgendem MediaQuery die Bereiche umgeben, die nur für diese beiden Browser gültig sein sollen:

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active)
{
 /* Hier CSS nur für IE10 und IE11 */
}