از قسمت های قبلی این دوره یاد گرفته ایم که JSON می تواند به راحتی تبدیل به جاوا اسکریپت شود و از طرفی جاوا اسکریپت نیز می تواند کد های HTML تولید کند بنابراین می توان گفت که JSON به نوعی HTML تولید می کند. به طور مثال ما جدول HTML زیر را با استفاده از اطلاعات دریافتی توسط JSON ساخته ایم:
<!DOCTYPE html> <html> <body> <h2>Make a table based on JSON data.</h2> <p id="demo"></p> <script> var obj, dbParam, xmlhttp, myObj, x, txt = ""; obj = { table: "customers", limit: 20 }; dbParam = JSON.stringify(obj); xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { myObj = JSON.parse(this.responseText); txt += "<table border='1'>" for (x in myObj) { txt += "<tr><td>" + myObj[x].name + "</td></tr>"; } txt += "</table>" document.getElementById("demo").innerHTML = txt; } }; xmlhttp.open("POST", "json_demo_db_post.php", true); xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send("x=" + dbParam); </script> </body> </html>
ما می توانیم این اطلاعات را در یک منوی drop down نیز قرار دهیم و لزومی به استفاده از جدول ها نداریم:
<!DOCTYPE html> <html> <body> <h2>Make a table based on the value of a drop down menu.</h2> <select id="myselect" onchange="change_myselect(this.value)"> <option value="">Choose an option:</option> <option value="customers">Customers</option> <option value="products">Products</option> <option value="suppliers">Suppliers</option> </select> <p id="demo"></p> <script> function change_myselect(sel) { var obj, dbParam, xmlhttp, myObj, x, txt = ""; obj = { table: sel, limit: 20 }; dbParam = JSON.stringify(obj); xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { myObj = JSON.parse(this.responseText); txt += "<table border='1'>" for (x in myObj) { txt += "<tr><td>" + myObj[x].name + "</td></tr>"; } txt += "</table>" document.getElementById("demo").innerHTML = txt; } }; xmlhttp.open("POST", "json_demo_db_post.php", true); xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send("x=" + dbParam); } </script> </body> </html>
حتی می توانیم آن را در قالب یک لیست drop down نیز دربیاوریم:
<!DOCTYPE html> <html> <body> <h2>Make a drop down list based on JSON data.</h2> <p id="demo"></p> <script> var obj, dbParam, xmlhttp, myObj, x, txt = ""; obj = { table: "customers", limit: 20 }; dbParam = JSON.stringify(obj); xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { myObj = JSON.parse(this.responseText); txt += "<select>" for (x in myObj) { txt += "<option>" + myObj[x].name; } txt += "</select>" document.getElementById("demo").innerHTML = txt; } }; xmlhttp.open("POST", "json_demo_db_post.php", true); xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send("x=" + dbParam); </script> </body> </html>
JSONP (مخفف JSON with Padding - به معنی JSON به همراه padding) متدی برای ارسال داده های JSON است که مشکلات بین-دامنه ای را حل می کند. JSONP از شیء XMLHttpRequest
استفاده نمی کند بلکه به جای آن از <script>
استفاده می کند.
همانطور که می دانید درخواست فایل از یک دامنه ی دیگر مشکلاتی را ایجاد می کند چرا که خلاف خط مشیء و قوانین مربوطه است (به دلیل مسائل امنیتی) اما درخواست یک script از یک دامنه ی دیگر چنین محدودیت هایی را ندارد بنابراین می توانیم به جای آنکه از شیء XMLHttpRequest
استفاده کنیم، فایل خود را از طریق تگ script انجام دهیم:
<script src="demo_jsonp.php">
به طور مثال در کد زیر، سرور نتیجه را در فراخوانی تابع جمع می کند:
<?php $myJSON = '{"name":"John", "age":30, "city":"New York"}'; echo "myFunc(".$myJSON.");"; ?>
خروجی این کد عبارت زیر است:
myFunc({"name":"John", "age":30, "city":"New York"});
در واقع نتیجه تابعی به نام myFunc را صدا می زند و JSON را به عنوان پارامتر به آن می دهد. البته باید مطمئن باشید که چنین تابعی برای سمت کلاینت وجود داشته باشد. در مثال ما این تابع در سمت کلاینت وجود داشت و آماده ی دریافت و مدیریت JSON بود:
<!DOCTYPE html> <html> <body> <h2>Request JSON using the script tag</h2> <p>The PHP file returns a call to a function that will handle the JSON data.</p> <p id="demo"></p> <script> function myFunc(myObj) { document.getElementById("demo").innerHTML = myObj.name; } </script> <script src="demo_jsonp.php"></script> </body> </html>
همانطور که حدس میزدید در خروجی عبارت "John" برای ما به نمایش در می آید.
مثال بالا تابع myFunc را زمانی اجرا می کند که صفحه در حال بارگذاری است و به مکان قرار دادن تگ script در صفحه تان بستگی دارد. این شیوه اصلا شیوه ی خوبی نیست و بهتر ما آن را پویا تر کنیم؛ یعنی تگ script زمانی به وجود بیاید که به آن نیاز داشته باشیم:
<!DOCTYPE html> <html> <body> <h2>Click the Button.</h2> <p>A script tag with a src attribute is created and placed in the document.</p> <p>The PHP file returns a call to a function with the JSON object as a parameter.</p> <button onclick="clickButton()">Click me!</button> <p id="demo"></p> <script> function clickButton() { var s = document.createElement("script"); s.src = "demo_jsonp.php"; document.body.appendChild(s); } function myFunc(myObj) { document.getElementById("demo").innerHTML = myObj.name; } </script> </body> </html>
این تابع زمانی که کسی روی دکمه کلیک کند یک تگ Script ساخته و آن را در سند ما قرار می دهد. اما این مثال هنوز هم به طور کامل پویا نیست. برای پویایی بیشتر می توانیم JSON را به فایل PHP بفرستیم تا فایل PHP بر اساس اطلاعاتی که دریافت می کند یک شیء JSON را برگرداند:
<?php header("Content-Type: application/json; charset=UTF-8"); $obj = json_decode($_GET["x"], false); $conn = new mysqli("myServer", "myUser", "myPassword", "Northwind"); $result = $conn->query("SELECT name FROM ".$obj->$table." LIMIT ".$obj->$limit); $outp = array(); $outp = $result->fetch_all(MYSQLI_ASSOC); echo "myFunc(".json_encode($outp).")"; ?>
در این مثال ابتدا درخواست را با استفاده از تابع ()json_decode
به یک شیء تبدیل می کنیم:
$obj = json_decode($_GET["x"], false);
سپس به پایگاه داده متصل می شویم:
$conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");
و اطلاعات درخواستی را درون یک آرایه می ریزیم و آن آرایه را به یک شیء اضافه می کنیم:
$result = $conn->query("SELECT name FROM ".$obj->$table." LIMIT ".$obj->$limit); $outp = array(); $outp = $result->fetch_all(MYSQLI_ASSOC);
حالا آرایه را با استفاده از ()json_encode
به JSON تبدیل میکنیم و myFunc را به شیء برگردانده شده اضافه می کنیم:
echo "myFunc(".json_encode($outp).")";
سپس می توانیم myFunc را از فایل PHP صدا بزنیم:
<!DOCTYPE html> <html> <body> <h2>Click the Button.</h2> <p>A script tag with a src attribute is created and placed in the document.</p> <p>The PHP file returns a call to a function with the JSON object as a parameter.</p> <button onclick="clickButton()">Click me!</button> <p id="demo"></p> <p>Try changing the table property from "customers" to "products".</p> <script> function clickButton() { var obj, s obj = { table: "customers", limit: 10 }; s = document.createElement("script"); s.src = "jsonp_demo_db.php?x=" + JSON.stringify(obj); document.body.appendChild(s); } function myFunc(myObj) { var x, txt = ""; for (x in myObj) { txt += myObj[x].name + "<br>"; } document.getElementById("demo").innerHTML = txt; } </script> </body> </html>
سوال: زمانی که به فایل سمت سرور دسترسی نداریم چطور به سرور بگوییم که تابع صحیح را صدا بزند؟
پاسخ: برخی اوقات فایل سمت سرور یک تابع از نوع callback را به عنوان یک پارامتر به شما می دهد. ما می توانیم از همین پارامتر استفاده کنیم:
<!DOCTYPE html> <html> <body> <h2>Request With a Callback Function</h2> <p>The PHP file returns a call to the function you send as a callback.</p> <button onclick="clickButton()">Click me!</button> <p id="demo"></p> <script> function clickButton() { var s = document.createElement("script"); s.src = "demo_jsonp2.php?callback=myDisplayFunction"; document.body.appendChild(s); } function myDisplayFunction(myObj) { document.getElementById("demo").innerHTML = myObj.name; } </script> </body> </html>
قسمت مهم این کد اینجاست:
s.src = "jsonp_demo_db.php?callback=myDisplayFunction";
امیدوارم این قسمت برای شما مفید بوده باشد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.