Portál AbcLinuxu, 2. května 2025 10:10
Tak nebyla, ono PHP 6 existovalo, jen se nikdy nevydalo :) viz. : http://www.wrox.com/WileyCDA/WroxTitle/Professional-PHP6.productCd-0470395095.html
pacman -Rcs php
pacman -S python-flask
php > $x = 'č'; php > echo $x[0]; Ä
php > $x = 'č'; php > echo mb_substr($x, 0, 1); č
php > $x = 'c'; php > $x[0] = 'č'; php > echo $x; Ä
Žiadne varovanie, veď prečo by aj keď na miesto 1 byte sa snažím vložiť 2 byte, že.
php > $x = 'c'; php > $x[0] = 'XXX'; php > echo $x; XOpět odkazujete na jeden konkrétní byte a jako vstup mu předáváte více bajtů - do jednoho bajtu se (jak známo) vejde právě jeden byte - zbytek řetězce je ignorován. Explicitní kontrola zda je v tomto případě řetězec delší než 1 byte a následné vyvolání warningu je trochu diskutabilní - např. z hlediska výkonu (proč se starat o zbytek když plníte právě jeden bajt). Pokud chcete znak na konkrétní pozici nahradit jiným znakem, musíte (opět) použít funkce pro zpracování textových, nikoliv binárních řetězců. Mmch. v tomto případě je to trochu podobné např. v Javě - Stringy tam jsou totiž immutable a také nemůžete změnit znak, ale musíte si to explicitně zpracovat a vyrobit nový String.
In [1]: x = 'č' In [2]: x[0] Out[2]: 'č' In [3]: len(x) Out[3]: 1
Môžme prehlásiť, že podpora unicode v PHP je rovnaká ako podpora unicode v assembleri, alebo C.
V assembleri nemám problém nastaviť do registrov (alebo na stack podľa konvencie volania) adresu reťazca v pamäti, index znaku a adresu znaku pre nahradenie a spustiť subrutinu, ktorá vykoná nahradenie unicode znaku. A presne na takej úrovni je podpora unicode v PHP. V assembleri musím myslieť na to, že je to kus pamäte rovnako ako v PHP. V assembleri musím použiť subrutinu pre manipuláciu s unicode rovnako ako v PHP musím použiť funkciu pre manipuláciu s unicode. Ak to v jednom či druhom jazyku neurobím skončím s nesprávnym reťazcom.
Podpora unicode sa dá dopísať do ľubovoľného turing complete jazyka, ale za skutočnú podporu unicode považujem keď mi jazyk dovolí nemyslieť na to, či pracujem s unicode, alebo nejakými inými dátami.
Python, Js, Perl ... u všetkých týchto jazykov sa nemanipuluje priamo nad bytmi, nedá sa omylom rozbiť unicode reťazec. U PHP, C, Assembleru ... je naopak nutné dávať pozor na to, či probramátor pracuje s unicode, alebo so surovým kusom pamäte.
U PHP, C, Assembleru ... je naopak nutné dávať pozor na to, či probramátor pracuje s unicode, alebo so surovým kusom pamäte.U Pythonu taky, spousta funkcí teď vrací takové ty divné binární/buffer stringy, a pak mě vždycky strašně naštve, když to hodí během rozdělané práce exception že ho to nemůže nacpat do dekódovaného stringu.
Aspoň, že niečo vyhodí. Nie až tak dávno som prepísal linuxos.sk do pythonu pretože som tam mal príliš veľa neošetrených chýb nie len s unicode (viem je to jeden z mojich prvých PHP projektov a úplne prvý python projekt).
Mícháte jablka s hruškami - práce s textem vs. práce s binárními daty.
Tak prečo PHP mieša prácu s textom s binárnymi dátami?
To že vám PHP umožňuje pracovat se Stringem za pomoci jednotlivých bajtů je možnost, nikoliv nutnost.
Mnou spomenuté jazyky neumožňujú pracovať so stringom pomocou bytov. To je dosť podstatný rozdiel.
Problémov bolo viacej od substr, ktoré umožňovalo robiť všeličo od XSS po SQL injection ak sa reťazec sekol v nesprávnej časti znaku, mysql_escape_string namiesto mysql_real_escape_string, ereg namiesto preg, mnoho mnoho unsafe záležitostí jednoducho spočítané a podčiarknuté oplatilo sa mi viacej naučiť sa nový jazyk, nový framework a celé to napísať odznovu než opravovať chybný kód.
Ešte raz PHP umožňuje manipulovať unicode reťazcami nepovoleným spôsobom.
Podpora unicode v PHP sa nelíši od podpory unicode v asm.
máte je k dispozici 14+ let ať chcete nebo nechcete, zatímco asm Vám žádné takové nativní funkce nedává, musíte si je sám napsat.Nebo použiješ v asm existující C knihovnu, což je přesně ten přístup PHP -
mb_string
je nejspíš pouze nějaký tenký wrapper nad C knihovnou, žádné abstrakce navíc PHP neposkytuje, je to úplně ten stejný suchý záchod jako v asm.
V tom případě se můžeme začít dohadovat nad přesnou definicí toho co znamená "Podpora Unicode" :)Jsem pro "má datový typ pro unicode stringy". To totiž PHP, C, asm, etc. nemají...
Natívny v zmysle preložený do strojového kódu je aj v asm.
Len tak pre zaujímavosť nedávno som robil štatistiku prechodov zo znaku a na znak b v slovenskom texte aby som podľa neho zostrojil generátor pseudoslovenského textu. Skúste si v PHP so mb_* funkciami napísať program, ktorý z textu vypíše početnosť prechodov z predchádzajúceho na nasledujúci znak. V pythone je to:
from __future__ import unicode_literals from collections import Counter s = "ááááách" Counter(zip('\0' + s, s + '\0')).most_common()
A výstup:
[(('á', 'á'), 4), (('c', 'h'), 1), (('h', '\x00'), 1), (('á', 'c'), 1), (('\x00', 'á'), 1)]
Vďaka natívnej podpore unicode žiadne rozmýšľanie nad reprezentáciou reťazca (u pythonu3 sú unicode literaly default).
$s = "ááááách"; $map = array(); for ($i = 0; $i < mb_strlen($s); $i++) { $k = mb_substr($s, $i, 1) . mb_substr($s, $i+1, 1); if (!array_key_exists($k, $map)) $map[$k] = 0; $map[$k]++; }Výstup:
Array ( [áá] => 4 [ác] => 1 [ch] => 1 [h] => 1 )... Díky podpoře unicode žádné rozmýšlení nad reprezentací řetězce ...
To má zložitosť O(n2). Na dlhé texty nič moc.
A string is series of characters, where a character is the same as a byte. This means that PHP only supports a 256-character set, and hence does not offer native Unicode support.[zdroj] Dovolím si zvýraznit jistou část:
A string is series of characters, where a character is the same as a byte. This means that PHP only supports a 256-character set, and hence does not offer native Unicode support.Vzhledem k dosavadní diskusi to asi není dostatečné zvýranznění, takže:
A string is series of characters, where a character is the same as a byte. This means that PHP only supports a 256-character set, and hencePředpokládám, že následně nastane nesmyslná diskuse nad slovy "native support" a o nesmrtelnosti chrousta... Protože akecptovat nedostatek PHP, toho PHP fanbois nejsou fyzicky schopni...does not offer native Unicode support
Takže aby som to zhrnul pre indexovanie so zložitosťou O(1) musím pretypovať na UTF-32. Lenže to je nová zbytočná nekonzistentnosť v mojej aplikácii, takže je fajn prepísať celú webovú aplikáciu do UTF-32 (teda napísať na všetky miesta kde je to nutné konverziu, áno tento skvelý jazyk pri miešaní bytov s unicode nevyhodí výnimku ani varovanie), zdrojové kódy písať v UTF-32 (zvláda PHP zdroják napísaný v UTF-32?), alebo na všetky reťazce použiť konverziu a v šablóne pri každom výpise použiť konverziu. Takže ten jazyk ma vlastne núti zahodiť celú moju aplikáciu ak chcem zostať konzistentný. Tak to je skvelá abstrakcia, ktorú ponúkajú jazyky so skvelou (TM) podporou unicode.
Konzistencia Vašich názorov je niekde na úrovni pohotovostného sáčku na grcanie ktorý som kedysi vymyslel na internáte.
Díky podpoře unicode žádné rozmýšlení nad reprezentací řetězce ...
... detekovali vstupní kódování, poté překódovávali na unicode s pevnou šířkou znaku (UTF-32) a to samé nazpět při každé operaci, nebo by striktně určili že každý řetězec je jen a pouze např. zmíněné UTF-32
Takže buď musím ručne prekódovať v časti mojej aplikácie a potom musím používať mb_substr(..., 'utf-32') v časti kde používam UTF-32 a mb_substr(..., ['utf-8']) v časti kde používam UTF-8 a teda musím sa nutne zamýšľať nad aktuálnou reprezentáciou textu v časti aplikácie kde sa práve nachádzam (keďže som v tomto nekonzistentný a niekde používam UTF-8 a inde UTF-32), alebo musím nutne prepísať celú aplikáciu tak, aby interne používala UTF-32 a to je presne to, čo som napísal.
Mimochodom v mojom príklade vôbec indexáciu nepotrebujem, stačí mi iterácia všetkými prvkami so zložitosťou O(n) čo zvláda mimochodom bez problémov aj ICU (U8_NEXT) v C.
Inak vlastnú reprezentáciu používa PERL (či skôr rozšírenie NFC formy UTF-32 o rozsah 0x80000000-0xFFFFFFFF + tabuľka grafemov). Python používa podľa nastavení pri kompilácii buť UTF-16 alebo UTF-32.
Vaše argumentační omyly a veletoče nemění nic na tom že php podporu unicode má, můžete se třeba 100x postavit na hlavu.Jasnýýýý, že má
ale ano potřebujete, jen dokola odmítáte pochopit, že ta indexace probíhá skrytě zatímco můj příklad ji otevřeně přiznáváMimochodem, toto není pravda. Mirecův příklad používá iterátor, v tom je ten rozdíl.
Hlboko sa ospravedlňujem, nikdy by som si nedovolil rýpať do človeka, ktorý trpí dyslexiou za to, že nepochopil komentár.
Aby ste nemuseli prechádzať celým vláknom tak to zhrniem do 2 viet.
PHP má podporu unicode na rovnakej úrovne ako jazyky 1. a 2. generácie (asm/C). Jazyky 3 generácie a vyššie už zvyčajne majú samostatný dátový typ pre unicode, na ktorom nie je možné omylom seknúť znak v polovici.
indexace probíhá skrytě zatímco můj příklad ji otevřeně přiznává
Iterácia nevyžaduje indexáciu. Môžem prejsť celý utf-8 reťazec po znakoch (v každom kroku prečítam jeden znak a posuniem ukazovateľ na začiatok ďalšieho) a budem mať zložitosť O(n) a nie O(n2).
Jazyky 3 generácie a vyššie už zvyčajne majú samostatný dátový typ pre unicode, na ktorom nie je možné omylom seknúť znak v polovici.Abychom byli k tomu chudákovi zmatenému trochu fér, tak je nutno dodat, že nevalidní utf-8 stringy jsou bohužel možné i v některých vyšších jazycích např. python a JS. JS navíc AFAIK ani pořádně nenabízí možnost utf-8 validovat. V pythonu je podpora na mnohem lepší úrovni - datový typ, možnost validace, iterátory, apod. Imho nejlépe je na tom Rust, kde ani nedovolí nevalidní utf-8 string zkonstruovat.
(kdyby to bylo implementované stejně, nebyl by to jiný jazyk ...)Zvláštní logika. Když jazyk b implementuje jednu věc tak jako jazyk a, přestává být samostatným jazykem? Ale je fakt že vyřešením všech problémů PHP by to už zákonitě přestalo být PHP a začalo být jiným jazykem který má nějaký ucelený koncept a konzistenci místo „dortu pejska a kočičky“.
Funkcie / subrutiny pre prácu s unicode majú jazyky 1. a 2. generácie. Jazyky 3. generácie majú zvyčajne dátový typ unicode, ktorý nedovolí náhodnú manipuláciu bytmi. Keď to intrpretujete ako "daný jazyk nepodporuje unicode" je to Váš problém.
konstrukce $s[0] vracející byte na dané pozici
Konštrukcia $s[0] vracia 0-položku sekvencie.
To vysvetli všetkým tým, ktorí v tutoriáloch používali substr namiesto mb_substr. Keď som začínal vedel som o jazyku veľké prd. Až neskôr som zistil, že za určitých okolností mi substr sekne reťazec v polovici znaku, občas tak nešťastne, že keď sa v html ako nasledujúci znak nachádzal < tak to rozbilo layout HTML. Ak sa také niečo vyskytlo v generovanom js bol z toho XSS ako vyšitý.
To vysvetli všetkým tým, ktorí v tutoriáloch používali substr namiesto mb_substr.Špatné tutoriály nejsou problém PHP, stejně jako nebude problém Pythonu, když na něj napíšu tutoriál (špatný, protože neumím programovat).
Ešte raz PHP umožňuje manipulovať unicode reťazcami nepovoleným spôsobom.Python taky. Ergo Python nepodporuje Unicode.
substrhttps://secure.php.net/manual/en/function.mb-substr.php
mysql_escape_string namiesto mysql_real_escape_stringToto bylo od začátku rozbité a proto je v PHP už sto let normální databázový interface s parametrizovanými dotazy.
PHP Vám dává možnost přistupovat ke Stringu 2 odlišnými způsoby a je na Vás, který si zvolíte - podle toho, co potřebujete docílit.Ano, PHP dává možnost, jenže to API je, jako téměř vždy u PHP, nelogické a matoucí.
mb_strlen($string)
je jistě funkční, ale naprosto neintuitivní. $srting->length
by bylo mnohem lepší, jenže to by PHP muselo podporovat scalar objects...
Aha, takže z jedné off-topic debaty (balíčky pro Arch vs. údajná nepodpora Unicode v PHP) teď začne někdo další flamovat nad PHP vs. jiné jazyky?To už je tady trochu folklór, téměř každá zprávička o PHP má v diskuzi "debatu" o tom, jak je PHP špatný jazyk.
bflmpsvz()
, která by vracela 3*délku stringu + 5, tak se najdou lidi, kteří budou tvrdit, jak je to naprosto v pořádku a jak je to plnohodnotná podpora Unicode...
To mi pripomenulo funkciu gzgetss :D
To co jste právě popsal je situace kdy vlastně žádný vyšší jazyk podporu Unicode nemáTo není pravda. Viz třeba tady nebo tady.
Because strings are valid UTF-8, strings do not support indexing: let s = "hello"; println!("The first letter of s is {}", s[0]); // ERROR!!! Usually, access to a vector with [] is very fast.
foo_string.as_bytes()
a na to už se samozřejmě indexovací operátor použít dá. Je tím důsledně a jasně odděleno, kdy pracuješ s bajty a kdy s Unicode stringem.
Jde o to, že to rozhraní není matoucí. Narozdíl od PHP, které má pouze ekvivalent toho byte vectoru a ten string vůbec nemá, respektive emuluje ho tím bytevectorem + kupou haluzně pojmenovaných funkcí.
To, že ako prvé napadne človeka strlen (podľa názvu by mala vracať dĺžku reťazca no v skutočnosti vracia počet bytov). Správne by sa mala volať byteslen a mb_strlen by naopak mala byť strlen ak už chceme niečo čo nie je mätúce.
Jde o to, že to rozhraní není matoucí.Diskuze byla o nepodpoře Unicode v PHP, ne o přehlednosti rozhraní.
Explicitní kontrola zda je v tomto případě řetězec delší než 1 byte a následné vyvolání warningu je trochu diskutabilní - např. z hlediska výkonu (proč se starat o zbytek když plníte právě jeden bajt).A taky to pak vede k těm věcem jako v C#, kde nejde double narvat do floatu a musí se to všechno explicitně přetypovávat.
Ano, a to zejmena diky tomu ze HHVM ma JIT, kdezto PHP 7 ne. Ale pokud se v HHVM vypne JIT, tak je to neuveritelny snek (horsa jak php 5.4) :)
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.