Luettelen alla aihealueittain tekemäni aihepiirit. Paluulinkkeinä tähän aihepiiriin on tämä valikko ja sivun yläreunassa oleva linkki Aihepiiriluettelo.
| |||||||||||||||
| Aihepiiriluettelo > Sekalaisten tietotekniikkasivujen etusivu > Sekalaisia > Dynaaminen rakenne PHP:llä > Selaintunnistukset (jakso 3/4) |
|---|
PHP:llä selaimia tunnistettaessa perusongelma on siinä, että selaimia voidaan tunnistaa vain selainten tunnistautumismerkkijonoista (UA strings) PHP:n sisäänrakennettujen muuttujien, esim. $HTTP_USER_AGENT avulla.
<?php print $HTTP_USER_AGENT; ?>
Yllä mainittu komento tulostaa selaimesi tunnistusmerkkijonon, mikäli Web-palvelimen asetukset sen sallivat. On kuitenkin paras luoda tähän tarkoitukseen uusi muuttuja, esim. $userBrowser = $_SERVER['HTTP_USER_AGENT']; (käytän esimerkeissäni $userBrowser-muuttujaa).
Palvelinkohtaisia huomautuksia:
Palvelimen PHP-asetuksissa saattaa olla register_globals=Off. Tällöin $HTTP_USER_AGENT ei toimi. $HTTP_USER_AGENT jne. ovat sisäänrakennettuja globaaleja, joiden näkyvyysalue kattaa koko sovelluksen (ts. ne ovat sovellusmuuttujia). Ne ovat käytettävissä kaikillä sivuilla ilman sen kummempia määrittelyjä. Sen sijaan kun koodissa määrätään muuttujan global sanalla globaaliksi, määritetään sen vaikutusalueeksi ko. skriptisivun (tosin esim. include-funktion avulla tällä voidaan jäljitellä sovellusmuuttujia). $_SERVER muuttujaa käyttämällä voi luoda uusia skriptikohtaisia yleismuuttuja. Esim. koodin
<?phppitäisi tulostaa selaimesi tunnistusmerkkijonon, joka näkyy tämän tekstin alapuolella:
global $userBrowser;
$userBrowser = $_SERVER['HTTP_USER_AGENT'];
print $userBrowser;
?>
CCBot/1.0 (+http://www.commoncrawl.org/bot.html)
Eräs ongelmallisimmista tunnistettavista on Netscape 4.x -sarjan selaimet. Ne kun antavat käytännössä hyödynnettäväksi vain Mozilla ja sen versionumeron. Alla esimerkki erään Netscape 4.x -selaimen antamasta tunnistusjonosta:
Mozilla/4.79 [en] (Win98; U)
Tunnistusjonoa Mozilla/4. käyttävät useimmat markkinoilla olevat selaimet, joten muut selaimet tulee raakata pois.Alla koodi, jossa ensin funktion stristr() avulla tunnistetaan MS IE, Mozilla Gecko ja Opera -selaimet sekä Mozilla/4 merkkijono (kyseistä funktiota käytettäessä ei ole merkitystä ovatko kirjaimet isoja vai pieniä).
$MSIE = (stristr($userBrowser, "MSIE") || stristr($userBrowser, "Internet Explorer")); /* Funktionstristr()ensimmäinen argumentti on merkkijono, josta etsitään. Jälkimmäinen on alimerkkijono, jota haetaan. */
$Opera = stristr($userBrowser, "Opera");
$Gecko = stristr($userBrowser, "Gecko");
$Moz4 = stristr($userBrowser, "Mozilla/4");
$NN4 = ($Moz4 && !$MSIE && !$Gecko && !$Opera);
Tunnistamatta jäävät sellaiset selaimet, joiden tunnistusmerkkijonossa mainitaan Mozilla/4. ja jotka eivät ole MS IE, Opera tai Netscape -selaimia. On kuitenkin mahdollista tunnistaa selaimet tietyltä väliltä. Mielekäs väli olisi tunnistaa selaimet, jotka ovat Mozilla/4.00 uudempia ja Mozilla/5.0 vanhempia. Nämä selaimet voidaan tunnistaa käyttämällä floatval() funktiota, jonka avulla merkkijonot voidaan kääntää desimaaliluvuiksi (käytetään engl. nimitystä double):
$Moz4All = ((floatval(substr(stristr($userBrowser, "Mozilla"),8, 3)) > 4.0) && (floatval(substr(stristr($userBrowser, "Mozilla"),8, 3)) < 5.0)); /* Ensimmäinensubstr()funktion arvo määrittää mistä kohtaa merkkijonon alusta alimerkkijono alkaa ja jälkimmäinen määrittää merkkijonon pituuden. Jos arvon loppuun tulisi välilyönti ja kirjaimia, ne eivät haittaa, sillä niiden mahdollisuus on otettu huomioon funktiossa.ctype_digit()avulla suoritettua arvotarkistusta ei tarvita. Saamani s-postin mukaan PHP:n float-tietotyypissä (liukuluku) tulee varmistaa, että tietotyyppi on liukuluku. Vertailevan liukuluvun voi myös pilkkoa explode()-funktiolla pisteen kohdalta ja vertailemalla erikseen syntyviä kokonaislukuja (ts. pisteen etu- ja jälkipuolta) intval() funktiota käyttäen. */
Palvelinkohtaisia huomautuksia:
Kaikki palvelimet eivät tue floatval() funktioita, sillä se on tuettu PHP 4.2.0 lähtien, mutta toimivuuden saa aikaiseksi vanhemmissa PHP-versiossa käyttäjän määrittelemällä funktiolla.
Joissakin tapauksissa tarvittava käännösfunktio on intval() (esim. Gecko/20001108 varten (intval(substr(stristr($userBrowser, "Gecko"),6, 8))). Selaintarkistukseni ei ota huomioon aivan kaikkia selaimia, mutta useimmat kuitenkin. On myös huomattava, että jotkin selaimet käyttävät joko MS IE:n tai Mozilla Gecko -selainten esityskonetta, jolloin ne otetaan huomioon MS IE ja Gecko -selaimia etsittäessä. Maininnan arvoisia selaimia ovat Linux käyttöjärjestelmässä käytettävissä oleva Konqueror ja Macissa Safari. Ne voi tunnistaa aivan samaan tapaan kuin muutkin selaimet. Alla on eräs Safarin tunnistusmerkkijono:
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/48 (like Gecko) Safari/48
JavaScript-koodauksessa voitaisiin kysyä if (document.layers), jota tukee vain Netscape 4.x -sarjan selaimet. Ongelmana olisi kuitenkin se, että kyselyjä ei voitaisi laittaa muuttujiksi (esim var 4NN4 = (...);) ja Netscape 4.x täytyy huomioida erityisellä tavalla.
Toinen ongelmakohta on tunnistamatta jääneet DOM-selaimet. JavaScript-koodauksessa voidaan kysyä if (document.getElementById) eikä selainten tunnistusmerkkijonoja tarvita. Ei ole mitään mieltä yrittää selvittää mitkä kaikki selaimet tukevat DOMia. Jos esim. halutaan määritellä DOMia tukeville selaimille tietty CSS tunnistuksessa voidaan edetä seuraavasti:
<?php
include('...'); /* Tiedosto sisältää muuttujamääritykset. */
if ($NN4){echo "<!--\n";}?>
<link rel="stylesheet" ...
...
<?php if ($NN4){echo "-->\n";}?>
ja siihen liittyvät muuttujamäärittelyt
).JavaScript ja PHP tunnistuksia voidaan myös yhdistellä. Ensin niin pitkälle kuin mahdollista PHP:llä ja selaimille, joille se ei sovellu tuotetaan tarvittava JavaScript-koodi tai viittaus JavaScript-tietostoon:
...
else {
echo "<script language=\"JavaScript\" type=\"text/javascript\" src=\"../Navigoinnit/AdviceBrowserSpecificCSS.js\"></script>"; }
Tavanomaiset (X)HTML-selainten ohella on myös WML-dokumenttien selailemiseen luotuja kännykkäselaimia. WML 1.x muistuttaa niin paljon XHTML:ää, että pienellä moduloinnilla on mahdollista luoda samasta materiaalista sekä WML 1.x:ää että (X)HTML:ää ymmärtäville selaimille eri versiot.
WML 1.x sisältää HTML:ään verraten vähän elementtejä. Jos sisältö on yhteinen, käytetään elementtejä ja attribuutteja, joita WML 1.x -selain ei tunnista, mutta joista ei pitäisi olla sille haittaa. WML:ssä on puolestaan elementtejä ja attribuutteja, jotka eivät kuulu XHTML:ään. Seuraavat elementit ovat yhteisiä (WML 1.2 elementeistä on myös englanninkielinen taulukko
):
HEAD-elementti.META-elementti (tuetut attribuutit ovat osittain eri).P ja PRE (jälkimmäinen vain WML 1.2:ssä).EM).A.IMG (kuvaformaatti on eri, joten tarvitaan skripti, joka valitsee eri kuvat).BR).FIELDSET, INPUT, SELECT, OPTGROUP ja OPTION.Mikäli WML-selaimia tuetaan ainakin seuraavat asiat tulee ottaa huomioon:
. Esim. HTML
4.0 tason koodaus riitä. Mielekäs peruskoodaus on XHTML
1.0, jossa ei käytetä aivan kaikkia XHTML:n piirteitä.card elementeillä jaksoihin eikä kokoavaa
runko-osan elementtiä ole lainkaan). On välttämättä
luotava käyttöympäristöriippuvaisia runko-osan aloituksia
ja dokumentin päätöksiä.id-attribuutit (jos rinnalla on name attribuutti,
arvojen tulee olla identtisiä esim. <a name="anchor1" id="anchor1">).BLOCKQUOTE) ja kaikissa
muissa lohkoissa, joissa tekstin tulee välttämättä olla
eri rivillä, sisältö kappaleiksi (esim. <li><p>...
</p></li>). Vaikka WML 1.x tukeva selain ei sisennäkään
tekstiä oikein, teksti ei kuitenkaan jää lukukelvottamaksi. Tavanomaisen selaintunnistuksen sijaan WML-selaimet voitaisiin periaatteessa
tunnistaa mime-tyypin perusteella eli sen perusteella millaisia
tiedostotyyppejä selaimet suoraan (ilman lisäosia) tukevat. Muuttujina
käytettääisiin joko $_SERVER['HTTP_ACCEPT'] tai
$HTTP_SERVER_VARS['HTTP_ACCEPT'] muuttujaa (jälkimmäinen
välttämätön, jos globaaleja muuttujia ei sallita). Alla
on testi, joka ilmoittaa toimiiko systeemi käyttämälläsi
selaimella riittävässä määrin. Testi myös listaa
selaimesi ilmoittamat mime-tyypit (alla testikoodi):
Selaimesi ilmoittaa palvelimelle riittävän määrän tuettuja mime-tyyppejä!
Selaimesi ilmoittaa seuraavat mime-tyypit:
text/html
application/xhtml+xml
text/xml;q=0.9
text/plain;q=0.8
image/png
*/*;q=0.5
<?php
$MimeTypes = $HTTP_SERVER_VARS['HTTP_ACCEPT'];
if (stristr($MimeTypes, "application/xhtml+xml") || stristr($MimeTypes, "text/html"))
{print "...";}
else {print "...";}
print "...";
$aMimeTypes = explode(",",$_SERVER['HTTP_ACCEPT']);
for($i=0;$i<count($aMimeTypes);$i++){
echo $aMimeTypes[$i] . "<br />";
?>
Testi meni riittävässä määrin läpi eräällä Opera ja eräällä Mozilla Gecko -selaimella, mutta ei MS IE 5.5:llä. Systeemi voisi toimia, jos kaikki WML-selaimet ilmoittavat tukevansa WML:ää ja ensin kysytään stristr($MimeTypes, "wml". Mikäli WML-selaimet eivät niin toimi, WML-selaimille pitäisi keksiä jokin muu tunnistuskeino.
Esittämäni moduloinnin vaihtoehtona on raskas XSLT-muunnos, jossa dokumentti luodaan ensin XML:nä ja muunnetaan joko WML 1.x tai XHTML dokumenteiksi.
Uudemmat kännykkäselaimet osaavat XHTML:ään perustuvaa WML 2.0:aa. Niille voi toteuttaa optimiratkaisun yksinkertaistetuilla XHTML-dokumenteilla. Tällaisten selainten täysi huomioiminen saattaa edellyttää erilaisia naviointi- ja Web-sivujen runko-osien rakennemoduuleja.
| Sivun jaksot: | Introjakso | Edellinen jakso | Seuraava jakso![]() | Viimeinen jakso![]() |