Blog Posting with XML-RPC
สำหรับคนที่ทำ SEO หลายคนคงเคยทำ network ส่วนตัวกันมาบ้างพอสมควร ไม่ว่าจะใช้ networks เหล่านั้นเป็นสะเหมือน web farm ที่จะสร้างลิงค์มายังเวปเป้าหมายหรือแม้กระทั่งจัดการเวปเป้าหมายโดยตรง แต่การจัดการ network/blogs เหล่านั้นมีความยุ่งยากและใช้เวลามากพอสมควร หลายคนจึงเลือกที่จะเสียเงินซื้อ tools ต่างๆมาใช้ เช่นพวก BMG, scrapbox ต่างๆ ซึ่งผมก็ไม่รู้ว่ามันมีข้อดีข้อเสียอย่างไรเพราะไม่เคยใช้ tool ที่ผมใช้ในการจัดการ network/blogs เหล่านั้น เขียนขึ้นมาเอง โดยเป็นการทำงานผ่าน protocol XML-RPC ซึ่งถ้า blogs เหล่านั้น enable XML-RPC ก็จะสามารถจัดการ blogs ได้ผ่าน protocol XML-RPC
วันนี้ผมเลยอยากเอาโค้ดมาแปะไว้กันลืมและเผื่อผู้ที่สนใจบ้างสักหน่อย การทำงานของโค้ดก็ตรงไปตรงมา ผมจะไม่ขออธิบายอะไรมากนัก ก่อนอื่นต้องโหลด include file ตัวนี้ก่อนโค้ดถึงจะทำงานได้นะครับ IXR_Library.inc
require_once("IXR_Library.inc");
$id = $_POST["id"];
$title = $_POST["title"];
$body = $_POST["body"];
$category = $_POST["$category"];
$tags = $_POST["tags"];
$blogURL = $_POST['BlogURL'];
// set it to false in Production Environment
$client->debug = false;
// encode needed
$title = htmlentities($title , ENT_NOQUOTES, "UTF-8");
$tags = htmlentities($tags ,ENT_NOQUOTES, "UTF-8");
$content = array('title'=>$title,
'description'=>$body,
'mt_allow_comments'=>0, // 1 to allow comments
'mt_allow_pings'=>0, // 1 to allow trackbacks
'post_type'=>'post',
'mt_keywords'=>$tags,
'categories'=>array($category),
'custom_fields' => array($customfields));
// create the client object
$client = new IXR_Client($blogURL . "xmlrpc.php");
$username = $_POST['Username'];
$password = $_POST['Passwd'];
// last parameter is 'true' which means post immideately, to save as draft set it as 'false'
$params = array(0,$username,$password,$content,true);
// run a query for PHP
if (!$client->query('metaWeblog.newPost', $params)) {
die('An error occurred - '.$client->getErrorCode().": ".$client->getErrorMessage());
} else {
// post blog success
// do what ever you want here
}
Synchronous AJAX calls
วันก่อนผมเจอปัญหาอย่างหนึ่ง ในการสร้าง request ด้วย AJAX เป็นที่รู้กันดีว่า request ที่ออกไปจะมีการทำงานแบบ Asynchronous และด้วยความสามารถของ HTML+JavaScript ทำให้เราสามารถตอบสนอง response ที่กลับมาได้โดยสะดวกมากขึ้นโดยที่ไม่ต้องรอ response ที่ยังไม่กลับมา

ปัญหาที่ผมเจอคือ ในการยิง request ครั้งละมากๆ เช่น 500 request และในแต่ละ request มี overhead และ process/server time ที่สูงมากๆ การทำงานของ script นั้นมันจะผิดพลาด ผลลัพธ์ที่เจอคือ มีแค่ request สุดท้ายเท่านั้นที่ reponse กลับมา ซึ่งอาจจะเป็นปัญหาจากตัว host ที่ผมเช่าอยู่ก็ได้ ซึ่งเป็นแบบ share host นั้นไม่ยอมให้มี request ไปที่ไซต์อื่นๆ, ในกรณีของผมเป็นลักษณะ Cross-site แต่เป็น การทำ Cross-site ที่ฝั่ง server, browser รุ่นใหม่จะมีการป้องกันหรือแจ้งเตือน ในกรณีที่มีการทำ Cross-site ที่ฝั่ง client เหตุผลเรื่อง security
กลับมาที่ปัญหาของ host ของผม เท่าที่วิเคราะห์เองน่าจะเกิดจาก
1. server ไม่ยอมให้มี request ไปที่ site ที่มีลักษณะเป็น Cross-site มากกว่าหนึ่ง site ณ.เวลาเดียวกัน
2. server ไม่ยอมให้มีการทำ Cross-site
และเนื่องจาก application ที่ผมเขียนขึ้นมา มีการจัดการ response แบบ Asynchronous คือจัดการ response แบบไม่เรียงลำดับ อธิบายเพิ่มเติมแล้วกันว่า application ของผมมีการยิง request ไปในหลายๆ site เพื่อดึงข้อมูลอะไรบางอย่างจาก site เหล่านั้น ซึ่งข้อมูลที่ได้กลับมาก็จะถูกจัดการแบบ Asynchronous และแสดงผลที่หน้าจอ แต่ผมไม่สามารถใช้การทำงานแบบ Asynchronous Ajax calls ได้
สิ่งที่ผมต้องทำคือ สร้าง request แบบ Synchronous Ajax calls โดยยิง request ไปครั้งละหนึ่ง site และจัดการ response data ตรงนั้นให้เสร็จทีละอันไป code จากการค้นคว้าใน internet และจับ code เหล่านั้นมายำๆรวมกัน มั่วๆบ้าง ลองผิดลองถูก สุดท้ายก็ได้ code นี้ออกมาครับ
var isProgress = false;
// Synchronous Ajax calls handler function
function syncAjaxHandler() {
isProgress = false;
makeAjaxCall();
}
function makeAjaxCall(){
if (!isProgress) {
isProgress=true;
// send a request
makeRequest();
// call itself
makeAjaxCall();
} else {
// if current request is work in progess, wait 500ms.
setTimeout("makeAjaxCall()", 500);
}
}
function makeRequest() {
var xmlHttp;
if (window.XMLHttpRequest) {
// code for IE7+, FF, Chrome, Opera, Safari
xmlHttp=new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.onreadystatechange=function() {
if (xmlHttp.readyState==4 && xmlHttp.status==200) {
// do someting with response text
var response = xmlHttp.responseText;
// job done
isProgress=false;
}
}
xmlHttp.open("GET", "somewhere");
xmlHttp.send();
}
บรรดทัดที่สำคัญคร่าวๆมีดังนี้
isProgress = false;
ในบรรทัดที่ 1 isProgress ที่จะบอกว่าในขณะนั้นมี work ของ request ปัจจุบัน in progress อยู่หรือป่าว ถ้ายังมีอยู่ก็จะยังไม่มีการยิง request ถัดไป จนกว่า request นั้นจะ response กลับมา
setTimeout("syncAjaxCall()", 500);
ในบรรทัดที่ 20 ถ้ายังมี progress อยู่ก็จะยังไม่สร้าง request ใหม่ขึ้นมา ให้รอไปอีก 500ms
isProgress=false;
ในบรรทัดที่ 41 เมื่อ job done เซ็ต isProgress เป็น false เพื่อบอกว่าสามารถสร้าง request ใหม่ได้แล้ว
นั้นคือโค้ดที่ทำ Ajax calls ให้มีการทำงานแบบ Synchronous ทั้งๆที่ข้อด๊และคุณสมบัติของ Ajax คือ Asynchronous งงมั้ย?? และบล็อกนี้เป็นบล็อกที่ผมเขียนขึ้นเอง อาจจะผิดจะถูกบ้างในคอนเซ็ปหรือคำศัพท์ต่างๆ เพราะตอนที่เขียนมันขึ้นมาผมก็มั่วเอา เลยอยากเขียนเก็บไว้กันลืม และเผื่อจะเป็นประโยชน์บ้างไม่มากก็น้อยกับใครสักคน
ภาพจาก adaptivepath.com