Mul on PHP-s muutuja ja mul on vaja selle väärtust oma JavaScript-koodis. Kuidas saan ma oma muutuja PHP-st JavaScripti?
Minu kood näeb välja selline:
<?php
...
$val = $myService->getValue(); // Makes an API and database call
?>
Mul on JavaScript-kood, mis vajab val
ja näeb välja umbes nii:
<script>
myPlugin.start($val); // I tried this, but it didn't work
<?php myPlugin.start($val); ?> // This didn't work either
myPlugin.start(<?=$val?> // This works sometimes, but sometimes it fails
</script>
Selleks on tegelikult mitmeid lähenemisviise. Mõned nõuavad rohkem üldkulusid kui teised ja mõnda peetakse paremaks kui teisi. Ilma erilise järjekorrata:
Seda meetodit peetakse parimaks, sest serveri- ja kliendipoolsed skriptid on täiesti eraldi.
AJAXi puhul on vaja kahte lehekülge, millest üks on see, kus PHP genereerib väljundi, ja teine on see, kus JavaScript saab selle väljundi:
/* Tehke siin mingi operatsioon, näiteks rääkige andmebaasiga, failisessiooniga.
// You can json_encode() any value in PHP, arrays, strings,
//even objects.
<!-- snip -->
<script>
function reqListener () {
console.log(this.responseText);
}
var oReq = new XMLHttpRequest(); // New request object
oReq.onload = function() {
// This is where you handle what to do with the response.
// The actual data is found on this.responseText
alert(this.responseText); // Will alert: 42
};
oReq.open("get", "get-data.php", true);
// ^ Don't block the rest of the execution.
// Don't wait until the request finishes to
// continue.
oReq.send();
</script>
<!-- snip -->
Ülaltoodud kahe faili kombinatsioon hoiatab 42
, kui faili laadimine on lõppenud.
See meetod on AJAXile vähem eelistatud, kuid sellel on siiski omad eelised. See'on ikkagi suhteliselt eraldatud PHP ja JavaScripti vahel selles mõttes, et JavaScripti sees ei ole otseselt PHP-d.
<input type=hidden>
informatsiooni salvestamiseks, sest inputNode.value
st on lihtsam infot välja saada, kuid seda tehes on teil HTML-is mõttetu element. HTML-is on <meta>
element dokumendi kohta käivate andmete jaoks ja HTML 5 võtab kasutusele data-*
atribuudid andmete jaoks, mida saab konkreetsete elementidega seostada spetsiaalselt JavaScriptiga lugemiseks.Selle puhul on mõte luua mingi element, mida kasutajale ei kuvata, kuid mis on nähtav JavaScriptile.
<!-- snip -->
<div id="dom-target" style="display: none;">
<?php
$output = "42"; // Again, do some operation, get the output.
echo htmlspecialchars($output); /* You have to escape because the result
will not be valid HTML otherwise. */
?>
</div>
<script>
var div = document.getElementById("dom-target");
var myData = div.textContent;
</script>
<!-- snip -->
See on ilmselt kõige lihtsamini arusaadav.
Rakendamine on suhteliselt lihtne:
<!-- snip -->
<script>
var data = <?php echo json_encode("42", JSON_HEX_TAG); ?>; // Don't forget the extra semicolon!
</script>
<!-- snip -->
Palju õnne!
Ma proovin lihtsamat vastust:
Kõigepealt mõistame sündmuste kulgu, kui lehte serveeritakse meie serverist:
Nii et tegelikult on põhiline asi, mida siinkohal meeles pidada, et HTTP on stateless. Kui taotlus on serverist lahkunud, ei saa server seda enam puudutada. Nii et meie võimalused on järgmised:
See's põhiküsimus, mida te peaksite endale esitama, on:
Veebilehed on peamiselt leheküljepõhised ja lehekülje laadimisaeg peab olema võimalikult kiire (näiteks - Wikipedia). Veebirakendused on rohkem AJAX-koormusega ja teevad palju ringkäike, et saada kliendile kiiresti teavet (näiteks - börsi armatuurlaud).
Kliendi poolt rohkemate päringute saatmine pärast esialgse päringu tegemist on hiline, kuna see nõuab rohkem HTTP-päringuid, millel on märkimisväärne üldkulu. Lisaks nõuab see asünkroonsust, kuna AJAX päringu tegemine nõuab käitlejat, kui see on lõppenud.
Ma ei soovitaks teha teist päringut, välja arvatud juhul, kui teie sait on rakendus, et saada seda teavet serverist.
Te soovite kiireid vastamisaegu, millel on tohutu mõju konverteerimis- ja laadimisaegadele. Ajax-päringute tegemine on sellisel juhul aeglane esialgse kasutusaja jaoks ja mittevajalik.
Teil on kaks võimalust probleemi lahendamiseks
Küpsise määramine ei ole tegelikult väga keeruline, te lihtsalt määrate sellele väärtuse:
setcookie("MyCookie", $value); // Sets the cookie to the value, remember, do not
// Set it with HTTP only to true.
Seejärel saate lugeda seda JavaScriptiga, kasutades document.cookie
:
Siin on lühikese käega rullitud parser, aga vastus, millele ma viitasin otse selle kohal, on paremini testitud:
var cookies = document.cookie.split(";").
map(function(el){ return el.split("="); }).
reduce(function(prev,cur){ prev[cur[0]] = cur[1];return prev },{});
cookies["MyCookie"] // Value set with PHP.
Küpsised on hea väheste andmete jaoks. Seda teevad tihtipeale jälgimisteenused.
Kui meil on rohkem andmeid, saame need hoopis JSONiga kodeerida JavaScript-muutuja sees:
<script>
var myServerData = <?=json_encode($value)?>; // Don't forget to sanitize
//server data
</script>
Eeldades, et $value
on PHP poolel json_encode
-võimeline (tavaliselt on see nii). Seda tehnikat kasutab näiteks Stack Overflow oma chatiga (ainult et PHP asemel kasutatakse .NET-i).
Kui sa'kirjutad rakendust - äkki ei ole esialgne laadimisaeg alati nii oluline kui rakenduse jooksev jõudlus ning andmete ja koodi eraldi laadimine hakkab end ära tasuma.
Minu vastus siin selgitab, kuidas andmeid AJAXi abil JavaScriptis laadida:
function callback(data){
// What do I do with the response?
}
var httpRequest = new XMLHttpRequest;
httpRequest.onreadystatechange = function(){
if (httpRequest.readyState === 4) { // Request is done
if (httpRequest.status === 200) { // successfully
callback(httpRequest.responseText); // We're calling our method
}
}
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();
Või jQuery abil:
$.get("/your/url").done(function(data){
// What do I do with the data?
});
Nüüd peab server lihtsalt sisaldama /your/url
marsruuti/faili, mis sisaldab koodi, mis haarab andmed ja teeb nendega midagi, sinu puhul:
<$php
...
$val = myService->getValue(); // Makes an API and database call
echo json_encode($val); // Write it to the output
$>
Nii küsib meie JavaScript-faili andmeid ja näitab neid, mitte ei küsi koodi või kujundust. See on puhtam ja hakkab tasuma, kui rakendus muutub kõrgemaks. See'on ka parem probleemide eraldamine ja see võimaldab testida kliendipoolset koodi ilma serveripoolse tehnoloogiata, mis on veel üks pluss.
Postscript: Peate olema suures teadlikkuses XSS-ründevektoritest, kui süstite midagi PHP-st JavaScriptini. See'on suur raskusi väärtuste korralikult põgeneda ja see'on kontekstitundlik. Kui sa'ei ole kindel, kuidas XSS-iga toime tulla, või ei ole sellest teadlik - palun loe seda OWASPi artiklit, seda ja seda küsimust.
myPlugin.start($val); // Tried this, didn't work
See ei tööta, sest $val
on JavaScripti jaoks määratlemata, st PHP-kood ei andnud $val
jaoks midagi välja. Proovige vaadata lähtekoodi oma brauseris ja siin on see, mida te'näete:
myPlugin.start(); // I tried this, and it didn't work
Ja
<?php myPlugin.start($val); ?> // This didn't work either
See ei tööta, sest PHP üritab käsitleda myPlugin'i kui konstanti ja kui see ebaõnnestub, siis üritab ta käsitleda seda stringina
'myPlugin', mida ta üritab liita PHP-funktsiooni
start()` väljundiga ja kuna see on määratlemata, siis tekib fataalne viga.
Ja
myPlugin.start(<?=$val?> // This works sometimes, but sometimes it fails
Kuigi see tõenäoliselt töötab, kuna PHP-kood toodab kehtivat JavaScript'i oodatud argumentidega, kui see ebaõnnestub, siis on tõenäoline, et myPlugin
ei ole veel valmis. Kontrollige oma täitmise järjekorda.
Samuti peaksite tähele panema, et PHP-koodi väljund on ebaturvaline ja seda tuleks filtreerida json_encode()
abil.
EDIT
Kuna ma ei märganud myPlugin.start(<?=$val?>
:-\ puuduvad sulgudes.
Nagu @Second Rikudo märgib, selleks, et see töötaks õigesti, peaks $val
sisaldama lõppsulge, näiteks: $val="42);"
See tähendab, et PHP toodab nüüd myPlugin.start(42);
ja töötab ootuspäraselt, kui JavaScript-kood seda täidab.