Tietokannan taulussa on tallennettuna tekstiä, joka sisältää skandeja. Kun php-skripti hakee kannasta tällaista tietoa selaimelle, selain näyttää skandit outona mössönä. Minkälaisella SQL-kyselyllä saisin muutettua taulun sisältämät skandit html-entiteeteiksi? Skandit esiintyvät muun tekstin seassa, joten lienee ainakin aika monimutkaista, jos ei peräti mahdotonta.
Oikea ratkaisu ei ole puuttua datan muotoon vaan säätää enkoodaukset kohdalleen sekä sivulta että tietokantayhteydestä.
Datan esittävän sivun enkoodaus on UTF-8:
<meta http-equiv="Content-Type" content= "text/html; charset=ISO-UTF-8">
ja MySQL:n merkistö: UTF-8 Unicode (utf8) ja MySQL-yhteyden aakkosjärjestys: utf8_general_ci
Pitäisikö MySQL:n asetuksia muutaa ja miten? Entä säilyykö taulun data entisellään, vai muuttuuko sekin samalla jotenkin?
Metatagisi on virheellinen. Ota välilyönti pois =-merkin perästä ja ISO- pois merkistöstä; oikea nimi on pelkkä UTF-8.
Toimivatko UTF-8-skandit muuten oikein sivulla? Mitä seuraava PHP-koodi tulostaa?
<?php $teksti = "åäö"; echo "<p>$teksti, ", rawurlencode($teksti), "</p>"; // Toimiva UTF-8-tulostus: "åäö, %C3%A5%C3%A4%C3%B6". // Tulostus, jos virhe on HTML-puolella: "åäö, %C3%A5%C3%A4%C3%B6". // Tulostus, jos virhe on PHP-puolella: "???, %E5%E4%F6". // Tulostus, jos molemmissa on virhe: "åäö, %E5%E4%F6".
Varmista, että data tulee MySQL:ltä UTF-8-muodossa. Aakkostus ei mitenkään liity datan siirtoon. Voit käyttää tarkistukseen samaa metodia kuin yllä: oikeat UTF-8-ääkköset koostuvat kahdesta tavusta, mikä näkyy rawurlencode-funktion tuloksessa. (Jos tarkistus tuntuu hankalalta, hae jotain ääkköstekstiä tietokannasta, enkoodaa rawurlencode-funktiolla ja lähetä tänne.)
(Edit. Muutin tunnistusohjeita.)
Korjasin metatagin ja tulostaa "åäö, 6". Skandit kylläkin tulostuivat aiemminkin sivulla oikein, paitsi siinä osassa tekstiä, johon haetaan kannasta tekstiä javascriptillä. Kannasta haetaan nimipäivä kyseiselle päivämäärälle ja koska tämän päivän nimissä ei ole skandeja, en nyt näe heti, olisiko ongelma vaikka nyt ratkennut näillä ohjeillasi. 8.5 on Åken päivä, joten silloin veri punnitaan :) Suuret kiitokset avustasi.
Jos kerran sivu muuten toimii ja käyttää UTF-8:a, luultavasti tietokantayhteyden merkistö on pielessä. Käytä aiemmin linkittämääni funktiota mysql_set_charset oikean merkistön valintaan.
Itselläni oli sama ongelma AJAXin kanssa. utf8_encode() sisään teksti joka sisältää ääkkösiä. Melkoista purkkaa ja itseänikin kiinnostaisi parempi ratkaisu ongelmaan.
Othnos: Ongelmasi on siis ilmeisesti siinä, että käsittelet palvelimella dataa ISO-8859-1-merkistössä mutta selain haluaa sen UTF-8:na. Ongelma saattaa siis olla sama kuin tässä keskustelussa, ratkaisun olen jo antanut!
No otetaan nyt vielä uudestaan.
Selain tulkitsee tekstin sen mukaan, mitä HTTP-otsikoissa sanotaan. Otsikon voi asettaa PHP:llä:
<?php header("Content-Type: text/html; charset=UTF-8"); // Tavalliselle tekstille text/plain. // ISO-8859-1-enkoodatulle tekstille charset=ISO-8859-1.
Nettisivujen kohdalla saman asetuksen voi lisäksi kirjoittaa meta-tagiin.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
Vanha tieto ei vaikuta myöhempiin sivunlatauksiin (esimerkiksi AJAXilla), vaan niissä täytyy ilmoittaa taas jokaisessa uudestaan merkistö.
MySQL-tietokannassa on lukuisia merkistöasetuksia mm. datan tallentamiselle (ei vaikuta tässä), aakkostukselle (ei vaikuta tässä) sekä sille, missä merkistössä tekstiä siirretään PHP:n ja MySQL-palvelimen välillä. Tämä viimeisin on nyt se merkittävä asetus, ja kuten jo aiemmin sanoin, oikea merkistö pitää valita funktiolla mysql_set_charset (tai kyselyllä SET NAMES 'UTF-8', mutta tämä on huonompi vaihtoehto).
Ymmärsit nyt ongelman väärin, Metabolix. PHP:llä normaalisti tulostettu teksti toimii oikein, mutta AJAX haulla, esim. document.getElementById('kayttajat_div').
rauski3 kirjoitti:
"Skandit kylläkin tulostuivat aiemminkin sivulla oikein, paitsi siinä osassa tekstiä, johon haetaan kannasta tekstiä javascriptillä."
Kyseessä lienee sama ongelma.
En ymmärtänyt lainkaan väärin. Oletko ilmoittanut MySQL:lle oikean merkistön ja HTTP-vastaukseen oikean merkistön, ja et kai itse muuta tekstiä väärään merkistöön tässä välissä? Oletko tarkistanut esittämälläni rawurlencode-tempulla, että myös tietokannasta tulevan datan merkistö on oikea?
Merkistöasioissa on turha jossitella ja muttailla. Kun merkistö ei tietyssä tilanteessa näy, jokin vaihe juuri tuolla matkalla on pielessä – siis tässä tapauksessa jokin vaihe linjalla MySQL → PHP → JS. Muunlaiset virheet ovat näihin verrattuna äärimmäisen epätodennäköisiä.
Kyseisellä mysql_set_charset-härpäkkeellä alkoi toimimaan, kuten jo aikaisemmin sanoit. En ollut tuolla määrittänyt koodausta ja muut meta yms. eivät toimineet, joten luulin ongelman olevan jossain muualla. Kiitokset tästä, voi lopettaa tuon purkan käytön.
Metabolix kirjoitti:
Jos kerran sivu muuten toimii ja käyttää UTF-8:a, luultavasti tietokantayhteyden merkistö on pielessä. Käytä aiemmin linkittämääni funktiota mysql_set_charset oikean merkistön valintaan.
Nimet haetaan kannasta näin:
$query="SELECT * FROM nimet WHERE pvm = '$today'";
$result=mysql_query($query);
$num = mysql_num_rows ($result);
mysql_close();
Mihin tuo mysql_set_charset pitäisi laittaa?
Jokaisen sivun alkuun (tai vaihtoehtoisesti includettamaasi sivuun jossa luot yhteyden). PHP.net:in mukaan valinta tehdään seuraavalla tavalla.
<?php //Yhdistetään tietokantaan $connect = mysql_connect('localhost','user','password'); //Valitaan merkistö kyseiselle yhteydelle mysql_set_charset('utf8',$connect); ?>
Hienoa,kiitokset! Voisiko sen vaihtoehtoisesti sisällyttää/yhdistää jotenkin tuohon $query="SELECT * FROM nimet WHERE pvm = '$today'"; lauseeseen? Voiko yhdessä kyselyssä ylipäätään ketjuttaa "komentoja", tai miksi niitä nyt kutsutaankin?
Metabolix kirjoitti:
Jos kerran sivu muuten toimii ja käyttää UTF-8:a, luultavasti tietokantayhteyden merkistö on pielessä. Käytä aiemmin linkittämääni funktiota mysql_set_charset oikean merkistön valintaan.
Asia oli, kuten tässä neuvoit ja homma toimii nyt oikein. Suurkiitokset avustasi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.