การเขียนโปรแกรมภาษา PHP

            
               

ฟังก์ชันที่ทำงานตรงกันข้ามกับฟังก์ชัน explode() คือฟังก์ชัน join ตัวอย่างการใช้งานมีดังนี้

<?
unset($a);
$a[]="aaa";
$a[]="bbb";
$a[]="ccc";
echo join(":",$a)."<BR>\n";
?>

การแปลง \n ให้เป็น <BR>

ฟังก์ชัน nl2br จะทำหน้าที่แปลง \n ให้เป็น <BR> สำหรับขึ้นบรรทัดใหม่ในเอกสาร HTML โดยอัตโนมัติ เช่น สมมุติว่า เราเปิดไฟล์และอ่านข้อความจากไฟล์นั้น แล้วต้องการจะแทรกข้อความเหล่านั้น เป็นบรรทัดๆ
ลงในเอกสาร HTML เนื่องจากว่าในข้อความที่เป็นสตริงค์และมี '\n' จบท้าย และเราต้องการจะแปลงให้เป็น <BR> เพื่อจัดหน้าเอกสารให้เหมาะสม เราก็ใช้ฟังก์ชันดังกล่าวช่วย

<?
// convert \n to <br>
$br=nl2br("\n\n");
echo $br."hello".$br;
?>
การตัวแปรแบบ static ภายในฟังก์ชัน

สมมุติว่า เราต้องการจะใช้ตัวแปรภายในฟังก์ชัน และสามารถเก็บค่าไว้ได้ตลอดเวลา โดยไม่สูญหายไปทุกครั้งที่มีการเรียกใช้ฟังก์ชัน ในกรณีนี้เราจะแจ้งใช้ตัวแปรให้เป็นแบบ static ตามตัวอย่างต่อไปนี้

function MyFunc() {
static $num_func_calls = 0;
echo "my function\n";
return ++$num_func_calls;
}
ทุกครั้งที่มีการเรียกใช้ฟังก์ชันดังกล่าว ตัวแปรชื่อ $num_func_calls ซึ่งมีค่าเริ่มต้นเป็นศูนย์ในตอนแรก จะเพิ่มค่าที่เก็บขึ้นทีละหนึ่ง
--------------------------------------------------------------------------------
การผ่านค่ากลับคืนมากกว่าหนึ่งจากฟังก์ชัน

โดยปรกติแล้วเราไม่สามารถผ่านค่ากลับคืนจากฟังก์ชันได้มากกว่าหนึ่ง แต่อย่างไรก็ตาม ยังมีวิธีการหนึ่งที่ช่วยแก้ปัญหาดังกล่าวได้ วิธีนี้คือ เก็บค่าต่างๆที่ต้องการจะใช้เป็นค่ากลับคืนไว้ใน array แล้วใช้ array นั้นเป็นค่ากลับคืน และผู้เรียกใช้ฟังก์ชันสามารถใช้ฟังก์ชัน list() อ่านค่าเหล่านั้นได้ ตัวอย่างเช่น

<?
function foobar() {
return array ("foo", "bar", 0xff);
}
list ($foo, $bar, $num) = foobar();
echo "$foo $bar $num <BR>\n";
?>
จากตัวอย่าง ฟังก์ชัน foobar() จะให้ค่ากลับคืนเป็น array ประกอบด้วยสามสมาชิก ค่าที่ได้จากฟังก์ชันนี้ก็จะส่งไปยังฟังก์ชัน list() เพื่อให้เก็บแยกลงในตัวแปรตามชื่อที่กำหนดคือ $foo, $bar และ $num ตามลำดับ
ถ้าเราต้องการสลับค่าระหว่างสองตัวแปร เราก็เขียนฟังก์ชัน swap() ขึ้นมา

<?
function swap(&$a, &$b) {
$t = $a;
$a = $b;
$b = $t;
}
$x=10;
$y=3;
echo "x=",$x,",y=",$y,"\n";
swap($x,$y);
echo "x=",$x,",y=",$y,"\n";
?>

ตัวอย่างข้างบน ก็แสดงให้เห็นวิธีการใช้ call-by-reference อีกเช่นกัน
มีข้อสังเกตอยู่ว่า การใช้ call-by-reference ไม่จำเป็นต้องทำตอนนิยามฟังก์ชันเท่านั้น แต่อาจจะทำตอนผ่านตัวแปรเมื่อเรียกใช้งานจริง ตัวอย่างเช่น

<?
function swap($a, $b) {
$t = $a;
$a = $b;
$b = $t;
}
$x=10;
$y=3;
echo "x=",$x,",y=",$y,"\n";
swap(&$x, &$y);
echo "x=",$x,",y=",$y,"\n";
?>
จากตัวอย่างนี้ เราแก้ไขฟังก์ชัน swap() ทำให้ไม่สนับสนุน call-by-reference ดังนั้นเพื่อจะใช้งานได้อย่างถูกต้อง เราก็จะต้องใช้ reference ของตัวแปรเป็นอาร์กิวเมนต์ของฟังก์ชัน ในเวลาที่เรียกใช้ ซึ่งก็คือ swap(&$x,&$y) ถ้าเราไม่ทำอย่างนี้ เช่น เขียนว่า swap($x,$y) ก็จะไม่มีการสลับค่าของตัวแปรทั้งสอง เนื่องจากว่า เมื่ออยู่ภายในฟังก์ชัน swap() แล้ว เราไม่สามารถเปลี่ยนแปลงค่าของตัวแปรเหล่านั้นได้ คืออ่านได้ แต่ไม่สามารถกำหนดค่าใหม่ได้
ถ้าต้องการเช็คดูว่า ตัวแปรมีข้อมูลแบบใด เราสามารถใช้คำสั่ง gettype() ได้ ค่าที่ได้จากฟังก์ชันก็จะเป็น "integer" "double" หรือ "string" เป็นต้น

<?
echo gettype(0),"\n";
echo gettype(1.1),"\n";
echo gettype(""),"\n";
echo gettype((1==1)),"\n";
$var="abc";
if ( gettype($var)=="string" ) {
echo "this is a string\n";
}
?>

เราอาจจะไม่ใช้ gettype() ก็ได้ แต่เลือกใช้ฟังก์ชัน is_long() สำหรับเช็คค่าที่เป็นเลขจำนวนเต็ม, is_string() สำหรับเช็คค่าที่เป็นสตริงค์, is_double() สำหรับค่าที่เป็นเลขทศนิยม, is_array() สำหรับค่าที่เป็นอาร์เรย์ หรือ is_object() สำหรับค่าที่เป็นออปเจคจากคลาสแทน ซึ่งจะให้ค่าเท่ากับ true (1) ถ้าตัวแปรมีแบบข้อมูล ตรงตามที่กำหนด

<?
unset($a);
$a="hello";
if (is_string($a) == true) {
echo "\$a is a string <BR>\n";
}
unset($a);
$a[]="red";
$a[]="green";
$a[]="blue";
if (is_array($a) == true) {
echo "\$a is an array of size ",count($a),"<BR>\n";
}
?>
โปรดสังเกตว่า เราใช้คำสั่ง unset() เพื่อลบค่าที่ตัวแปรเก็บอยู่ในขณะนั้น ในกรณีนี้ เรากำหนดให้ $a เป็นสตริงค์ในตอนแรก ถ้าเราจะต้องการใช้ตัวแปรตัวเดียวกันนี้ เป็นค่าใหม่แต่เป็นอาร์เรย์ ก็จะใช้คำสั่ง unset() ก่อน
ตัวอย่างการใช้ echo เพื่อแสดงข้อความ (เพิ่มเติม)
การพิมพ์ค่าใดๆที่เก็บอยู่ในตัวแปร ถ้าชื่อของตัวแปรอยู่ในสตริงค์ระหว่าง double quote เวลาสร้างเอาพุตแล้ว จะอ่านค่าของตัวแปรนั้นก่อนแล้วจึงแทนที่ลงในข้อความ แต่ถ้านำหน้าด้วย backslash (\) ก็จะไม่มีการอ่านค่าของตัวแปร เช่น "\$a" จะให้ผลต่างจาก "$a" สังเกตได้จากตัวอย่างต่อไปนี้

<?
$a=1;
echo "\$a=$a <BR>\n";
$test = "test";
echo "$test$test$test<BR>\n";
echo $test,$test,$test,"<BR>\n";
$a = 1;
$b = 2;
echo $a,"+",$b,"=","$a+$b","<BR>\n";
echo $a,"+",$b,"=",$a+$b,"<BR>\n";
?>

สำหรับข้อความในภาษา PHP เราอาจจะใช้ single qoute แทน double quote ได้ แต่เวลาใช้งานร่วมกับ echo หรือ print() จะให้ผลต่างกัน ซึ่งสังเกตได้จากตัวอย่างต่อไปนี้

<?
$a = "aaa";
$b = 'bbb';
echo "$a $b<BR>\n";
echo '$a $b<BR>\n';
?>

ตัวแปลคำสั่งจะมองข้ามชื่อตัวแปรและรวมถึงพวก escape sequence ต่างๆด้วยที่อยู่ในข้อความที่ใช้ single quote
Regular Expression หรือเรียกย่อๆว่า Regex หมายถึง รูปแบบของลำดับ หรือกลุ่มของสัญลักษณ์ ที่ใช้แทนลำดับ หรือกลุ่มของอักขระตามที่ต้องการ

เราใช้สัญลักษณ์ [ ] (square brackets) เพื่อกำหนดขอบเขตของกลุ่มตัวอักขระหลายตัวที่ใช้เป็นตัวเลือก เช่น สมมุติว่า เราต้องการจะเขียนรูปแบบที่ใช้แทนตัวอักขระหนึ่งตัว อะไรก็ได้จาก {a,e,i,o,u} เราก็จะเขียนว่า [aeiou] โดยจะเรียงลำดับก่อนหลังอย่างไรก็ได้ เช่น [eioua] ให้ผลเหมือนกับ [aeoui] หรือ ถ้าเราต้องการเขียน รูปแบบเพื่อใช้แทนตัวขระหนึ่งตัวที่เป็นตัวเลขตัวใดตัวหนึ่งจาก 0 ถึง 9 เราก็เขียนว่า [0123456789] หรือจะเขียนแบบสั้นๆใหม่ได้เป็น [0-9] หรืออีกตัวอย่างหนึ่ง ถ้าเราต้องการจะเขียนนิพจน์แบบ regex ขึ้นมา เพื่อใช้แทนอักขระตัวใดตัวหนึ่งที่เป็นได้ทั้งตัวพิมพ์ใหญ่หรือเล็กในภาษาอังกฤษหรือตัวเลขระหว่าง 0 ถึง 9 เราก็เขียนว่า [A-Za-z0-9]


[aeiou] 

ตัวอักขระตัวหนึ่งจาก {a,e,i,o,u} ตัวไหนก็ได้

[0-9] 

ตัวอักขระตัวหนึ่งจาก {0,1,...,9} ตัวไหนก็ได้

[A-Za-z0-9] 

ตัวอักขระตัวหนึ่งจาก {A,B,..,Z, a, b, ... , z, 0, 1, ... 9} ตัวไหนก็ได้

ถ้าเรามีข้อความแล้วเราต้องการจะค้นหาอักขระหรือลำดับของอักขระ (หรือ pattern) ในข้อความเรานั้น เราเรียกขั้นตอนในการค้นหาตามรูปแบบนี้ว่า pattern matching ในภาษา PHP จะมีฟังก์ชันที่เราใช้ในการค้นหาลำดับของตัวอักขระตามแบบที่ต้องการคือ ereg() และ eregi()
และต่างกันตรงที่ว่า ฟังก์ชัน eregi() จะเปรียบเทียบโดยไม่คำนึงถึงเรื่องตัวพิมพ์เล็กหรือใหญ่
ตัวอย่างเช่น สมมุติว่า เรามีข้อความอยู่ในอาร์เรย์เป็นข้อความที่มีแค่ตัวอักขระตัวเดียว แล้วเราต้องการจะหาว่า ตัวไหนบ้างที่เป็นตัวเลข 0 ถึง 9 บ้างและตัวไหนบ้างที่เป็นตัวพิมพ์ภาษาอังกฤษ a, b, หรือ c เราก็เขียนสคริปต์โดยใช้ฟังก์ชัน ereg() ได้ดังนี้

<?
$a=array("0","1","2","3","5","7","a","b","c");

for ($i=0; $i < count($a); $i++) { // print only digit
if ( ereg("[0-9]",$a[$i]) ) {
print ("$a[$i] <BR>\n");
}
}
?>
<HR>
<?
for ($i=0; $i < count($a); $i++) { // print only a, b or c
if ( ereg("[a-c]",$a[$i]) ) {
print ("$a[$i] <BR>\n");
}
}
?>
ข้อความที่เราใช้ในตัวอย่างข้างบนมีแค่ตัวอักขระเพียงหนึ่งตัว แต่อันที่จริงแล้วฟังก์ชัน ereg() จะให้ค่าเป็นจริง ถ้าพบว่า ข้อความที่มีความยาวมากกว่าหนึ่งตัวอักขระและมีตัวอักขระอย่างน้อยหนึ่งตัวที่ตรงตามรูปแบบที่กำหนด ฟังก์ชันก็จะให้ค่าเป็นจริงด้วย ตัวอย่างเช่น

<?
$a=array("f","mn", "eU","+5","Y","17","a4","%m","cdef");
for($i=0; $i < count($a); $i++) {
if ( ereg("[a-z]",$a[$i]) ) {
print ("$a[$i] <BR>\n");
}
}
?>
ผลจากการทำงานของสคริปตในตัวอย่างนี้จะได้ว่า ข้อความที่ตรงตามรูปแบบ [a-z] โดยใช้ฟังก์ชัน ereg() ในการเปรียบเทียบ คือ "f", "mn", "eU", "a4", "%m" และ "cdef" เพราะว่าข้อความเหล่านี้ มีตัวอักขระอย่างน้อยหนึ่งตัวที่อยู่ระหว่าง a ถึง z ดังนั้นจึงจะเห็นได้ว่า ข้อความที่เหลือคือ "+5", "Y" และ "17" ไม่ตรงตามรูปแบบ
จากตัวอย่างข้างบน สมมุติว่า เราต้องการจะหาข้อความที่มีสองตัวอักขระและมีแค่สองตัวเท่านั้น เป็นตัวใดก็ได้ระหว่าง a ถึง z เราก็จะต้องกำหนดรูปแบบให้การค้นหาให้เป็น ^[a-z]{2}$ โดยที่สัญลักษณ์ ^ หมายถึงการเริ่มต้น และ $ หมายถึงการลงท้าย และเราจะอ่านว่า ให้ค้นหาข้อความที่เริ่มต้นด้วยตัวภาษาอังกฤษพิมพ์เล็ก และจบด้วยตัวภาษาอังกฤษพิมพ์เล็ก และมีอยู่สองตัวเท่านั้น จากตัวอย่างข้างบน ถ้าเราใช้รูปแบบใหม่นี้ในการค้นหา เราจะได้ "en" เป็นข้อความเดียวเท่านั้นที่ตรงตามรูปแบบ
สมมุติว่า เราต้องการค้นหาคำที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่ภาษาอังกฤษและตามด้วยสระ {a,e,i,o,u} ถ้าข้อความมีมากกว่าสองตัวอักขระแล้วตัวที่ตามมาจะเป็นอะไรก็ได้ เราก็เขียนรูปแบบในการค้นหาได้ เป็น ^[A-Z][aeiou] ลองตัวดูอย่างต่อไปนี้

<?
$a=array("f","Monday", "eU","755","Pu","English","Tuesday","for", "Bee");

for($i=0; $i < count($a); $i++) {
if ( ereg("^[A-Z][aeiou]",$a[$i]) ) {
print ("$a[$i] <BR>\n");
}
}
?>

ตัวอย่างนี้จะได้ว่า "Monday", "Pu" ,"Tuesday" และ "Bee" คือข้อความที่ตรงตามรูปแบบที่กำหนด
ถ้าต้องการจะหาข้อความที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่แล้วตามด้วยสระเป็นตัวพิมพ์เล็กอย่างน้อยหนึ่งตัว เราก็เขียนว่า ^[A-Z][aeiou]+$ ซึ่งเครื่องหมายบวกที่อยู่ข้างหลัง [aeiou] หมายความว่า มีได้อย่างน้อยที่สุดหนึ่งตัว จากตัวอย่างข้างบน ถ้าเราใช้รูปแบบใหม่นี้ในการค้นหา ก็จะได้ข้อความ "Pu" และ "Bee" เท่านั้นที่ตรงตามรูปแบบ
ถ้าจะหาข้อความที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่แต่ตามด้วยตัวพิมพ์เล็กใดๆก็ได้ที่ไม่ใช่สระ {a,e,i,o,u} เราก็เขียนใหม่ได้เป็น ^[A-Z][^aeiou] โปรดสังเกตว่า เราใส่สัญลักษณ์ ^ ไว้ระหว่าง [ ] และอยู่ข้างหน้าสุด เพื่อใช้กำหนดกรณีตรงข้าม และจากตัวอย่างข้างบน เราจะได้ข้อความ "English" เท่านั้นที่ตรงตามรูปแบบใหม่นี้
อีกตัวอย่างหนึ่งที่น่าสนใจ คือ สมมุติว่า เรามีรายชื่อไฟล์อยู่หลายๆชื่อ ต้องการจะตรวจดูว่า ชื่อไหนลงท้ายด้วย .gif .jpeg .jpg หรือ .png บ้าง โดยใช้ eregi() ในการค้นหา เราจะต้องกำหนดรูปแบบของ regex ขึ้นมาก่อน ซึ่งทำได้ดังนี้ (\.gif|\.jpg|\.jpeg|\.png)$ ในกรณีนี้เราไม่ได้ใช้ [ ] แต่ใช้วงเล็บคู่ ( ) แทน และสัญลักษณ์ \. เป็น escape sequence ที่เราใช้แทนจุด (.) ถ้าเขียนอยู่ในระหว่างวงเล็บคู่ เนื่องจากว่าถ้าใช้จุดโดยไม่มี backslash (\) นำหน้าก็จะหมายถึง ตัวอักขระใดๆก็ได้ ถ้าเราใช้จุดระหว่าง [ ] ก็จะหมายถึงจุด โดยไม่ต้องใส่ \ ไว้เพื่อกำหนดให้เป็น escape sequence


<?
$files=array("bird.gif","Linux.JPG", "unknown.xbm","icon.Png");
for($i=0; $i < count($files); $i++) {
if ( eregi("(\.gif|\.jpg|\.jpeg|\.png)$",$files[$i]) ) {
print ("$files[$i] <BR>\n");
}
}
?>

ความแตกต่างของการใช้ ( ) และ [ ] อยู่ที่ว่า ถ้าเขียน (abc) หมายถึงข้อความที่เริ่มด้วย a ตามด้วย b และ c ตามลำดับ ในขณะที่ [abc] หมายถึง a หรือ b หรือ c ซึ่ง [abc] จะให้ผลเหมือนกับ (a|b|c) และเครื่องหมาย | ที่ใช้ภายในวงเล็บคู่ ( ) จะหมายถึง "หรือ" ดังนั้นจากตัวอย่างข้างบน จากรูปแบบเดิม (\.gif|\.jpg|\.jpeg|\.png)$ เราอาจจะเขียนใหม่ได้เป็น [(\.gif|\.png)(\.jpg|\.jpeg)]$ ก็จะให้ผลเหมือนกัน
จากที่ได้อธิบายมาก็เป็นเพียงการใช้งานส่วนหนึ่งของ Regular Expression ซึ่งยังมีลักษณะและการใช้งานที่นอกเหนือจากที่กล่าวไป
สัญลักษณ์พื้นฐานที่ใช้ในการเขียน Regular Expression


 .

 ตัวอักขระใดๆก็ได้

 [ ... ]

 ตัวอักขระตัวใดๆก็ได้ที่อยู่ในกลุ่มของตัวอักขระที่เป็นตัวเลือก

 [^... ]

 ตัวอักขระตัวใดๆก็ได้ที่ไม่ได้อยู่ในกลุ่มของตัวอักขระที่เป็นตัวเลือก

 ^

 ตำแหน่งเริ่มต้นของข้อความ

 $

 ตำแหน่งท้ายสุดของข้อความ

 \<

 ตำแหน่งเริ่มต้นของคำ

 \>

 ตำแหน่งท้ายสุดของคำ

 |

 สัญลักษณ์ที่ใช้แยกตัวเลือกระหว่าง ( ... )

 (...)

 ใช้แทนกลุ่มของตัวเลือก

Repetition Quantifiers


 ? 

 ถ้ามีก็ไม่เกินหนึ่งตัวหรือไม่มีก็ได้

 *

 มีหนึ่งตัวหรือมากกว่าหนึ่งหรือไม่มีเลยก็ได้

 +

 มีหนึ่งตัวหรือมากกว่าหนึ่งก็ได้ แต่ต้องมีอย่างน้อยหนึ่งตัว

{min,max}

 ใช้กำหนดจำนวนน้อยที่สุดและมากที่สุดที่จะมีได้

ตัวอย่างของการใช้ regular expressions


^be

 ข้อความที่ขึ้นต้นด้วย b และถัดจาก b ตามด้วย e

^[be]

 ข้อความที่ขึ้นต้นด้วย b หรือ e

[^be]

 ข้อความที่ไม่ได้ขึ้นต้นด้วย b และ e

ion$

 ข้อความที่ลงท้ายด้วยหรือจบท้ายด้วย ion

[ion]$

 ข้อความที่ลงท้ายหรือจบท้ายด้วย i หรือ o หรือ n

\n$

 ข้อความที่มีสัญลักษณ์ \n (new line) อยู่ท้าย

<H[1-6]>

 ข้อความที่มี <H1> <H2> <H3> <H4> <H5> หรือ <H6> อยู่ด้วย

<H[^4-6]>

 ข้อความที่ไม่มี <H4> <H5> และ <H6> อยู่ด้วย

[0-9.]

 ข้อความที่มีตัวเลขใดๆระหว่าง 0 ถึง 9 หรือ จุด อยู่ด้วย

^Subject$

 ข้อความที่มีคำว่า Subject เท่านั้น

^(From|Subject|Date):

 ข้อความที่มีคำว่า From: หรือ Subject: หรือ Date: ขึ้นต้น

^[0-9]+$

 ข้อความที่มีตัวเลขเท่านั้นและอย่างน้อยหนึ่งตัว

([0-9]+(\.[0-9]+){3})

 ข้อความที่ตรงตามรูปแบบของหมายเลข IP เช่น 127.0.0.1

^[-+]?[0-9]+(\.[0-9]*)?$

 ข้อความที่ตรงตามรูปแบบของตัวเลขทศนิยม เช่น -12.345

การใช้งาน regular expression อย่างจริงจังนั้นไม่ใช่เป็นเรื่องง่าย ต้องทำความเข้าใจอย่างจริงจัง และในเอกสารนี้ก็ทำได้แค่นำเสนอเนื้อหาพื้นฐานสำหรับการใช้งานเท่านั้น ถ้าใครสนใจการใช้งานอย่างจริงจัง ในเรื่องของ regular expression ก็สามารถหาหนังสือ สำหรับเรื่องนี้โดยเฉพาะมาอ่านได้

TOP