probleem met htmlentities

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

De Clercq Andy

De Clercq Andy

09/04/2015 16:10:18
Quote Anchor link
Hallo,
Op mijn website zee ik allerlei vreemde tekens en na opzoekingswerk bleek dit (vermoedelijk) een probleem met de manier van opslaan/uitlezen.
Met volgende functie probeer ik dit p te lossen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
function kennisbank()
{

$sqlkennis='SELECT * FROM tblkennisbank
            INNER JOIN tblpagina
            ON tblpaginaId=tblKennisbanktblpaginaId
            ORDER BY tblKennisbankNieuw DESC,
                tblKennisBankHits DESC
                LIMIT 0,20'
;
$querykennis=mysql_query($sqlkennis)or die(mysql_error());
while ($resultkennis=mysql_fetch_array($querykennis))
    {

    $sopschrift=htmlentities($resultkennis['tblKennisbankOnderwerp'], ENT_COMPAT, "UTF-8");
    echo "<a href=\"$resultkennis[tblPaginaLink]\" title=\"$resultkennis[tblKennisbankOnderwerp]\" class=\"kennisbanklink\">$sopschrift test</a>&nbsp - &nbsp";
    }
}

?>

Bij het uitlezen van "gewone" records, geen probleem.
Bij gebruik van "rare" tekens krijg ik niks terug.
Kan iemand helpen?
Dank bij voorbaat!
 
PHP hulp

PHP hulp

22/12/2024 13:26:35
 
Ivo P

Ivo P

09/04/2015 16:39:08
Quote Anchor link
om te beginnen is een definitie van een raar teken misschien wel handig.

Waar de een een é al raar vindt, is dat bij een ander mogelijk bij < of & het geval, danwel met ?

Toevoeging op 09/04/2015 16:39:57:

(op de plek van he ? stond in mijn post een chinees teken. Kennlijk kan PhpHulp daar ook niet zo goed mee overweg)

Toevoeging op 09/04/2015 16:42:25:

wat is trouwens de tekenset van de pagina?
Wat die van de verbinding met de database?

Wt voegt htmlentities toe aan functionaliteit? Die functie heb je niet nodig als je tekensets goed staan. Hooguit heb je htmlspecialchars() nodig om < en > weer te geven.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

09/04/2015 17:20:39
Quote Anchor link
Echt heel erg interessant om te lezen: http://www.joelonsoftware.com/articles/Unicode.html
 
Thomas van den Heuvel

Thomas van den Heuvel

09/04/2015 20:42:02
Quote Anchor link
^ What he said.

Van PHP.net:
Quote:
If the input string contains an invalid code unit sequence within the given encoding an empty string will be returned, unless either the ENT_IGNORE or ENT_SUBSTITUTE flags are set.

Oftewel: de data is waarschijnlijk met de verkeerde character encoding opgeslagen.
Oftewel: de data in je database is in zekere zin corrupt.

Nu valt deze waarschijnlijk wel te repareren met een eenmalige omzetting, maar je zult van tevoren een grondige analyse moeten maken van wat er precies aan de hand is.

EDIT: èn voorzieningen moeten treffen zodat dit in de toekomst niet meer misgaat!
Gewijzigd op 09/04/2015 20:42:49 door Thomas van den Heuvel
 
De Clercq Andy

De Clercq Andy

09/04/2015 22:21:56
Quote Anchor link
Met rare tekens bedoel ik het deelteken, accenten enzo worden ruitvormige tekens met vraagtekens in
Voor wat ik vind in google heeft dit te maken met de manier van opslaan.
Dit is de tabel die ik gebruik:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
- phpMyAdmin SQL Dump
-- version 3.5.8.1
-- http://www.phpmyadmin.net
--
--
Host: 10.246.17.25:3306
-- Generation Time: Apr 09, 2015 at 08:10 PM
-- Server version: 5.5.42-MariaDB-1~wheezy
-- PHP Version: 5.3.3-7+squeeze15

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
--
Database: `karpovmeetskarp`
--

-- --------------------------------------------------------

--
--
Table structure for table `tblkennisbank`
--

CREATE TABLE IF NOT EXISTS `tblkennisbank` (
  `tblKennisbankId` int(11) NOT NULL AUTO_INCREMENT,
  `tblKennisbankOnderwerp` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `tblKennisbankOmschrijving` varchar(250) NOT NULL,
  `tblKennisbanktblpaginaId` int(11) NOT NULL,
  `tblKennisbankHits` int(11) NOT NULL DEFAULT '0',
  `tblKennisbankNieuw` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`tblKennisbankId`)
)
ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

--
--
Dumping data for table `tblkennisbank`
--

INSERT INTO `tblkennisbank` (`tblKennisbankId`, `tblKennisbankOnderwerp`, `tblKennisbankOmschrijving`, `tblKennisbanktblpaginaId`, `tblKennisbankHits`, `tblKennisbankNieuw`) VALUES
(1, 'Karpov', 'Carrière en palmares van Anatoly Karpov', 8, 1, 1),
(
2, 'Hans Böhm', 'info over Hans Böhm, alias Mister schaak', 10, 103, 1),
(
3, 'Bezverkhni Mikhail', 'Bezverkhni Mikhail winnaar Koningin Elizabeth wedstrijd 1976', 13, 47, 1),
(
5, 'Schaakclub Karpov Deinze', 'Schaakclub Karpov Deinze', 15, 147, 1),
(
4, 'Thomas Van der Plaetsen', 'Thomas Van der Plaetsen', 14, 243, 1);

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
?>

Samen met de inhoud, hier merk je bij de laatste record een ander teken dan ö.
Nochtans gebruik ik hier volgens mij geen andere instellingen dan diegene die standaard worden meegegeven.
Alvast bedankt voor de reacties!
 
Thomas van den Heuvel

Thomas van den Heuvel

10/04/2015 01:25:54
Quote Anchor link
Okay, tegen beter weten in ga ik hier opnieuw een poging wagen om zo simpel mogelijk uit te leggen wat dit mysterieuze ding "character encoding" nu precies is, en hoe je hier correct mee om moet gaan.

Een character encoding is de manier waarop symbolen (waar een tekst uit bestaat) in het geheugen worden opgeslagen (denk hierbij aan nullen en enen, bits en bytes). Twee identieke teksten (reeks symbolen) zien er in het geheugen mogelijk compleet verschillend uit als deze verschillende character encoderingen hebben.

Vergelijk:
Afbeelding
Een ISO-8859-1 tekst (latin1 in MySQL)

met
Afbeelding
Een UTF-8 tekst (utf8 in MySQL)

Je zou een character encoding kunnen zien als een soort van indicatie van de "taal" waarin gesproken wordt.

Wanneer je zo'n tekst weergeeft in bijvoorbeeld een HTML-document en je aangeeft hoe deze bytes (of byte-reeksen) geïnterpreteerd moeten worden (door middel van een character encoding) dan worden deze vertaald naar de juiste bijbehorende symbolen (de karakters en andere exotische tekens op je scherm).

Je webserver serveert bijvoorbeeld een document waarbij deze tegen je browser zegt "dit is een "engelse" tekst". Vervolgens onderneemt je browser een poging om de tekst in het "engels" weer te geven.

Als je echter een tekst (met character encoding A) weergeeft op je scherm, en je geeft daarbij aan dat deze weergegeven moet worden in character encoding B, dan is de kans groot dat deze data verkeerd geïnterpreteerd wordt, en daarmee ook verkeerd wordt weergegeven.

In dit geval serveert je webserver bijvoorbeeld een document aan je browser met de mededeling "dit is een "franse" tekst" (terwijl de inhoud nog steeds "engels" is). Je browser zal dan een dappere, maar waarschijnlijk redelijk vruchteloze, poging ondernemen om de "engelse" tekst in het "frans" weer te geven. Het is dan haast onvermijdelijk dat er verwarring ontstaat over de interpretatie van het document. Het kan ook gebeuren dat de webserver (en ook het document zelf) helemaal geen indicatie geeft in welke "taal" het document is opgebouwd. De browser zal dan mogelijk terugvallen op een standaard "taal" die mogelijk helemaal niets te maken heeft met de "taal" van het document.

De lering die je hier uit kunt trekken is tweeledig:
- het is altijd beter om ondubbelzinnig te zijn over de "taal" die je spreekt om verwarring te voorkomen
- je moet er zorg voor dragen dat het document ook echt in deze "taal" is geschreven (en niet alleen maar doet alsof)

Dit wordt nog iets complexer wanneer er nog een stap zit in de uitwisseling van data: de variant waarin je gebruik maakt van een database.

Schematisch is de communicatie als volgt:
database <--> webserver <--> browser

Hier zijn dus twee plekken waar er mogelijk misverstanden kunnen ontstaan over de "taal" die je spreekt: tussen de database en de webserver (bij het opslaan en uitlezen van gegegevens) en tussen de webserver en de browser (bij de interpretatie van het geserveerde document).

De eenvoudigste oplossing om problematiek met character encoderingen te voorkomen is door ervoor te zorgen dat je overal dezelfde taal spreekt.

De meest gangbare taal (character encoding) die voor de meeste toepassingen tegenwoordig wel voldoet is UTF-8. Als je zorgt dat je overal UTF-8 gebruikt (iets wat op deze site NIET gebeurt, LOL) dan zal dit geen nieuwe problemen creëren. Ik zeg "nieuwe", want misschien HEB je al problemen, misschien zonder het zelf te weten, totdat je besluit dat je alle character encoderingen gelijk wilt trekken, en dan blijkt er bijvoorbeeld dat er VERTAALFOUTEN zijn opgetreden bij het opslaan van je gegevens. Deze zullen dan eenmalig gecorrigeerd moeten worden.

Wat is dan "overal"? Nou...
* In je database
- de database, tabellen en kolommen hebben een character encoding
- de DATA in je tabellen heeft een character encoding (die hopelijk overeenkomt met je tabel- en kolomdefinities)

* In je database-CONNECTIE
- bij het maken van een verbinding geef je aan in welke taal je wilt communiceren (via een aanroep van een _set_charset() functie)

* In het uiteindelijke document wat je serveert
- middels een header() aanroep en of via een meta-tag geef je aan wat het Content-Type en de character encoding is

* En tevens: de bestanden zelf waar dit uiteindelijke document uit opgebouwd is: denk aan alle PHP-, HTML-, CSS- en JavaScript-bestanden. Deze hebben elk (en zijn opgeslagen in) een ongeschreven of expliciete character encoding. Dit leidt minder vaak voor problemen omdat de karakters (symbolen) die hierin gebruikt worden meestal beperkt blijven tot het "standaard ASCII repertoire" en de wat meer exotische symbolen worden voorgesteld door hun HTML-entiteit (die weer bestaat uit karakters uit de standaard ASCII-set, denk bijvoorbeeld aan € en &euro;). Het is meestal de "dynamische content" (waarbij dus een mogelijk extra vertaalmoment wordt geïntroduceerd waar dingen mis( kunnen )gaan) die voor problemen zorgt.

Wat er bij de topicstarter waarschijnlijk aan de hand is is het volgende: hij heeft geen (of een afwijkende) character encoding aangegeven bij het maken van een verbinding met zijn MySQL-database. Maar MySQL is slim: als deze ziet dat je een verbinding maakt met "latin1" (meestal default) en de tabellen "utf8" (UTF-8 in MySQL) dan zal deze DATA vertalen van utf8 naar latin1 bij het opvragen en vertalen van latin1 naar utf8 bij het wegschrijven. MySQL doet dus een serieuze poging om e.e.a. in goede banen te leiden maar het gaat meestal toch mis omdat:
- je ofwel aangeeft dat je latin1 data aanlevert, maar stiekem data stuurt die al utf8 is,
- ofwel je data uitleest en aangeeft dat je deze in latin1 wilt hebben, en deze data vervolgens serveert alsof het UTF-8 is!

Het lijkt erop dat de data in de database van de topicstarter 1x teveel is vertaald naar UTF-8. Oftewel: de aangeleverde data was al utf8, maar bij de connectie werd ofwel niet aangegeven dat je al middels utf8 communiceerde, ofwel werd er helemaal niets aangegeven, waarbij mysql dus latin1 veronderstelde en de data alsnog (en dus te vaak) vertaalde naar utf8 om het te laten passen bij de encodering van de tabeldefinities. (EDIT: al onderbouwt de database-dump van de topicstarter dit niet, want hier staat "DEFAULT CHARSET=latin1" - feit blijft dat (het er iig op lijkt dat) de data in de dump 1x te vaak als utf8 geëncodeerd is)

De stappen die je moet ondernemen bij dit soort zaken zijn bijvoorbeeld:
- het voor dit moment stoppen van nieuwe invoer
- het repareren / gelijkschakelen van al je character encoderingen
- het analyseren welke data niet in de goede encodering is opgeslagen (hier kan ik evt nog wel wat over vertellen)
- HET MAKEN VAN EEN BACKUP VOORDAT JE OOK MAAR IETS IN JE DATABASE WIJZIGT
- het eenmalig repareren van deze data (of als dit niet heel erg veel is, het opnieuw invoeren ervan na het gelijkschakelen van alle encoderingen, is meteen een goede test om te zien of alle data nu niet door de vleesmolen gaat)

Zo, laat dit maar eens ff bezinken :p.
Gewijzigd op 10/04/2015 09:19:48 door Thomas van den Heuvel
 
Ivo P

Ivo P

10/04/2015 08:25:42
Quote Anchor link
Je ziet hierboven dat je een tabel maakt met defaultset Latin1.
Kolom1 is numeriek,
Kolom2 een tekst die utf8 is,
Kolom3 is niet expliciet aangeduid, dus Latin1

Dan kijken we naar de inserts.
Karpov is de 2e waarde die dus in de 2e kolom gast.
Niets bijzonders.
In de 3e Value zien we duidelijk de weergave van unicode tekens als è. (Omdat unicode multibyte is, zie je meestal 2 rare tekens op de plek waar een accented teken hoort).

Deze unicode sla je vervolgens op in de latin1 kolom....

Verder zelfde verhaal nog steeds.
In wat andere uitleg: http://wiki.pfz.nl/charactersets
 
Thomas van den Heuvel

Thomas van den Heuvel

10/04/2015 08:49:38
Quote Anchor link
Maar hoe verklaar je deze regel dan?
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
(2, 'Hans Bhm', 'info over Hans Bhm, alias Mister schaak', 10, 103, 1)

(EDIT: LOL deze site worstelt ook nog met UTF-8, maar das niks nieuws)
De tweede en derde kolom hebben verschillende character encoderingen (EDIT zie db dump van de topicstarter).

MySQL zou deze zelfde passage "Hans Böhm" verschillend opgeslagen moeten hebben omdat deze automatisch vertalingen uitvoert lijkt mij, TENZIJ:
- de data van de verschillende kolommen elk op een afzonderlijke manier en via verschillende character encodingen wordt aangeleverd en opgeslagen, en/of
- de toevoeging "CHARACTER SET utf8" pas is uitgevoerd NADAT deze informatie al in de database was opgeslagen (en hierbij was de data oorspronkelijk al niet van de juiste character encoding ofzo)

Anyhoo, het heeft geen zin om een situatie waarvan je weet dat deze niet klopt eindeloos te bestuderen - maak deze eerst correct (schakel alle character encoderingen gelijk), kijk welke problemen er dan (nog) spelen, en ga deze vervolgens oplossen.
Gewijzigd op 10/04/2015 08:51:23 door Thomas van den Heuvel
 
Ivo P

Ivo P

10/04/2015 09:25:11
Quote Anchor link
precies: alles gelijk zetten.
Want 1 kolom unicode en de andere niet: dan krijg je hooguit dat Böhm wel goed in de titel staat maar niet in de tekst zelf.

Nog los van de vraag wat er nu werkelijk in de table staat.
Zolang er in de hele keten van onderdelen (tabellen, kolommen, verbindingen, headers, meta-tags, default browser settings, php-settings) er 1 fout zit (en dat niet alleen bij het weergeven, maar ook bij de scripts die de data eerder opsloegen in de database), dan gaat er iets mis.

Dus: alles nalopen, en de huidige data ook als "kapot" beschouwen en niet doorbeunen tot het huidige "carrière" uit de database goed op je scherm staat, want dan heb je mogelijk alleen een pleister geplakt voor een huidig probleempje
 
De Clercq Andy

De Clercq Andy

10/04/2015 15:56:09
Quote Anchor link
Hallo,
bedankt voor al deze duiding. Ik snap het probleem nu wel.
Als ik de tabellen in mijn database wil omzetten qua collatie zie ik meerdere soorten van UTF 8.
Welke soort moet ik nemen?
Verder heb ik in mijn php bestanden volgende regel in de header gezet:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
?>

Vermoedelijk zit ik op dat niveau ook goed daarmee.
Klopt het zo een eetje wat ik hier aan het doen ben?
 
Thomas van den Heuvel

Thomas van den Heuvel

10/04/2015 16:22:38
Quote Anchor link
collation is niet hetzelfde als character encoding

collation is de manier waarop karakters worden vergeleken (wanneer zijn symbolen gelijk) en gesorteerd (welke symbolenreeks komt alfabetisch voor een andere symbolenreeks bij het sorteren op een tabelkolom)

Dit zegt dus niets over hoe deze symbolen zijn geëncodeerd (in het geheugen staan opgeslagen).

De bovenstaande regel is HTML, deze hoef je dus niet in een PHP-blok te zetten... Het alternatief voor zo'n HTML meta-tag is een PHP-header:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
header('Content-Type: text/html; charset=UTF-8');
?>

Hiermee geef je trouwens enkel aan dat je je document als UTF-8 wilt weergeven, maar je moet er (eigenlijk) ook voor zorgen dat dit document zelf (mits hier van zichzelf speciale karakters in zitten) als UTF-8 is opgeslagen. De meeste fatsoenlijke hedendaagse code-editors kunnen dit (en doen dit wellicht al automatisch).

Dan moet je je connectie met je database nog fixen, daar moet je met een _set_charset('utf8') aanroep afdwingen dat er in de "UTF-8 taal" gecommuniceerd wordt.

Dan moet je al je tabeldefinities gelijk trekken.

En dan moet je nog zorgen dat de DATA in je tabellen ook met de UTF-8 encodering (utf8 in MySQL) is opgeslagen. Gezien de hoeveelheid data die er nu in zit en bij wijze van test zou ik eerst alle vorige stappen doorlopen en dan je database gewoon opnieuw vullen.

Dit bovenstaande verhaal is eigenlijk een herhaling van wat al is verteld trouwens, behalve de opmerking over collation wellicht.
Gewijzigd op 10/04/2015 16:26:38 door Thomas van den Heuvel
 
Ivo P

Ivo P

10/04/2015 16:30:02
Quote Anchor link
over het sorteren:

wij Nederlanders zullen een ö vaak naast de o zetten bij het sorteren.
Een Duitser vat een ö op als de combinatie "oe" en zet deze dan na de "od" en voor de "of"

Terwijl een Zweed 29 letters kent: na de Z volgen nog de ä, de ö en de å

Sorteer je op z'n Zweeds dan komt de ö dus pas na de z en de ä.

Vandaar dat dat ook aangegeven kan worden. (net trouwens of je onderscheid denkt te gaan maken tussen hoofd- en kleine letters)
 
De Clercq Andy

De Clercq Andy

10/04/2015 16:33:42
Quote Anchor link
De tabel die ik hier toon is maar één tabel van de database. De data opnieuw ingeven is niet echt een optie. Bestaat er een ander techniek voor?
 
Thomas van den Heuvel

Thomas van den Heuvel

10/04/2015 16:39:43
Quote Anchor link
Ja maar dat wordt niet echt heel eenvoudig. Je moet namelijk eerst een goede analyse maken van wat er per tabel / kolom aan de hand is voordat je dingen om gaat zetten. Je kunt niet zomaar de character sets van je tabellen en kolommen wijzigen als de DATA die er in zit niet in de huidige variant geëncodeerd is omdat de omzettingen van de DATA naar alle waarschijnlijkheid fout gaan bij het aanpassen van de structuur...

Over hoeveel tabellen / records / data hebben we het?

En sorry dat ik het zeg, maar ik hoop dat je hier iets van leert.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.