Van egy régi PHP kód, ami adatbázisból generál tartalmat.
A tartalom generálásához a következő feltételt használja: "WHERE statusz = 'Aktív'". Igen, ékezetes karakter van a feltételben. A PHP forráskód ISO-8852 kódolású, mint ahogy az adatbázisban is latin2 karakterkészlettel tárolódnak az adatok, latin2_hungarian_ci használatával. A generált HTML tartalom is ISO-8859-2 kódolású.
Minden tesztelésre használt böngészőnkben rendben lefut a kód, és helyes kódolású tartalmat generál.
De a naplóban ritkán GET kérelmek esetén megjelenik a következő hibaüzenet:
"PDOException: SQLSTATE[HY000]: General error: 1267 Illegal mix of collations (latin2_hungarian_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' ... "
Elképzelni sem tudom, hogy milyen kérelmeket küldhetnek ilyenkor a böngészők. A napló alapján az URL ugyanaz, mint a tesztelésre használt URL, tehát gondolom, valamilyen spéci header-t küldenek, vagy épp valamit nem küldenek ... nem tudom. Azt meg végképp nem, hogy ez hogyan befolyásolhatja a fixen lekódolt PHP-ból indított SQL kérés karakterkészletét.
Az SQL kérelemben nem szerepel semmilyen egyéb paraméter, amit a kérelem küldhetne.
Ha bárkinek van használható ötlete, örömmel olvasnám.
- 1278 megtekintés
Hozzászólások
Nem megoldás a karakterkódolásra, de érdemes lehet átgondolni ezt a statusz mezőt, mondjuk egy int segítségével kódolni az értékeket. Ez nem csak ezt a problémát oldaná meg, hanem az a kellemetlen helyzet is elkerülhető, hogy hibás eredményt kaptok, ha "Aktív" és "Aktiv" vegyesen szerepel.
Debian - The "What?!" starts not!
http://nyizsa.blogspot.com
- A hozzászóláshoz be kell jelentkezni
Sajnos egyelőre ez nem járható út. Ez egy élesben futó nagy rendszer, az adatszerkezeten nem tudok módosítani. Természetesen én is örülnék, ha a kód kicsit barátibb lenne, de most elsődleges feladat megtalálni a hiba okát, és megoldani.
- A hozzászóláshoz be kell jelentkezni
A hiba valódi oka az el...ott adatszerkezet, tehát azt kell megjavítani. Vagy minimum a lekérdezést, ami az ékezetes mezővel operál átvakarni - mondjuk WHERE UPPER(statusz) LIKE 'AKT%'
Ami a hibaüzenetből nekem lejön, az az, hogy az egyik az multibyte, a másik meg nem, és ezekre nem vizsgálhatsz egyenlőséget, ami valahol jogos is... Hogy miért érkezik az "=" egyik oldalára multibyte-os string, na az jó kérdés...
- A hozzászóláshoz be kell jelentkezni
Szerintem nem az a fő kérdés, hogy miért nem jó, hanem az, hogy hogyan lehetséges az, hogy ezer lekérésből 999 esetben jó, 1 esetben pedig nem? Mi lehet a különbség a kérelmek között, és hogyan hathatnak így a scriptre?
- A hozzászóláshoz be kell jelentkezni
Mondjuk az, hogy máshol van a hiba, mint ahol gondolod?
PDOException: SQLSTATE[HY000]: General error:
1267 Illegal mix of collations (latin2_hungarian_ci,IMPLICIT)
and (utf8_general_ci,COERCIBLE) for operation '=' ...
Ebben a hibaüzenetben van PHP-sorszám is?
- A hozzászóláshoz be kell jelentkezni
Szemfüles vagy! :) A php sorszám az '=' jel utáni ... helyén van. A hibaüzenet tartalmazza a konkrét SQL kódot is, amivel baja van, és az abban a php fájlban fordul elő egyedül, tehát elég jól beazonosíthatóan a PHP indítja el a hibás SQL kérést.
- A hozzászóláshoz be kell jelentkezni
Off: Boldogult úrfikoromban magam is sok hibakeresésben vettem részt, és valahogy azt figyeltem meg, hogy mindig a konkrét információk (teljes hibaüzenet, programrészlet, táblaleírás stb) segítenek, nem pedig a helyzet igazságtalansága fölötti meditáció.
- A hozzászóláshoz be kell jelentkezni
Hányszor éltem át én is azt, hogy órákon keresztüli sikertelen hibakeresés végén végül betűről betűre elolvastam a hibaüzenetet, és az vezetett nyomra ... :)
De megnyugtatlak, megnéztem a hibában jelzett sor, és ott nem volt más, mint a PHP kódban közvetlenül megadott SQL lekérdezés, ami a hibaüzenetben is szerepelt.
- A hozzászóláshoz be kell jelentkezni
Ott lesz a megoldás tippre, egy rossz enkódolású karakterláncot ad át valami, és az hívódik meg.
- A hozzászóláshoz be kell jelentkezni
Igen, én is ezt tippelem, csak ugye nem ez a kérdés, hanem az, hogy 1000-ből miért csak 1-szer rossz a fixen beírt karakterlánc kódolása, a többi 999 esetben miért nem rossz? Ugyanis mind ékezetes karakter, ami az SQL-ben szerepel, az ott van közvetlenül megadva a PHP kódban. Nem kívülről jön, nem más PHP fájlok include-jával kerül be, hanem abban a PHP fájlban van konstansként megadva.
- A hozzászóláshoz be kell jelentkezni
az nem lehet, hogy az adatbazis mezo/tabla collation-je valtozik valami kulso hatasra a php-tol fuggetlenul? (script/job/trigger/stb)
Support Slackware: https://paypal.me/volkerdi
- A hozzászóláshoz be kell jelentkezni
Köszönöm, ez egy olyan lehetőség, amire nem is gondoltam eddig.
Ha a hibaüzenet következetesen sorolja fel az illesztéseket, akkor az adatbázisbeli collation rendben van, és az = jobb oldalán lévő string konstanst illesztené utf-8 szerint. Ebből arra gondolok, hogy nem az adatbázissal lesz a gond. Ennek ellenére legalább egy új irány, amerre keresgélhetek.
- A hozzászóláshoz be kell jelentkezni
Az a konstans az milyen encoding-gal íródott fájlban van...?
- A hozzászóláshoz be kell jelentkezni
hogy hibás eredményt kaptok, ha "Aktív" és "Aktiv" vegyesen szerepel.
Az ilyen dolgokat nem a kőkorszakba való visszatéréssel kell elkerülni, hanem megfelelő input validációval, check constraintraintekkel, stb.
- A hozzászóláshoz be kell jelentkezni
A böngésző nem áll kapcsolatban a mysql-szerverrel (vagy ki tudja, lassan a CPU mikrokódja is JavaScript), szóval inkább PHP-oldalon kellene nézelődni. Kezdetnek: ugye volt set names 'latin2'
(vagy mysqli_set_charset('latin2')
) ?
Szerk: azt írja az internet, hogy az '=' nem feltétlenül '='-t jelent, más esetben is előfordulhat, hogy két mező egyezését vizsgálja a szerver, mondjuk egy "UNION" esetén (a duplaszűrés miatt).
- A hozzászóláshoz be kell jelentkezni
Erre írtam, hogy minden általunk futtatott tesztben helyesen fut a kód. Ez egy fix url, még csak egyedi paramétereket sem kap.
Én is azt hittem, hogy a böngésző nem hat a szerveroldali szkript karakterkódolására, de ha ezerből 1-szer ilyen hibát ad úgy, hogy nincsenek kívülről jövő paraméterek, akkor mégsem tudok másra gondolni.
Amúgy PDO és nem mysqli, de igen, beállítottuk a mysql felé a karakterkészletet.
Konkrétan a csatlakozás parancs a következő:
$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
, PDO::ATTR_PERSISTENT => true
, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'latin2' COLLATE 'latin2_hungarian_ci'"
);
$dbh = new PDO( 'mysql:host=localhost;dbname=dbname;charset=latin2', user, pwd, $options );
- A hozzászóláshoz be kell jelentkezni
em lehet hogy valamelyik tábla mégis más kódolású és némely lekérésnél van csak behivatkozva péládul joinnal?
- A hozzászóláshoz be kell jelentkezni
(Sőt nem is táblánként, hanem mezőnként lehet különböző karakterkódolást/collationt beállítani.)
- A hozzászóláshoz be kell jelentkezni
A web szerverről nem volt szó, annak is van default és vhost esetén is karakter kódolás beállítása. Olyat láttam régebben, hogy több vhost volt, és egyiken nem volt jól beállítva minden, hasonló hibát hozott.
Apache esetén .htaccess file a site rootban is tartalmazhat ilyet.
Másik ok, ami okozhatja: kézzel a Firefoxban például át tudom állítani az enkódolást menüből, és akkor a form azzal a karakterkészlettel küld adatokat. Ez is lehet.
Tippre állami projekt vagy a fejlesztő egyik első munkája ez. Én csak állami projektekben láttam hasonlókat, de hát valakinek azt is el kell készíteni.
Ha még nincs itt, eljön majd az, hogy indiai, filippínó juniorok írják a Magyarország.hu új verzióját, akik a vállalkozói lánc negyedik, ötödik szintjén lesznek csak. (ahol régen a legolcsóbb informatikus volt)
- A hozzászóláshoz be kell jelentkezni
A webszerver apache, és a .htaccess fájlok nincsenek engedélyezve.
Az űrlap karakterkészletével már nekem is volt gondom, és ha ez egy POST kérelem lenne, vagy legalább egy GET FORM url, akkor ki is tudnám próbálnám, de itt nincs űrlap. Azonban ahogyan az űrlap elküldi a karakterkészletet, gondolom a böngésző is küldhet valamilyen accept header-t, amiben jelzi, hogy milyen karakterkészletben várná az url tartalmát, és amit a webszerver még a PHP futtatása előtt értelmez.
A PHP generál saját header-t a válaszhoz, amiben beállítja a karakterkódolást, tehát az Apache AddDefaultCharset értéke elvileg nem juthat érvényre. Azért a biztonság kedvéért most ezt is beállítottam, de logikusan ez nem lehet a megoldás.
[off]
Az állami tipp nem jött be. Meglepő módon ez egy élő piaci vállalkozás, ahol az eredeti tulaj anno a "legolcsóbb" megoldást választotta, egy önjelölt programozó személyében...
- A hozzászóláshoz be kell jelentkezni
"egy önjelölt programozó" kontra ,,"legolcsóbb" megoldás'' - a kettő csak első látásra van pariban... Most például kiderült, hogy az "olcsó" megoldáshoz még kell x óra debug/fixálás, hogy rendesen működjön, illetve utána ennek - és a vélhetően szép számmal a kódban lévő hasonló "egyszerű megoldások"-nak - a kigyomlálása is szép és az időt bőségesen zabáló feladat lesz...
- A hozzászóláshoz be kell jelentkezni
Egyrészt ez így van.
Másrészt azonban hiába dolgozom évtizedek óta PHP-val, mégsem tudom, mi állhat a jelenség mögött, így számomra mindenképp hasznos továbbtanulási lehetőség ez az eset. :)
- A hozzászóláshoz be kell jelentkezni
[on]
akkor én klónoznám a rendszert és teszt környezetben próbálnám a hibát előhozni
ha valami oknál ott is előfordul, és nem tudni, mitől, akkor teljes mysql logolást kapcsolnék be, és ott látszódna, hogy mi után jön ez, akkor a kódban is megkereshető, hogy merre lehet
az élő rendszeren is növelném a logolást, hátha kiderül valami, access log, error log, bármi
megnézném a sémában vagy bárhol máshol, hogy hol van utf8_general_ci
honnan jön az "Aktív" szó? hány helyről? ott mi az enkódolás? minden esetben jó? ha megnyitod latin2 módolású editorral, mindenhol jól látszódik az "Aktív" szó? Lehet olyan is, hogy Latin2 kódolású fájlban utf-8-ként szerepel ez a szó, mert olyan editorral nyúltak hozző, ahol ez volt az encoding. Az is okoz hasonlót. Kb ezt fogod ott látni: "AktĂv". Ha pedig fordítva: "Akt"[xED]"v". Az [xED] egy nem megjeleníthető karakter.
[off]
Kb ugyanezek a személyek dolgoznak sokszor az állami projekteken is, mert más nem vállalja az adott áron/feltételekkel. Tehát a "személyt" kb eltaláltam, a megrendelőt nem.
- A hozzászóláshoz be kell jelentkezni
Tesztelni azért nehéz teszt környezetben, mert semmilyen módon nem tudtuk még reprodukálni a hibát. Próbáltuk az access.log-ban a User-Agent alapján beazonosított böngészőkkel, de azokkal sem reprodukálható a hiba. Sőt, nem is csak egyféle böngészőben jön elő. Generálta már I-phone kliens, de Windows böngésző is.
Tehát tesztelném, ha tudnám...
Emiatt is nyitottam ezt a témát, már több ember több extrém esetbe ütközött már. Hátha valaki valamikor látott már hasonlót, vagy van ötlete, mi lehet az a környezeti paraméter, amivel érdemes lenne tesztelni. Elvégre a hiba nem lehet túl bonyolult. Valahogy egy GET kérést kell elindítani, hogy a PHP-ban foglalt string konstans karakterkódolása befolyásolható legyen.
- A hozzászóláshoz be kell jelentkezni
Végül mi volt a megfejtés?
- A hozzászóláshoz be kell jelentkezni
db-n belul egy tobb tablat is erinto query-ben az egyik tabla ikyen, a masik meg oyan kodolasu.(marmint kulonbozik a collartion isezaltal)
information _schema megmondja, hogy melyik
- A hozzászóláshoz be kell jelentkezni
Gondolom a péklapát apróra van törve a kódot elkövető hátán...
- A hozzászóláshoz be kell jelentkezni
Állami projekteknél, feltörekvő vállalkozóknál az ékezet használata hasonló módon teljesen megszokott, az a szint. Meg hogy egy óriás queryben hívnak le mindent, így nem tud működni a cache. Ezért egy lekérdezés másodpercek a sok left join meg hasonlók miatt. Meg nincsenek indexek, stb.
Alvállalkozó alvállakozójának alvállalkozójának az ismerőse készítette a kódot, aki még gimibe jár, de már készített több honlapot! :)
- A hozzászóláshoz be kell jelentkezni
És gondolom a "select * from *" jellegű lekérdezés eredményét péhápéból szűri/rendezgeti...
- A hozzászóláshoz be kell jelentkezni
Van az az use-case, amikor gyorsabb ;)
- A hozzászóláshoz be kell jelentkezni
Sajnos nincs megfejtés azóta sem. Egyelőre együtt élünk a hibaüzenettel, mivel ritka. Valós ügyfél még nem jelezte, pedig reméltem, mert akkor lenne infó a kliens környezetről.
Amúgy nem állami szféra, hanem olcsóban dolgozó - valószínűleg önképzett - vállalkozó műve volt, aki azóta már eltűnt.
- A hozzászóláshoz be kell jelentkezni
ezt nezted? miert nem?
- A hozzászóláshoz be kell jelentkezni
Igen, és megvallom, nem is értettem, hogyan jön ide. Arról van szó, hogy teljesen azonos GET kérelmek néha hibát okoznak, néha nem. Ugyanarról a tábláról, ugyanarról a mezőről van szó.
- A hozzászóláshoz be kell jelentkezni
select TABLE_SCHEMA, TABLE_COLLATION, count(1) from INFORMATION_SCHEMA.TABLES group by TABLE_SCHEMA, TABLE_COLLATION;
(vagy valami ilyesmi)
- A hozzászóláshoz be kell jelentkezni
De azért jól emlékszem, ugye, hogy végülis nem idézted be sem a teljes hibaüzenetet, sem a releváns programrészt?
- A hozzászóláshoz be kell jelentkezni
Arra gondolok, hogy a probléma oka az lehet, a get nem feltétlen abból html outputból érkezik, amit várnál.
Hiba esetén loggolni kellene a felhasználói adatokat, mint pl https://www.php.net/manual/en/function.get-browser.php
- A hozzászóláshoz be kell jelentkezni
Ez jó ötlet, nem ismertem. Az Apache logja alapján próbáltam a böngészőt beazonosítani, és valami összefüggésre rájönni, de sikertelenül. Ez lehet, hogy többet el fog árulni.
- A hozzászóláshoz be kell jelentkezni
Tippjeim:
- valaki ezer éves böngészővel tolja, ami nem mainstream
- fixre vette valamelyik user az char kódolást
- egy bot nyomja a get-et
Ps.: A kódra ráférne egy refaktor
- A hozzászóláshoz be kell jelentkezni
nem, ez nem jo otlet, teljesen fals. futtasd mar le azt a kurva INFORMATION_SCHEMA-s query-t!
- A hozzászóláshoz be kell jelentkezni
Ha ez lenne a baj, akkor kb minden írás gond lenne. Nem?
- A hozzászóláshoz be kell jelentkezni
a hibauzenet egyertelmuen azt sugallja, ezert kellene lefuttatni vegre.
- A hozzászóláshoz be kell jelentkezni
Értem, de azt is írja, hogy nem mindig csinálja. Sőt! Nagyon ritkán.
- A hozzászóláshoz be kell jelentkezni
jol van, en kiszalltam, oldjatok meg, have fun!
- A hozzászóláshoz be kell jelentkezni
Megoldástól bármi nagyon messze van. Üvölt az egész a trógerságról. Ennek a mezőnek, bool, enum -nak kellene lennie, nem stringnek, valamint mindennek utf8-nak így 2023-ban.
- A hozzászóláshoz be kell jelentkezni
Nem, ez egy speciális, ritkán használt tábla (és/vagy programrész), mondjuk áfabelföldi lemúrok esetére.
- A hozzászóláshoz be kell jelentkezni
Haladt valamit mostanában? Még mindig nincs jobb gondolatom, mint hogy a táblák között van olyan ritkán használt nünüke, aminek a charset/collate értéke különbözik a többiétől.
- A hozzászóláshoz be kell jelentkezni
mar az elejen ezt mondtam, de az OP lathatoan l*szarja
- A hozzászóláshoz be kell jelentkezni
Az OP nem leszarja, hanem már elmondta, hogy olyan fix kérelmekről van szó, amik mindig ugyanazon a táblák ugyanazon mezőit használják. Nem tábladefiníciós problémáról van szó, mivel a kérelmek 99%-ában hibaüzenetek nélkül lefutnak ugyanazok a kérelmek, amik - és megint ismételem - ugyanazokból a táblákból ugyanazokat a mezőket használják.
- A hozzászóláshoz be kell jelentkezni
Azért beidézhetné a derék OP a komplett SQL utasítást...
- A hozzászóláshoz be kell jelentkezni
Azért jó lenne, ha jönne egy visszaigazolás az OP-tól, hogy 'végül megnéztük a kódot, és észrevettük, hogy a hiba nem az általános esetben, hanem csak a kisnyugdíjas banánimportőrök adatait tartalmazó táblával kapcsolatban jelentkezik.'
- A hozzászóláshoz be kell jelentkezni
Off: közben fájlba gépeltem ezt is, hátha jól jön valamikor valakinek:
https://lzsiga.users.sourceforge.net/ekezet.html#Q0227
- A hozzászóláshoz be kell jelentkezni
hmm jo kis gyujtemeny, boormarkoltam, 1x meg jol johet nekem is, bar azert ebbol sokat en is tudtam mar
- A hozzászóláshoz be kell jelentkezni
Tippre a futtató rendszeren a lokalizációs változóknál a LANG vagy LC rész nem latin2-re van konfigurálva, vagyis a latin2 nincs a felsorolt lehetőségek között, hanem default UTF8-at használ. Próbaképp megpróbálnám a szervert LANG
="hu_HU.ISO-8859-2" /path/binary formában futtatni, megnézni ilyenkor is sír-e a logban.
“The world runs on Excel spreadsheets.” (Dylan Beattie)
- A hozzászóláshoz be kell jelentkezni
A kérdésből nem derült ki a "PHP / MySQL" verzió.
Bár már több mint 10 éve nem PHP-zok, de van pár dolog amire már akkor is érdemes volt oda figyelni:
A PHP file-ok kódolására. Azaz, hogy egységes legyen minden file-ban, pláne ha az egyik beölti ("include"-olja) a másikat.
Ha az egyik ilyen (ISO-8852), a másik olyan (utf8, stb.) akkor az pont ilyen hibákat tud okozni ha emlékeim nem csalnak.
Pl.: Előfordulhat az, hogy ha ez a logika egy megosztott (több helyről is hivatkozott) fájlban van akkor a betöltőtől is függhet a viselkedés ha annak eltérő a kódolása.
file1.php (ISO) -> shared.php (ISO) (jó)
file2.php (UTF8) -> shared.php (ISO) (rossz és csak ennél az ágnál jön a hiba)
Ez mindenképp a szerveren érdemes ellenőrizni, mert lehetett hiba a fájl átvitelben (deployment) is ha az nem olyan módon történt.
Én még körülnéznék az index-ek körül, hogy nincs-e valami corruption.
A másik MySQL kapcsolat kódolása, de ha félszemmel jól láttam itt a hozzászólásoknál akkor az megfelelően került beállításra.
- A hozzászóláshoz be kell jelentkezni