Autor Zpráva
Joker
Profil
Autor: Joker
Odkaz na aktuální verzi textu: Základní kurz 15: Komunikace mezi PHP a JavaScriptem

zveřejněno
Odkud se vede diskuse k aktuálnímu stavu textu:
První příspěvek po poslední revizi textu
Joker
Profil
Poslední chybějící kapitola základního kurzu. Jelikož nemám žádné informace, že by na ní Radek9 pracoval, dal jsem dohromady první verzi. Zatím ji ještě nedávám do menu.
Kubo2
Profil
Joker, konečne existuje zrozumiteľný text, ktorý začiatočníkom od počiatku objasní ten najfrekventovanejší problém. :-)
Jan Tvrdík
Profil
Joker:
V části „Vložení do stránky“ to podle mě řešíš nebezpečně a zbytečně složitě. Pokud chceš předat data z PHP do JS, tak bys vždycky měl jít přes funkci json_encode. Ta ti řeší escapování a zároveň ti bude bez problémů fungovat i předávání pole.

Tedy správně by to mělo být:
<script type="text/javascript">
    var ip = <?php echo json_encode($_SERVER["REMOTE_ADDR"]); ?>;
</script>



U posílání požadavku přes obrázek bych uvedl i klasický příklad:
var img = new Image(); // případně méně magické document.createElement('img');
img.src = "...";
Joker
Profil
Jan Tvrdík:
Pokud chceš předat data z PHP do JS, tak bys vždycky měl jít přes funkci json_encode.
Tohle by asi bylo dobré tam napsat, ale neřekl bych, že to řešení s řetězcem je pro případ IP nějak nebezpečné. $_SERVER["REMOTE_ADDR"] pokud vím uživatel nemůže nijak podvrhnout ve smyslu, že by tam dostal svůj text (i když by se možná mělo zdůraznit, že to takhle platí jen pro data z důvěryhodného zdroje).
Jan Tvrdík
Profil
Příklady by pokud možno měly být bezpečné vždy, ne jen někdy, protože neznalý uživatel bude mít zrovna smůlu na ten případ, kdy to bezpečné nebude. Navíc v řetězcích budeš pravděpodobně výrazně častěji předávat obecně nebezpečná data, než 100 % bezpečná.

A neplatí to jen pro řetězce. I čísla bych vždy proháněl přes json_encode, protože uživatel většinou není schopen spolehlivě uhlídat, že v proměnné má skutečně číslo. On si dá třeba id do hidden políčka a už mu nedojde, že mu do toho políčka může zákeřný hacker dát úplně cokoliv.
Joker
Profil
Rozšířil jsem část Vložení do stránky o výklad json_encode a přidal jsem její použití i do části o JSONP. Taky jsem trochu rozšířil popis JSONP a AJAX a do části o vytváření požadavku přes obrázek přidal ukázku vytvoření objektu Image.
_es
Profil
Joker:
V texte je istá nesprávnosť či nepresnosť, no či je vhodné to nejako zložito opraviť...
Z něj je zřejmé, že PHP běží jinde a jindy, než JavaScript. V době zpracování PHP se stránka ještě ani neodeslala do prohlížeče, v době zpracování JavaScriptu zase už PHP skončilo a prohlížeč ani neví, že na stránce nějaký PHP kód byl.
Jednako v dobe spracovania dlhého PHP skriptu môže byť už časť HTML zobrazená v prehliadači a aj JavaScript sa spúšťa už hneď po načítaní obsahu elementu script, takže podstata problému je hlavne v tom, že PHP a JS bežia „inde“, než že bežia „inokedy“. Teoreticky môže aj JS nejako ovplyvniť PHP skript, ktorý ho generuje - asi sa to však nejako prakticky nikde nevyužíva.
Joker
Profil
_es:
I tak podle mě to tvrzení platí.
Dobře, teoreticky je možné spustit JavaScript ve chvíli, kdy ještě na serveru běží PHP generující tu stejnou stránku. Ale z pohledu toho skriptu samotného ho stejně musí nejdřív vygenerovat PHP a teprve když je pak přenesený na klienta, zpracuje ho JS.
Přesnější než jindy by bylo říct, že se zpracovává asynchronně, ale jindy vidím jako přijatelné zjednodušení pro začátečníky.

A ono není podstatné jen místo, ale i ten čas (resp. synchronnost), třeba databázový server taky může běžet jinde než aplikační, přesto jeden PHP skript může odeslat dotaz i zpracovat jeho výsledek, protože PHP po odeslání dotazu synchronně čeká na výsledek z databáze.

Teoreticky môže aj JS nejako ovplyvniť PHP skript, ktorý ho generuje - asi sa to však nejako prakticky nikde nevyužíva.
Zajímavá myšlenka, teoreticky to tak opravdu je.
PHP by vytvořil JS, odeslal na klienta, pak dělal nějakou dlouhou operaci, pak kontroloval existenci nějakého souboru a na základě ní něco dělal.
A JS by odesílal požadavek, který vytvoří nebo smaže ten soubor.

V praxi ale něco takového není použitelné, protože chování toho kódu může být náhodné a nejde spolehlivě předvídat.
Jan Tvrdík
Profil
Joker:
„Pokud bychom chtěli do JS předat hodnotu potenciálně obsahující konfliktní znaky“
Máš tam pořád podle mě obrácenou logiku u toho escapování. Programátor nesmí uvažovat, tak, že pokud tam jsou nebezpečné znaky, tak escapovat. Správně musí escapovat vždy, kromě výjimečných situací, kdy to escapované být nesmí. To „důkazní břemenu“ by prostě mělo být naopak. Ten tvůj způsob uvažování vede k takovým věcem, jako XSS přes HTTP hlavičky, protože se programátor naivně domníval, že mu tam nikdo nemůžeš poslat HTML. Samozřejmě, že může.
Joker
Profil
Jan Tvrdík:
Máš tam pořád podle mě obrácenou logiku u toho escapování.
Přeformuloval jsem tu větu, aby bylo ještě víc zřejmé, že typicky bude potřeba escapovat.
_es
Profil
Joker:
I tak podle mě to tvrzení platí.
Je tam viac tvrdení a často neplatia nielen teoreticky ale aj prakticky.
V době zpracování PHP se stránka ještě ani neodeslala do prohlížeče
PHP skript môže ešte stále bežať a časť stránky už môže byť spracovaná prehliadačom. Prípadne môže byť spracovaná aj celá stránka a skript môže ešte bežať - napríklad pracovať na nejakých len čisto serverových úlohách.
v době zpracování JavaScriptu zase už PHP skončilo
Ani to nemusí byť pravda - z rovnakého dôvodu ako v predchádzajúcom bode.

V praxi ale něco takového není použitelné, protože chování toho kódu může být náhodné a nejde spolehlivě předvídat.
Dalo by sa zabezpečiť, aby to predvídateľné bolo. Stačilo by len spraviť tú „čakaciu fázu“, ktorú si uviedol v príklade s databázovým serverom. No asi to nie je veľmi praktické využitie.
Joker
Profil
_es:
Podobně by se dalo s tím tvrzením polemizovat argumentem, že v době zpracování JS může PHP na serveru běžet a zpracovávat nějaký jiný požadavek.
Ale to není těžiště toho sdělení.

To, co zpracovává PHP, se ještě neodeslalo do prohlížeče. U toho, co je dostupné v JS, zpracování PHP už skončilo. Jestli PHP v té chvíli ještě zpracovává něco jiného, není až tak podstatné.
Stále si myslím, že tak jak to je napsané je pro začátečníky přijatelné zjednodušení, místo abych musel rozebírat, co je synchronní a asynchronní zpracování.

Dalo by sa zabezpečiť, aby to predvídateľné bolo. Stačilo by len spraviť tú ‚čakaciu fázu‘, ktorú si uviedol v príklade s databázovým serverom. No asi to nie je veľmi praktické využitie.
V reálných podmínkách jen těžko.
Bylo by nutné mít pod kontrolou celý server. Jakýkoliv buffer po cestě to rozbije, bylo by potřeba vyřešit cache prohlížeče a podobně. Klient nemusí mít zapnutý JS, nemusí se z nějakého důvodu odeslat ten požadavek a až do případného timeoutu nedostane zbytek stránky a nespustí se skripty navázané na načtení stránky. Navíc pořád PHP nemá dostupné ty části stránky jako JS a naopak.
Alphard
Profil
• Úvahy o důvěryhodných hodnotách bych tam také vůbec nezatahoval. Escapujme všechno, pokud není důvod neescapovat. Tečka.

• To stručně vysvětlené escapování podle mě neznalý čtenář nepochopí, akorát ho to zmate. Z toho generování kódu (echo "alert") také nejsem nadšený, raději bych si připravil jen js proměnné a js logiku psal jako normální js.

• K výše uvedenému, nebylo by lepší dát vysvětlení escapování někam jako samostatnou kapitolku, tady jen odkázat a dál to nepitvat? Nejlépe dát ty 2 dlouhé odstavce úplně pryč a jen stručně zdůvodnit použití json_encode().

• Ukázat vygenerovaný js kód, nejen napsat poznámku, ať si to čtenář zkusí. Zdůraznit, že takto kód vypadá po vygenerování v PHP a nyní ho začne zpracovávat js.

• Na úvod doplnit poznámku, že jde spíše o přehled a pochopení této kapitoly není klíčové pro další díly.

• Slovíčkaření jak píše _es bych tady neřešil.

• Tohle je dle plánu poslední kapitola Základního kurzu, skvělá práce. Máš můj obdiv a velkou pochvalu :-)
_es
Profil
Joker:
Podobně by se dalo s tím tvrzením polemizovat argumentem, že...
Išlo snáď o beh toho PHP skriptu, ktorý práve generuje HTML kód stránky a nie o beh nejakých iných PHP skriptov. Pre začiatočníkov môžu byť tvrdenia samozrejme zjednodušené, no nemuseli by byť z toho dôvodu zároveň aj nepravdivé.

Bylo by nutné mít pod kontrolou celý server.
Prečo by to malo byť nutné? Na tebou uvedený príklad komunikácie s databázovým serverom je treba mať pod kontrolou celý server kde beží PHP? Záleží o aký druh čakania by šlo. Napríklad by PHP skript čakal, či JS na strane klienta potvrdí, že je na stránke zobrazená reklama cez nejaký reklamný systém a ak áno, PHP skript by poslal zvyšok stránky.
Joker
Profil
Alphard:
• Úvahy o důvěryhodných hodnotách bych tam také vůbec nezatahoval. Escapujme všechno, pokud není důvod neescapovat. Tečka.
• To stručně vysvětlené escapování podle mě neznalý čtenář nepochopí, akorát ho to zmate. Z toho generování kódu (echo "alert") také nejsem nadšený, raději bych si připravil jen js proměnné a js logiku psal jako normální js.

Jenže když skript vypisuje skutečně nějaký kód, escapovat se samozřejmě nemá. Což je případ zrovna třeba JSONP: Escapovat se mají jen data, ne volání funkce kolem nich.
Záměr byl v prvním příkladu ukázat generování kódu a potom rozvést to escapování.

• K výše uvedenému, nebylo by lepší dát vysvětlení escapování někam jako samostatnou kapitolku, tady jen odkázat a dál to nepitvat?
Ošetření dat se probírá v kapitole 12.

• Ukázat vygenerovaný js kód, nejen napsat poznámku, ať si to čtenář zkusí.
Asi ano. Já se snažil ty části týkající se JS brát jen stručně, protože to má být učebnice PHP, ale tohle by to asi chtělo.

• Na úvod doplnit poznámku, že jde spíše o přehled a pochopení této kapitoly není klíčové pro další díly.
Zkusím to nějak naformulovat.

• Tohle je dle plánu poslední kapitola Základního kurzu, skvělá práce. Máš můj obdiv a velkou pochvalu :-)
Díky, příští týden se to může oslavit :-)

_es:
Přemýšlel jsem o lepší formulaci těch vět, ale zatím mě nic nenapadlo.

Prečo by to malo byť nutné? Na tebou uvedený príklad komunikácie s databázovým serverom je treba mať pod kontrolou celý server kde beží PHP?
Tohle by byl daleko větší problém, než komunikace s databází.
Server je nutné mít pod kontrolou proto, že při některých nastaveních to nebude fungovat. A je třeba myslet na to, že celý skript včetně timeoutu uvnitř se musí vejít do timeoutu pro skripty.

Celkově to podle mě je spíš kuriozita, nevidím v tom žádné výhody, jen nevýhody (ve výsledku to pro odeslání dat stejně musí odeslat další požadavek na server, takže prakticky jen navíc někde na serveru cyklí skript a čeká na data. Kdybychom první PHP skript ukončili a zbytek práce nechali udělat ten druhý na požadavek z JS, dosáhneme v podstatě téhož a jednodušeji).
_es
Profil
Joker:
Přemýšlel jsem o lepší formulaci těch vět, ale zatím mě nic nenapadlo.
Možno by to bolo dobré rozdeliť na časť „inde“, že PHP beží na serveri a JavaScript v počítači návštevníka - oba s vlastnou pamäťou a teda nemôžu nijako priamo čítať či meniť premenné na tom druhom. A na časť „inokedy“, že v čase behu JS už PHP skript, generujúci stránku, môže byť skončený.

Celkově to podle mě je spíš kuriozita, nevidím v tom žádné výhody, jen nevýhody
Asi by to bolo viac vhodné na iné serverové technológie než PHP, že by bol serverový skript nejako „uspaný“ a zareagoval by na na sieťový dotaz - že by sa to „necyklilo“, ale vyčkávalo nejako efektívnejšie - že by sa zadala reakcia na nejakú udalosť. Či to je možné v PHP neviem - to je skôr orientované na to, aby skript čo najskôr skončil a nie bežal na pozadí. Asi nemá veľký praktický význam to skúšať práve v PHP - asi len keby bol PHP server nejako špeciálne nakonfigurovaný, doplnený či upravený.
Joker
Profil
_es:
že by bol serverový skript nejako ‚uspaný‘ a zareagoval by na na sieťový dotaz
No, a techniky jako AJAX, JSONP apod. existují z velké části právě proto, že tohle není možné :-)
HTTP je bezestavový protokol a nic jako „dodatek k předchozímu požadavku“ nebo „pokračování v komunikaci“ neumí. To naznačuje právě i ten obrázek, komunikace je pořád jen jednosměrná, klient odešle požadavek, server ho zpracuje a odešle odpověď.
_es
Profil
Joker [#18]:
Zjavne si ma nepochopil, išlo by o nový (ďalší) HTTP dotaz, len by naň PHP skript nevyčkával v nekonečnej slučke, ale by reagoval na nové HTTP dotazy - asi nejako „napojený“ na udalosti HTTP servera.
Joker
Profil
_es:
To jsem právě pochopil. Když to bude navštěvovaný web, na server budou HTTP dotazy přicházet každou chvíli a server neví, který z nich je pokračování toho předchozího (aby probudil ten skript).
A v každém případě tam nevidím žádnou výhodu proti tomu, když ten druhý dotaz bude prostě nový dotaz.
Joker
Profil
Doplnil jsem na úvod poznámku podle Alphard [#14] a ještě jednou pozměnil tu část o vkládání skriptu do stránky.
Alphard
Profil
Joker [#21]:
Hezké, takto je to podle mě pro začátečníky přehlednější.
_es
Profil
Joker:
a server neví, který z nich je pokračování toho předchozího (aby probudil ten skript).
No tak bude predsa obsahovať nejakú informáciu, aby to „vedel“, v cookie či inak, napríklad by mohla aj stačiť len kontrola adries GET dotazov. Išlo mi o to, že sa to teoreticky dá, preto je predhadzovanie jednoduchých riešiteľných problémov akosi mimo.

A v každém případě tam nevidím žádnou výhodu proti tomu, když ten druhý dotaz bude prostě nový dotaz.
Napríklad, ak by bola stránka náročná na serverový výkon či pamäť či na databázu, tak by nemusel ten „druhý dotaz“ skoro nič robiť, vyrábať znova to, čo už existuje, „prvý dotaz“ by sa len dokončil. Okrem toho by ten druhý dotaz stačil v smere od prehliadača k serveru - teda by bolo rýchlejšie „dotiahnutie“ zvyšku stránky.
Joker
Profil
_es:
No tak bude predsa obsahovať nejakú informáciu, aby to ‚vedel‘, v cookie či inak
Takže ve finále by skriptu byl předřazený jiný skript, který by analyzoval požadavek a rozhodl, co s ním udělat. Pořád to ale budou dva požadavky a ten předřazený skript by na druhý požadavek měl formulovat druhou odpověď.

Jak jsem psal, podle mě celý ten koncept není v praxi (v PHP) použitelný. Jednak tam je moc proměnných na to, aby to bylo spolehlivé, jednak vzniká problém s vyvážením timeoutu: Krátký timeout nebude fungovat s pomalými připojeními a při dlouhém timeoutu tam zbytečně budou viset procesy.
A mimochodem by to bylo náchylné na DoS útok: Stačilo by v prohlížeči vypnout JavaScript a položit kamínek na F5. Server by nejstále vytvářel nová spojení a držel je až do timeoutu, takže za chvíli narazí na limit.
Což by ostatně mohla způsobit i vysoká zátěž v normálním provozu: Kdyby se server dostal na limit počtu spojení, byl by nucený zahazovat ty „potvrzovací“ požadavky, kvůli tomu by neuzavíral ty původní požadavky a kvůli nim by zase neměl dostatek volných spojení.

Ale už jsme asi opravdu daleko od tématu.
Joker
Profil
Doplnil jsem do článku ještě odkaz na diskusi a zařadil ho do menu.
Takže tímto se dá celý základní kurz považovat za zveřejněný. Sice to trvalo déle než jsem si myslel, ale povedlo se :-)
Chamurappi
Profil
Jen jsem si všiml drobnosti v poslední podkapitolce:
Používá se k tomu JavaScriptový objekt XmlHttpRequest
Je to XMLHttpRequest, tedy velké XML, malé Http. Název toho objektu je typickým projevem nerozhodnosti při psaní velkých písmen :-)

Vaše odpověď

Mohlo by se hodit

Ostrá verze učebnice běží na www.pehapko.cz.

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: