วิธีทำ Ajax Cross Domain แบบสมบูรณ์ด้วย CodeIgniter และ jQuery

เอาละครับ วันนี้ผมได้เจอปัญหา Ajax Cross Domain อย่างจริงๆจังๆ แล้วตกผลึกความรู้ได้มาพอสมควรครับ ทุกคนผมติต่างว่ารู้จัก Web Service นะครับโดยวันนี้เราจะมาทำแบบ REST กันครับ โดยผมมาพร้อมกับปัญหาที่ผมเจอบ่อยๆมีดังนี้ครับ

  • สามารถเรียก Web Service ได้จาก Domain เดียวกัน
  • สามารถเรียก Web Service จาก Host ได้จาก localhost
  • แต่ไม่สามารถเรียกจาก host หนึ่งไปยังอีก host หนึ่งได้

หลังจากที่ผมได้ลองทำ Web Service มาหลายแบบ แบบที่ผมชอบที่สุดก็คงหนีไม่พ้นแบบ JSON แน่นอนครับ เพราะใน php มันมี function ที่ชื่อว่า json_encode ซึ่งเปลี่ยน array ของ php ไปเป็น json ให้เราได้ทันที แต่วันนี้ผมจะเอาตัวอย่างที่ผมทำผิดแล้ว วันนี้ได้เรียนรู้มาบอกต่อกันครับ ซึ่งใน php ตัวที่ผมทำ web service นั้นชอบทำแบบนี้ครับ

echo json_encode($array);

ซึ่งวิธีนี้จริงๆแล้วน่าจะใช้ได้ดีกับหมดทุกระบบแล้วนะครับ เพราะปกติถ้าใน php เรามี function นี้ครับ file_get_content ซึ่งอำนวยความสะดวกเรื่องนี้ให้เรา เสร็จแล้วเราก็ json_decode จบได้ข้อมูลมาใช้ละง่ายโคตรๆ แต่กระนั้นครับ แล้วถ้าเราจะใช้ Javascript ดึง Web Service ของเราละครับ ยิ่งถ้าใช้ jQuery ก็คงยิ่งหมูเลย

$.getJSON(url,callback);

แค่นี้ก็น่าจะเพียงพอ แต่ผลที่ได้คือ “ถ้าไม่อยู่ใน domain เดียวกัน หรือไม่มีการเปิดให้สิทธิทำ cross-domain ก็จะใช้ไม่ได้ครับ” ในที่นี้ผมหมายถึง เวลา internet explorer จะขึ้น privacy ซึ่งถ้าเราตกลง มันก็ยอมให้เราทำ cross-domain ได้ซึ่ง การใช้ json_encode ถึงเพียงพอครับ แต่พอเอาไปขึ้น host จริงๆคนอื่นที่เขาใช้ javascript ดึงก็ใช้ไม่ได้อยู่ดีแล้วเราจะแก้ปัญหาอย่างไรละ ? ผมเลยค้นหาวิธีต่างๆซึ่ง JSONP เนี้ยเป็นคำตอบ แล้วทำยังไงละ ? วันนี้ผมเอาวิธีทำมาให้เลยละกัน โดย ต้องขอบคุณ Tee++ จาก jQueryTips ซึ่งเป็นคนนำทางผมครับ ผมแนะนำให้อ่านของคุณ Tee++ ก่อนนะครับเอาละประเด็นคืออยู่ที่บรรทัดนี้ครับ

echo $_GET[‘jsoncallback’].‘(’.$json->encode($arr).‘)’; // ของคุณ Tee++ ผมข้อแก้เป็นด่านล่าง เพื่อลักษณะใกล้เคียง
echo $_GET[‘jsoncallback’].‘(’.json_encode($arr).‘)’;

ซึ่งสังเกตว่าจะใช้ . นะครับ ไม่ใช่ = แล้วจะตามวงเล็บเปิดแล้วลงท้ายด้วยวงเล็บปิด ซึ่งเป็นตามหลัก JSONP ส่วนสาเหตุที่ทำไมต้องทำเช่นนี้ ผมยังไม่แน่ใจนัก แต่อธิบายคร่าวๆได้ว่า การใช้ Ajax Cross Domain ตรงๆนั้นมันมีึความเสี่ยงสูง ดังนั้นเลยเกิด JSONP (JSON with Padding) เพื่อมาช่วย แล้วการที่เรามีการใส่ตัวแปลสักตัว ในตัวอย่างคือ jsoncallback แล้วมีการใส่วงเล็บเปิดปิดไปนั้น เืพื่อให้ทางฝั่ง Client สามารถเล่นกับข้อมูลได้สะดวก โดยถ้าเป็น jQuery ก็จะมีการใส่่  jsonp1236274532659 (แล้วแต่มันจะ genให้)แบบนี้เป็นต้น ซึ่งผลลัพธ์ตอนจบมันจะกลายเป็นประมาณนี้

jsonp1236274532659({"name":"dominixz","url":"http:\/\/dominixz.com"})

จะสังเกตว่าพอสามารถใส่อะไรลงไปข้างหน้าได้ มันจะกลายเป็น function !!! ซึ่งทำให้ทางฝั่ง client เล่นอะไรกับข้อมูลนี้ก็ได้ โดยถ้าให้ผมเดาเป็นผมกรณีนี้ใน function นั้นก็อาจมีการ set ค่าตัวแปรค่างๆหรือแม้กระทั่ง eval ข้อมูลเลยก็เป็นได้ แล้วแต่เราจะเขียน โดยถ้าใช้พวก Framework นั้นมีการจัดการกับ JSONP เกือบทุกตัวแล้วละไม่ว่าจะเป็น MooTools , jQuery , Dojo ฯลฯ อธิบายพอเห็นภาพละ แล้ววิธีเรียกใน jQuery ละทำยังไงก็ง่ายๆเลยครับ

$.getJSON(url+”?jsoncallback=?”,callback);

โดยผมมีตัวแบบจริงสักอันละกันครับ โดยถ้าผมมี Web Services ของ CodeIgniter ดังนี้ครับ http://localhost/codezend/index.php/webservices/test ดังนั้นโค้ดนี้ผมจะได้ url เป็นดังนี้ครับ

$.getJSON(“http://localhost/codezend/index.php/webservices/test?jsoncallback=?”,callback);

ซึ่งใน web service ของผมก็ต้องมีการ set ค่า jsoncallback เหมือนกันไม่งั้นก็ใช้ไม่ได้ โดยถ้าไม่ได้ใช้ CodeIgniter แค่นี้ก็คงจบบทความแล้วแต่ CodeIgniter ถ้าทำแค่นี้ไม่ได้แน่ครับ เพราะเจ้า CodeIgniter ดันไม่ยอมให้ใส่ ?jsoncallback=? อย่างงี้ตอนเริ่มต้นได้นี้สิ โดยถ้าต้องการใช้เราจะต้องไป set ใน config.php ให้ enable_query_strings เป็น TRUE ซะก่อนนะครับ

$config['enable_query_strings'] = TRUE;

เป็นอันจบครับ ไว้ผมมีประสบการณ์อะไรเพิ่มเติมจะนำมาเล่าต่อครับผม วันนี้ไปนอนแล้วครับสวัสดีครับ

ประกาศส่งครามกับ IE6

เบื่อไหม ? ที่ทำเว็บแล้วใน Browser ทุกตัวก็ดูดี ยกเว้น IE6 ทุกวันนี้ใครยังทนทุกที่จะต้องทำงานเกี่ยวกับเว็บให้ลูกค้า ก็ยังเจอมันหลอกหลอน อยู่เป็นแน่แท้ ผมไม่มั่นใจว่าคนส่วนใหญ่ทำไมยังใช้ IE6 กัน แต่ที่แน่ๆคือมีคนใช้อยู่ต้องยอมรับความจริง แต่ที่มาประกาศวันนี้คือเชิญชวนให้ทุกท่านที่ยังใช้ IE6 อยู่เปลี่ยนกันเถอะครับ เพราะคนทำเว็บลำบากที่จะต้องทำให้ IE6 แสดงผลเหมือน Browser ตัวอื่น ข้อเสียที่เห็นได้บ่อยๆใน IE6

  • PNG แบบโปรงใสใช้ไม่ได้ใน IE6 ต้องใช้ Javascript แก้
  • Layout ที่เพี้ยนเวลาใช้ padding หรือ margin

ทางแก้ปัญหาก็คือเชิญชวนให้ทุกๆคนมาใช้ IE7 , Firefox , Safari , Chrome หรือแม้แต่ Opera กันดีกว่าครับคนทำเว็บจะได้ไม่ต้องมาแก้ปัญหาจุกจิก แล้วเอาเวลาไปพัฒนางานให้ดีขึ้นแทนกันครับ เพราะถ้านักพัฒนาต้องแก้ปัญหพวกนี้แล้วอย่างน้อยต้องเสียเวลาไปทำเรื่องพวกนี้ครับ

  • PNG โปรงใส
  • CSS reset
  • IE6 Hack
  • Javascript Framework problem (ถ้าใช้ jQuery บาง effect ก็ไม่ติด)

อย่างน้อยกว่าจะแก้สิ่งเหล่านี้อาจจะเสียเวลาหลายวันหรือไม่ก็หลายอาทิตย์เลยก็ได้ครับ สำหรับงานขนาดใหญ่ หรือไม่ได้วางแผนไว้ตั้งแต่ต้น ฝากเนื้อหานี้ให้ Blogger ช่วยกันโพส รณรงค์เรื่องนี้กัน และเิชิญชวนให้ผู้อ่านทุกท่านที่ยังใช้ IE6 upgrade เป็น IE7 เถอะครับหรือไม่ก็เปลี่ยนไปใช้ Browser ตัวอื่นกันครับ

สำหรับชาว Blogger ทุกท่านช่วยกัน Tag อันนี้กันครับ : เลิกใช้ IE6 , abandon-ie6

« Previous PageNext Page »