ผมเคยเขียนโปรแกรมที่เก็บข้อมูลมาหลายครั้ง ทุกครั้งที่ต้องเก็บข้อมูลในฐานข้อมูล ผมจะดูว่า จะเลือกว่าจะเขียนด้วยภาษาอะไร และเก็บฐานข้อมูลด้วยโปรแกรมจัดการฐานข้อมูลตัวไหน เช่นล่าสุดผมเขียนโปรแกรมด้วยวิชวลเบสิก และเลือกใช้ฐานข้อมูลของ Microsoft SQL Server หรือ ถ้าสมัยก่อนก็เขียนโปรแกรมด้วยฟอกซ์โปร ซึ่งต้องใช้ฐานข้อมูลของฟอกซ์โปร เมื่อผมลองเขียนโปรแกรมภาษา PHP ซึ่งอนุญาตให้เลือกโปรแกรมจัดการฐานข้อมูลได้หลายแบบ แรกๆ ผมก็เลือกใช้ MySql ซึ่งเป็นโปรแกรมจัดการฐานข้อมูลที่มีให้เกือบทุก Server และ โปรแกรมเมอร์ทุกคนที่เขียน PHP มักจะเลือกเป็นอันดับแรกๆ แล้ววันหนึ่งก็เกิดปัญหาขึ้นมาจนได้ เมื่อ Server ที่ผมเลือกฝากข้อมูล ไม่มีบริการ MySql หรือ มี MySql แต่ลูกค้าเลือก Server ในเงื่อนไขราคาถูก ปัญหาใหญ่จึงเกิดขึ้นแก่ผม ผมจึงตัดสินใจเขียนโปรแกรมจัดการฐานข้อมูลขึ้นมาเอง อันดับแรกเลย ผมต้องตัดสินใจให้ได้ก่อนว่าจะเก็บข้อมูลในรูปแบบไหน จะเรียกใช้ด้วยคำสั่งอะไร หลังจากคิดดูหลายตลบ จึงตัดสินใจว่า ทำไมไม่เขียนให้เรียกใช้ด้วยคำสั่ง SQL ซะเลย ผมจะได้ไม่ต้องคิดออกแบบคำสั่งในการเรียกใช้ให้วุ่นวาย เนื่องจากมีรูปแบบคำสั่งเป็นมาตรฐานอยู่แล้ว และผมก็ไม่ต้องอธิบายวิธีการใช้ให้มากความ เพราะคนที่เขียนโปรแกรม PHP น่าจะรู้จักคำสั่ง SQL พื้นฐานอยู่แล้ว หรือไม่ก็สามารถศึกษาคำสั่ง SQL ได้จากแหล่งอื่นๆ ถ้าอย่างนั้นก็เหลืออีกอย่างคือ จะเก็บข้อมูลในลักษณะไหนดี เก็บแบบ Text สิ เริ่มเขียนครั้งแรกน่าจะใช้แบบนี้ เพราะเวลาดูจะง่ายดี
หลังจากตัดสินใจได้ ผมก็เริ่มเขียนเลย
อันดับแรก ผมเลือกเขียนในลักษณะของ Object เนื่องจาก Object มีคุณสมบัติในการเก็บรักษาข้อมูลที่เป็นส่วนตัว ซึ่งทำให้สามารถเปิดฐานข้อมูลได้ไม่จำกัด เพราะเราสามารถสร้างวัตถุขึ้นมาใหม่ได้ตลอดเวลา และวัตถุแต่ละชิ้นจะมีคุณสมบัติต่างๆ เป็นของตนเอง
วิธีสร้าง class
class Db {
var $sqlCmd="";
function Db($cmd="" , $para1="" , $para2=””) {
if (isSqlCommand($cmd,$sqlCmd)) {
$this->sqlCmd=$cmd;
if (method_exists($this,$sqlCmd)) $this->$sqlCmd($cmd,$para1,$para2);
}
}
}//--- End Of Class Db ผมกำหนดวิธีการสร้าง class ให้ Class Constructor รับ Parameter มา 3 ค่า โดย $cmd เป็นคำสั่ง SQL ที่ต้องการให้จัดการกับตารางข้อมูล ซึ่งทำให้สามารถสร้าง Object ใหม่พร้อมกับทำงานคำสั่ง SQL ได้ทันที เช่น $guestbookDb = new Db(“SELECT * FROM /guestbook/guestbook.db”) จะเป็นการเปิดตารางข้อมูลชื่อ /guestbook/guestbook.db และดึงข้อมูลทุกรายการและทุกฟิลด์จากตาราง น่าจะสะดวกดี ตัวแปรอีกสองตัวมีไว้สำหรับส่งข้อมูลเพิ่มเติมให้กับคำสั่ง อันดับที่ 2 ต้องมีคำสั่งสร้างตารางข้อมูลก่อน ซึ่งก็คือคำสั่ง CREATE TABLE
รูปแบบมาตรฐานคือ
CREATE TABLE tableName ( field type [ (size [,decimal] ) ] [index] [ , field type [ (size [,decimal] ) ] [index] [,...] ] )
เอาเป็นว่ารุ่นที่ 1 ยังไม่ต้องมี Index ก่อนก็แล้วกัน แค่ให้สามารถสร้างหัวตารางได้ก็พอ คำสั่งที่ได้จึงมีแค่
CREATE TABLE tableName ( field type [ (size [,decimal] ) ] [ , field type [ (size [,decimal] ) ] [,...] ] )
Method ในการสร้างตารางเป็นอย่างนี้
//--------------------------------------------------------------------------------------------------------------------
function Create($sqlCmd="",$propStr="") {
/*
Method for create new table
CREATE คำสั่งสำหรับสร้างฐานข้อมูลใหม่
version 1.00
สร้างเมื่อวันที่ 1 เมษายน 2545
Sql Command
CREATE TABLE tableName ( field type [ (size [,decimal] ) ] [index] [ , field type [ (size [,decimal] ) ] [index] [,...] ] )
field คือชื่อฟิลด์
type คือชนิดของข้อมูลของฟิลด์ มี ชนิดคือ
- auto [ (size) ] เป็นตัวเลขที่เพิ่มขึ้นอัตโนมัติ ครั้งละ 1 ถ้าระบุ size จะเติม 0 ข้างหน้า(ยังใช้งานไม่ได้)
- char [ (size) ] เป็นตัวอักษรที่มีขนาดจำนวน size ตัวอักษร ถ้าไม่ระบุ size จะไม่จำกัดจำนวน
- date เป็นชนิดวันที่ รูปแบบในการเก็บข้อมูลคือ ปปปปดดวว
- int [ (size) ] เป็นตัวเลขจำนวนเต็มที่มีขนาด size ถ้าไม่ระบุ size จะเป็นจำนวนเต็มไม่จำกัดหลัก
- double [ (size [ ,decimal) ] ] เป็นตัวเลขทศนิยมที่มีขนาด size และจำนวนทศนิยม decimal หลัก
ตัวอย่าง CREATE TABKE guestbook.db ( id auto(6) , postDate date , postTime char(8) , name char , message char )
รูปแบบ db header คือ field1 type=type of field;size=size of field,decimal=number of decimal;
property
debug = yes/no yes=พิมพ์ค่าแสดงผลลัพท์การทำงาน
*/
$fieldTypeList=array("auto","date","char","int","double");
$propList=db_propertyExplode($propStr,"overwrite=no");
if ($propList["debug"]==="yes") {
echo "<div style=\"border:2px white ridge;padding:5px;width:100%;text-align:center;\"/>";
echo "<div style=\"border:2px white groove;background-color:#FF8040;padding:2px;font-weight:bold;font-size:12pt;color:#FFF1EA\"/>Debug of CREATE SQL command</div/>";
}
$this-/>sqlCmd=trim($sqlCmd);
$sqlClause=explodeSqlCmd($this-/>sqlCmd);
if ($propList["debug"]==="yes") db_arrayPrint($sqlClause,"header=sql command<br/>$this-/>sqlCmd");
if (!isSet($sqlClause["create"])) {
$this-/>error(1010,"<b/>$this-/>sqlCmd</b/> is not a create sql command");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
if (!isSet($sqlClause["table"])) {
$this-/>error(1011,"Create table not specify");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
if (!ereg("^[a-zA-Z0-9./:]*[ ]",$sqlClause["table"]." ",$eregResult)) {
$this-/>error(1012,"Table name is not a valid name");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
$tableName=trim($eregResult[0]);
$sqlClause["field"]=trim(subStr($sqlClause["table"],strLen($tableName)));
$sqlClause["table"]=$tableName;
$this-/>dbName($sqlClause["table"]);
if ($this-/>haveFile($this-/>dbFullName())) {
$this-/>error(1013,"Table {$sqlClause["table"]} was exists");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
$fieldStr=$sqlClause["field"];
$field=array();
if ( subStr($fieldStr,0,1) != "(" or subStr($fieldStr,-1) != ")" ) {
$this-/>error(1013,"Field specification incorrect. Must have ( at begin and ) at the end.");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
$fieldStr=subStr($fieldStr,1);
$fieldStr=trim(subStr($fieldStr,0,-1));
if (empty($fieldStr)) {
$this-/>error(1014,"Field specification empty");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
while (!empty($fieldStr)) {
$char=subStr($fieldStr,0,1);
$fieldStr=subStr($fieldStr,1);
if ($char==="(") $openChar=true;
elseif ($char===")") $openChar=false;
if ( $char==="," and !$openChar ) {
if (!empty($fieldSet)) $field[]=$fieldSet;
$fieldSet="";
} else $fieldSet.=$char;
}
if (!empty($fieldSet)) $field[]=$fieldSet;
if ($propList["debug"]==="yes") db_arrayPrint($field,"name=field;header=Field Listing<br/>field : {$sqlClause["field"]};");
$dbStructure="";
foreach ($field as $fieldSpec) {
$fieldSpec=trim($fieldSpec);
if (!ereg("^[a-zA-Z0-9]*[ ]",$fieldSpec,$eregResult)) {
$this-/>error(1014,"Field name <b/>$fieldSpec</b/> not correct");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
$fieldName=trim($eregResult[0]);
$fieldSpec=trim(subStr($fieldSpec,strLen($fieldName)));
list($fieldType,$fieldTypeExtension)=explode("(",$fieldSpec);
$fieldType=trim($fieldType);
if (!in_array($fieldType,$fieldTypeList)) {
$this-/>error(1015,"Field type of <b/>$fieldName $fieldSpec</b/> incorrect");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
if (subStr($fieldTypeExtension,-1)===")") $fieldTypeExtension=subStr($fieldTypeExtension,0,-1);
list($fieldSize,$fieldDecimal)=explode(",",$fieldTypeExtension);
$fieldSize=trim($fieldSize);
if (!ereg("^[0-9]*$",$fieldSize,$r)) {
$this-/>error(1016,"Field size of <b/>$fieldName $fieldSpec</b/> not integer");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
if (!ereg("^[0-9]*$",$fieldDecimal,$r)) {
if ($propList["debug"]==="yes") echo "</div/>";
$this-/>error(1017,"Field decimal of <b/>$fieldName $fieldSpec</b/> not integer");
return;
}
if ( in_array($fieldType,array("auto","char","int")) and !empty($fieldDecimal) ) {
$this-/>error(1018,"No field decimal on type <b/>$fieldType</b/> field <b/>$fieldName $fieldSpec</b/>");
if ($propList["debug"]==="yes") echo "</div/>";
return;
}
$dbStructure .= $fieldName." ";
$dbStructure .= "type=$fieldType;";
$dbStructure .= (empty($fieldSize) ? "" : "size=$fieldSize;");
$dbStructure .= (empty($fieldDecimal) ? "" : "decimal=$fieldDecimal;");
if (subStr($dbStructure,-1)===";") $dbStructure=subStr($dbStructure,0,-1);
$dbStructure .= _dbSeparator;
}
$dbStructure=subStr($dbStructure,0,-1);
if ($propList["debug"]==="yes") echo "<div style=\"border:2px white groove;padding:2px;text-align:left;\"/><b/>db Structure Generate is</b/><br/><font color=red/>$dbStructure</font/></div/>";
$fp=fopen($this-/>dbFullName(),"w");
if ($fp) {
fputs($fp,$dbStructure._dbNewLine);
fclose($fp);
}
if ($propList["debug"]==="yes") echo "</div/>";
$this-/>Select("SELECT * FROM $this-/>dbName");
return true;
}
มีคำสั่งที่ผมต้องสร้างขึ้นมาใหม่ 2-3 คำสั่ง เนื่องจากยังต้องใช้อีกหลายแห่ง คือ
1. db_propertyExplode ซึ่งทำงานคล้ายคำสั่ง Explode ของ PHP
2. db_arrayPrint ไว้สำหรับพิมพ์แสดงค่าตัวแปรชนิด Array
2. explodeSqlCmd ไว้สำหรับถอดคำสั่ง SQL ให้ออกมาเป็นส่วนๆ เพื่อจะได้หาองค์ประกอบของคำสั่งต่อไป
งานส่วนใหญ่ของ Method คือการถอดคำสั่ง SQL ออกมาเป็นส่วนๆ เพื่อหาชื่อฟิลด์ และคุณสมบัติของแต่ละฟิลด์ แล้วสร้างแฟ้มที่ประกอบด้วยส่วนหัวของตาราง ด้วยคำสั่ง
$fp=fopen($this->dbFullName(),"w");
if ($fp) {
fputs($fp,$dbStructure._dbNewLine);
fclose($fp);
}
แค่นี้ก่อน โปรดติดตามอ่านตอนต่อไปนะครับ......
(Top 7 Internet Threats in Thailand and 10 Easy Steps to Protect Yourself from the Internet Threats)
ปัญหาภัยอินเทอร์เน็ตของประเทศไทยจากสถิติในสองสามปีที่ผ่านมา พบว่ามีอัตราการเพิ่มขึ้นของปัญหาต่าง ๆ เป็นไปอย่างก้าวกระโดดตามอัตราการเพิ่มขึ้นของจำนวนผู้ใช้อินเทอร์เน็ตในประเทศไทย ซึ่งในขณะนี้คาดว่า ผู้ใช้งานอินเทอร์เน็ตมีจำนวนไม่ต่ำกว่า 10 ล้านคน ตลอดจนการเพิ่มจำนวนของผู้ใช้อินเทอร์เน็ตตามบ้านที่ใช้ Broadband Internet (ADSL) จำนวนไม่ต่ำกว่า 500,000 ครัวเรือน ปัญหาภัยที่มาจากอินเทอร์เน็ตจึงมีอัตราเพิ่มขึ้นจากปัจจัยดังกล่าว ซึ่งในอนาคตคาดว่าผู้ใช้ Broadband Internet น่าจะไม่ต่ำกว่า 1 ล้านครัวเรือน
ส่วนใหญ่ผู้ใช้อินเทอร์เน็ตตามบ้านมักจะไม่ค่อยมีความรู้ความเข้าใจเรื่องภัยอินเทอร์เน็ตเพียงพอจึงตกเป็นเหยื่อของผู้ไม่หวังดีเข้ามายึดเครื่องเพื่อทำเป็น “BOTNET” หรือ “Robot Network” จากนั้น แฮกเกอร์ ก็จะใช้เครื่องคอมพิวเตอร์ตามบ้านของเราส่ง SPAM Mail หรือส่งข้อมูลตามที่แฮกเกอร์ต้องการซึ่งในปัจจุบันกฎหมายการกระทำผิดเกี่ยวกับคอมพิวเตอร์ได้ผ่าน สนช. เป้นที่เรียบร้อยแล้ว และ กำลังจะมีผลบังคับใช้ในอีก ไม่กี่เดือนข้างหน้าภายในปี พ.ศ. 2550 นี้ โดยมาตรา 11 ระบุชัดเจนว่าผู้ส่ง SPAM Mail มีโทษปรับไม่เกิน 100,000 บาท และ ผู้ที่ชอบ Forward Mail โดยไม่ระมัดระวัง และทำให้ผู้อื่นเกิดความเสียหายก็มีโทษเช่นกัน (เข้ามาตรา 14)
ดังนั้นผู้ใช้อินเทอร์เน็ตตามบ้าน อาจกลายเป็น “แพะรับบาป”โดยไม่รู้ตัว เนื่องจากแฮกเกอร์เข้ามาใช้เครื่องของเราในการทำกิจกรรมที่ไม่ชอบด้วยกฎหมายดังที่กล่าวมาแล้ว เราจึงควรเตรียมตัวพร้อมรับภัยจากอินเทอร์เน็ตในรูปแบบต่าง ๆ ที่นับวันจะมีพัฒนาการเปลี่ยนแปลงรูปแบบ ทำให้โปรแกรมกำจัดไวรัสไม่สามารถที่จะตรวจรับโปรแกรมมุ่งร้าย (MalWare) ในบางโปรแกรมได้ เราจึงจำเป็นต้องเรียนรู้และเข้าใจภัยอินเทอร์เน็ตให้มากขึ้น และตระหนักไว้เสมอว่าไม่มีโปรแกรมกำจัดไวรัส โปรแกรมใดที่สามารถป้องกันภัยอินเทอร์เน็ตให้เราได้ 100% ตัวเราเองจำเป็นต้องมีสติ และ ระมัดระวังในการเปิดไฟล์ที่แนบมากับ อิเล็กโทรนิคส์เมล์ หรือ ระวังในการ “Click” Link ต่าง ๆ ที่อยู่ใน Web Browser หรือมากับเนื้อความใน อิเล็กโทรนิคส์เมล์ (eMail) ตลอดจน Link มักถูกส่งมาจากเพื่อนที่ใช้งาน MSN หรือ IM(Instant Messaging) กับเราอยู่โดยที่เครื่องของเพื่อนเราอาจถูก MalWare เล่นงานแล้วส่ง Link มาหลอกเรา โดยที่เพื่อเราเองยังไม่รู้ตัวเลยก็เป็นได้
ภัยอันดับหนึ่ง : ภัยจาก SPAM Mail (SPAM Threat)
ปัญหา SPAM Mail ถือเป็นปัญหาอันดับหนึ่งของผู้ใช้อินเทอร์เน็ตในวันนี้ เพราะเราต้องเปิดอ่าน อิเล็กโทรนิคส์เมล์ทุกวัน ซึ่งหลายครั้งพบว่าเราได้รับอิเล็กโทรนิคส์เมล์ที่เราไม่อยากอ่านแต่มีผู้ส่งมาให้เราเป็นประจำ เช่น email ขายยา Viagra เป็นต้น นอกจากจะเกิดความรำคาญในการคัดเลือก Junk Email แล้ว อิเล็กโทรนิคส์เมล์บางฉบับมีไฟล์แนบหรือ “Attached File” ที่เป็น Mal Ware หรือ Virus โดยจะมีนามสกุลไฟล์แปลก ๆ เช่น .SCR หรือ .PIF บางครั้งก็ใช้นามสกุลไฟล์ที่เห็นได้ชัดว่าเป็นโปรแกรมไม่ใช่ไฟล์เอกสาร เช่น นามสกุลไฟล์ .EXE, .COM หรือเป็น Script เช่น .VBS, .BAT หรือ .CMD เป็นต้น ไฟล์นามสกุลต่าง ๆ ดังที่กล่าวมาแล้วล้วนมีโอกาสเป็น Mal ware ถึง 95% ขึ้นไป ดังนั้น เราจึงไม่ควรเปิดไฟล์แนบดังกล่าว (ควรจะลบทิ้งเลยด้วยซ้ำ) และนอกจากนั้นไฟล์นามสกุล .ZIP ซึ่งเป็นไฟล์ที่ถูกบีบอัดมาบางไฟล์มีไฟล์ MalWare อยู่ข้างในก็มี เราจึงต้องระมัดระวังเป็นพิเศษ ในการเปิดไฟล์แนบ แม้ว่า email นั้นจะมาจากคนรู้จักหรือเพื่อนร่วมงานก็ไม่ควรไว้ใจเพราะ SPAMMER อาจจะแอบขโมย email address จาก Google ได้เพียงแค่พิมพ์ @ ตามด้วย Domain name เช่น @ abc.com ก็สามารถจะหา email address ได้อย่างง่ายดาย เราจึงไม่ควรเปิดเผย email address ของเราในอินเทอร์เน็ตโดยไม่จำเป็นเนื่องจากผลกระทบของ SPAM Mail ไม่ใช่แค่เรื่องความรำคาญแต่ SPAM Mail อาจนำ MalWare หรือ Virus เข้ามาในเครื่องคอมพิวเตอร์ตลอดจนระบบเครือข่ายของเรา ดังนั้น การใช้โปรแกรมหรืออุปกรณ์ในการป้องกัน SPAM (ANTI-SPAM) จึงมีความสำคัญอย่างยิ่งยวด โดยเฉพาะองค์กรที่มีผู้ใช้งาน email เป็นจำนวนมาก ยิ่งจำเป็นต้องจัดหาอุปกรณ์ ANTI-SPAM มาใช้ที่บริเวณ Gateway หรือ บริเวณ DMZ ของระบบเครือข่าย เพื่อให้มั่นใจว่าเราได้มีการป้องกันในระดับที่ไม่ส่งผลกระทบกับองค์กรในกรณีที่ผู้ใช้ได้รับ SPAM Mail แล้วเผลอเปิดไฟล์แนบที่มี MalWare หรือ Virus ติดมาโดยไม่ระมัดระวัง การป้องกัน SPAM ที่บริเวณ Gateway นั้นเป็นปราการด่านแรกที่เราควรจะมี หากหลุดจาก Gateway มาแล้วก็ควรจะกรองที่ email server และ email client อีก สองชั้น หากทำได้ตามนี้ เชื่อว่าปัญหา SPAM ก็จะลดลง เช่น จากเคยได้รับ SPAM Mailวันละ 20-30 ฉบับ ก็ อาจเหลือเพียง 1-2 ฉบับ ต่อวัน ก็ถือว่าได้ผลเป็นที่น่าพอใจในระดับหนึ่งแค่นี้ก่อน โปรดติดตามอ่านตอนต่อไปนะครับ......