วันพฤหัสบดีที่ 27 พฤศจิกายน พ.ศ. 2557

ฟังก์ชันใน PHP

ฟังก์ชันใน PHP

ฟังก์ชันในโปรแกรมส่วนใหญ่ได้รับการเรียกคำสั่งเพื่อทำงานอย่างเดียว สิ่งนี้ทำให้คำสั่งอ่านได้ง่ายและยอมให้ใช้คำสั่งใหม่แต่ละครั้งเมื่อต้องการทำงานเดียวกัน
ฟังก์ชันเป็นโมดูลเก็บคำสั่งที่กำหนดการเรียกอินเตอร์เฟซ ทำงานเดียวกัน และตัวเลือกส่งออกค่าจากการเรียกฟังก์ชัน คำสั่งต่อไปเป็นการเรียกฟังก์ชันอย่างง่าย
my_function ();
คำสั่งเรียกฟังก์ชันชื่อ my_function ที่ไม่ต้องการพารามิเตอร์ และไม่สนใจค่าที่อาจจะส่งออกโดยฟังก์ชันนี้
ฟังก์ชันจำนวนมากได้รับการเรียกด้วยวิธีนี้ เช่น ฟังก์ชัน phpinfo () สำหรับแสดงเวอร์ชันติดตั้งของ PHP สารสนเทศเกี่ยวกับ PHP การตั้งค่าแม่ข่ายเว็บ ค่าต่างๆ ของ PHP และตัวแปร ฟังก์ชันนี้ไม่ใช้พารามิเตอร์และโดยทั่วไปไม่สนใจค่าส่งออก ดังนั้นการเรียก phpinfo () จะประกอบขึ้นดังนี้
phpinfo ();

การกำหนดฟังก์ชันและการเรียกฟังก์ชัน

การประกาศฟังก์ชันเริ่มต้นด้วยคีย์เวิร์ด function กำหนดชื่อฟังก์ชัน พารามิเตอร์ที่ต้องการ และเก็บคำสั่งที่จะประมวลผลแต่ละครั้งเมื่อเรียกฟังก์ชันนี้
<?php
function function_name(parameter1,…)
{
ชุดคำสั่ง …
}
?>
ชุดคำสั่งต้องเริ่มต้นและสิ้นสุดในวงเล็บปีกกา ({ }) ตัวอย่างฟังก์ชัน my_function
<?php
function my_function()
{
$mystring =<<<BODYSTRING
my function ได้รับการเรียก
BODYSTRING;
echo $mystring;
}
?>
การประกาศฟังก์ชันนี้ เริ่มต้นด้วย function ดังนั้นผู้อ่านและตัวกระจาย PHP ทราบว่าต่อไปเป็นฟังก์ชันกำหนดเอง ชื่อฟังก์ชันคือ my_function การเรียกฟังก์ชันนี้ใช้ประโยคคำสั่งนี้
my_function ();
การเรียกฟังก์ชันนี้จะให้ผลลัพธ์เป็นข้อความ "my function ได้รับการเรียก " บน browser

การตั้งชื่อฟังก์ชัน

สิ่งสำคัญมากในการพิจารณาเมื่อตั้งชื่อฟังก์ชันคือชื่อต้องสั้นแต่มีความหมาย ถ้าฟังก์ชันสร้างส่วนตัวของเพจควรตั้งชื่อเป็น pageheader () หรือ page_header ()
ข้อจำกัดในการตั้งชื่อคือ
  • ฟังก์ชันไม่สามารถมีชื่อเดียวกับฟังก์ชันที่มีอยู่
  • ชื่อฟังก์ชันสามารถมีได้เพียงตัวอักษรตัวเลข และ underscore
  • ชื่อฟังก์ชันไม่สามารถเริ่มต้นด้วยตัวเลข
หลายภาษายอมให้ใช้ชื่อฟังก์ชันได้อีก ส่วนการทำงานนี้เรียกว่า function overload อย่างไรก็ตาม PHP ไม่สนับสนุน function overload ดังนั้นฟังก์ชันไม่สามารถมีชื่อเดียวกันกับฟังก์ชันภายใน หรือฟังก์ชันกำหนดเองที่มีอยู่
หมายเหตุ ถึงแม้ว่าทุกสคริปต์ PHP รู้จักฟังก์ชันภายในทั้งหมด ฟังก์ชันกำหนดเองอยู่เฉพาะในสคริปต์ที่ประกาศสิ่งนี้หมายความว่า ชื่อฟังก์ชันสามารถใช้ในคนละไฟล์แต่อาจจะไปสู่ความสับสน และควรหลีกเลียง
ชื่อฟังก์ชันต่อไปนี้ถูกต้อง
name ()
name2 ()
name_three ()
_namefour ()
ชื่อไม่ถูกต้อง
5name ()
Name-six ()
fopen ()
การเรียกฟังก์ชันไม่มีผลจากชนิดตัวพิมพ์ ดังนั้นการเรียก function_name (), Function_Name() หรือ FUNCTION_NAME() สามารถทำได้และมีผลลัพธ์เหมือนกัน แต่แบบแผนการกำหนดชื่อฟังก์ชันใน PHP ให้ใช้ตัวพิมพ์เล็ก
ชื่อฟังก์ชันแตกต่างจากชื่อตัวแปร โดยชื่อตัวแปรเป็นชนิดตัวพิมพ์มีผล ดังนั้น $Name และ $name เป็น 2 ตัวแปร แต่ Name () และ name () เป็นฟังก์ชันเดียวกัน

การหยุดประมวลผลภายในฟังก์ชัน

คีย์เวิร์ด return หยุดการประมวลผลฟังก์ชัน ฟังก์ชันสิ้นสุดได้เพราะประโยคคำสั่งทั้งหมดได้รับการประมวลผล หรือ ใช้คีย์เวิร์ด return การประมวลผลกลับไปยังประโยคคำสั่งต่อจากการเรียกฟังก์ชัน
<?php
function division($x, $y)
{
if ($y == 0 || !isset($y))
{

echo " ตัวหาร y ต้องไม่เป็นศูนย์หรือไม่มีค่า" ;
return;
}
$result = $x / $y;
echo $result;
}
?>
ถ้าประโยคคำสั่ง return ได้รับการประมวลผล บรรทัดคำสั่งต่อไปในฟังก์ชันจะถูกข้ามไป และกลับไปยังผู้เรียกฟังก์ชันนี้ ในฟังก์ชันนี้ ถ้า y เป็น 0 จะหยุดการประมวลผล ถ้า y ไม่เท่ากับ 0 จะคำนวณผลหาร
สมมติป้อนค่าเป็น
x = 4, y = 0
x = 4
x = 4, y = 2
ผลลัพธ์ของคำสั่ง คือ
x = 4, y = 0 ผลลัพธ์ ตัวหาร y ต้องไม่เป็นศูนย์หรือไม่มีค่า
x = 4, y = ผลลัพธ์ ตัวหาร y ต้องไม่เป็นศูนย์หรือไม่มีค่า
x = 4, y = 2 ผลลัพธ์ 2

การเรียกฟังก์ชัน

เมื่อฟังก์ชันได้รับการประกาศหรือสร้างขึ้นแล้ว การเรียกฟังก์ชันสามารถเรียกมาจากที่ใดๆ ภายในสคริปต์ หรือ จากไฟล์ที่มีการรวมด้วยประโยคคำสั่ง include() หรือ require()
ตัวอย่าง ฟังก์ชัน show_message() เก็บอยู่ในไฟล์ fn_ 03 _keeper.php ส่วนผู้เรียกอยู่ในสคริปต์ fn_ 03 _caller.php
<?php
include("fn_ 03 _keeper.php");
show_message();
?>

พารามิเตอร์

ตามปกติฟังก์ชันส่วนใหญ่ต้องการรับสารสนเทศจากผู้เรียกสำหรับการประมวลผล โดยทั่วไปเรียกว่า พารามิเตอร์

ไวยากรณ์พื้นฐาน

การกำหนดฟังก์ให้รับพารามิเตอร์ส่งผ่านโดยการวางข้อมูล ชื่อตัวแปรที่เก็บข้อมูลภายในวงเล็บหลังชื่อฟังก์ชัน การเรียกฟังก์ชันที่ประกอบด้วยพารามิเตอร์เขียนดังนี้
<?php
function show_parameter($param1, $param2, $param3)
{
echo <<<PARAM
รายการพารามิเตอร์ <br/>
param1: $param1 <br/>
param2: $param2 <br/>
param3: $param3 <br/>
PARAM;
}
?>
พารามิเตอร์ที่ส่งไปยังฟังก์ชันแยกกันเครื่องหมายจุลภาคภายในวงเล็บ โดยสามารถส่งเป็นนิพจน์สำหรับแต่ละพารามิเตอร์ด้วย ตัวแปร ค่าคงที่ ผลลัพธ์จากการคำนวณ รวมถึงการเรียกฟังก์ชัน
scope ของพารามิเตอร์จำกัดภายในฟังก์ชัน ถ้าชื่อตัวแปรเหมือนกับตัวแปรใน scope ระดับอื่น พารามิเตอร์นี้ "ระบุ" เป็นตัวแปรภายในที่ไม่มีผลกับตัวแปรภายนอกฟังก์ชัน

การส่งผ่านโดยค่า(By Value)

ตามปกติการส่งผ่านพารามิเตอร์ไปยังฟังก์ชันเป็นการส่งผ่านค่า การเปลี่ยนแปลงจะจำกัดภายในเฉพาะภายในฟังก์ชัน
ตัวอย่างฟังก์ชัน new_value () ที่ยอมให้เพิ่มค่า อาจจะเขียนคำสั่งดังนี้
<?php
function new_value($value, $increment= 1)
{
$value = $value + $increment;
}
$value = 10 ;
new_value($value);
echo "$value<br/>\n";
?>
คำสั่งนี้ใช้ไม่ได้ ผลลัพธ์จะเป็น "10" ค่าใหม่ของ $value ไม่มีการเปลี่ยนแปลง
สิ่งนี้เป็นเพราะกฎ scope คำสั่งนี้สร้างตัวแปรเรียกว่า $value เป็น 10 เมื่อเรียกฟังก์ชัน new_value () ตัวแปร $value ในฟังก์ชันได้รับการสร้างเมื่อเรียกฟังก์ชัน ค่า 1 ได้รับการเพิ่มให้กับตัวแปร ดังนั้นค่าของ $value คือ 11 ภายในฟังก์ชัน จนกระทั่งสิ้นสุดฟังก์ชัน แล้วกลับไปยังคำสั่งที่เรียกภายในคำสั่งนี้ ตัวแปร $value เป็นอีกตัวแปร global scope และไม่มีการเปลี่ยนแปลง

การส่งผ่านโดยการอ้างอิง (By Reference)

ตามตัวอย่างฟังก์ชัน new_value ถ้าต้องการให้ฟังก์ชันเปลี่ยนแปลงค่าได้ มีวิธีหนึ่งในการแก้ไขคือ ประกาศ $value ในฟังก์ชันเป็น global แต่หมายความว่าในการใช้ฟังก์ชันนี้ ตัวแปรที่ต้องการเพิ่มค่าต้องตั้งชื่อเป็น $value แต่มีวิธีดีกว่าคือ ใช้การส่งผ่านโดยการอ้างอิง
การอ้างอิงไปตัวแปรต้นทางแทนที่มีค่าของตัวเอง การปรับปรุงไปยังการอ้างอิงจะมีผลกับตัวแปรต้นทางด้วย
การระบุพารามิเตอร์ที่ใช้การส่งผ่านโดยการอ้างอิงให้วาง ampersand (&) หน้าชื่อพารามิเตอร์ในข้อกำหนดฟังก์ชัน
ตัวอย่าง new_value () ได้รับปรับปรุงให้มี 1 พารามิเตอร์ส่งผ่านโดยการอ้างอิงและทำงานได้อย่างถูกต้อง
<?php
function new_value(&$value, $increment=1)
{
$value = $value + $increment;
}
?>
คำสั่งทดสอบฟังก์ชัน ให้พิมพ์ 10 ก่อนการเรียก increment () และ 11 ภายหลัง
ในการส่งค่าโดยการอ้างอิงต้องส่งเป็นตัวแปรไม่สามารถกำหนดค่าคงที่โดยตรง

จำนวนตัวแปรของพารามิเตอร์

การส่งผ่านพารามิเตอร์ไปยังฟังก์ชันนั้น การควบคุมของ PHP ได้กำหนดฟังก์ชันจำนวนหนึ่งให้ยอมรับจำนวนตัวแปรของพารามิเตอร์ ได้แก่ func_num_args, func_get_arg และ func_get_args
func_num_args() บอกจำนวนพารามิเตอร์ไปยังฟังก์ชันที่เรียก func_get_arg() แสดงค่าของพารามิเตอร์ตามดัชนี และ func_get_args() ส่งออก array ของพารามิเตอร์
<?php
function show_pass_value()
{
$idx = count(func_get_args());
echo " จำนวนพารามิเตอร์ $idx <br/>\n";

if ($idx > 0)
    echo ">> ใช้ฟังก์ชัน func_get_arg<br/>\n";

for ($i = 0 ; $i < $idx; $i++)
{

echo " พารามิเตอร์ที่ $i ค่า: ". func_get_arg($i)."<br/>\n";
}
if ($idx > 0)
    echo ">> ใช้ฟังก์ชัน func_get_args<br/>\n";

$params = func_get_args();
foreach ($params as $index => $val)
{

echo " พารามิเตอร์ที่ $index ค่า: $val<br/>\n";
}
echo " *********<br/>\n";
}
$x = 4 ;
show_pass_value("one", "two", 3 , $x, " ห้า" , " หก") ;
show_pass_value();
?>
ผลลัพธ์
จำนวนพารามิเตอร์ 6
>> ใช้ฟังก์ชัน func_get_arg
พารามิเตอร์ที่ 0 ค่า: one
พารามิเตอร์ที่ 1 ค่า: two
พารามิเตอร์ที่ 2 ค่า: 3
พารามิเตอร์ที่ 3 ค่า: 4
พารามิเตอร์ที่ 4 ค่า: ห้า
พารามิเตอร์ที่ 5 ค่า: หก
>> ใช้ฟังก์ชัน func_get_args
พารามิเตอร์ที่ 0 ค่า: one
พารามิเตอร์ที่ 1 ค่า: two
พารามิเตอร์ที่ 2 ค่า: 3
พารามิเตอร์ที่ 3 ค่า: 4
พารามิเตอร์ที่ 4 ค่า: ห้า
พารามิเตอร์ที่ 5 ค่า: หก
*********
จำนวนพารามิเตอร์ 0
*********

Scope

เมื่อต้องการใช้ตัวแปรภายในไฟล์ที่รวม ต้องมีการประกาศตัวแปรเหล่านั้นก่อนประโยคคำสั่ง require () หรือ include () แต่เมื่อใช้ฟังก์ชันจะเป็นการส่งผ่านตัวแปรเชิงประจักษ์เหล่านั้นไปยังฟังก์ชัน บางส่วนเป็นเพราะไม่มีกลไกส่งผ่านตัวแปรเชิงประจักษ์ไปยังไฟล์ที่รวม และบางส่วนเป็นเพราะ scope ของตัวแปรของฟังก์ชันแตกต่างกัน
การควบคุม scope ของตัวแปรเป็นการทำให้ตัวแปรมองเห็นได้ ใน PHP มีกฎตั้งค่า scope ดังนี้
  • การประกาศตัวแปรภายในฟังก์ชันอยู่ใน scope จากประโยคคำสั่งซึ่งตัวแปรให้รับการประกาศภายในวงเล็บปีกกา สิ่งนี้เรียกว่า function scope ตัวแปรเรียกว่า local variable
  • การประกาศตัวแปรภายนอกฟังก์ชันอยู่ใน scope จากประโยคคำสั่งซึ่งตัวแปรได้รับการประกาศที่สิ้นสุดแต่ไม่ใช้ภายในฟังก์ชัน สิ่งนี้เรียกว่า global scope ตัวแปรเรียกว่า global variable
  • การใช้ประโยคคำสั่ง require () และ include () ไม่มีผลกับ scope ถ้าประโยคคำสั่งได้รับการใช้ภายในฟังก์ชัน ประยุกต์ด้วย function scope ถ้าไม่ได้อยู่ภายในฟังก์ชัน ประยุกต์ด้วย global scope
  • คีย์เวิร์ด global สามารถระบุได้เองเพื่อกำหนดหรือใช้ตัวแปรภายในฟังก์ชันให้มี scope เป็น global
  • ตัวแปร สามารถลบโดยการเรียก unset ($variable_name) และตัวแปรที่ unset จะไม่มี scope
  • ตัวแปรระดับ superglobal สามารถเข้าถึงได้ทุกส่วนในสคริปต์

ตัวแปรระดับฟังก์ชัน

ตัวแปรระดับฟังก์ชันหรือ local variable เป็นการประกาศเพื่อใช้เฉพาะภายในฟังก์ชัน ไม่สามารถเรียกจากภายนอกฟังก์ชันได้
<?php
$newline = <<<NLSTRING
<br/>\n
NLSTRING;
$var_global = 10 ;
function show_value()
{
global $newline;
$var_local= 75 ;
echo "\$var_local 1: $var_local";
echo $newline;
}
show_value();
echo "\$var_global : $var_global";
echo $newline;
echo "\$var_local 2: $var_local";
echo $newline;
?>
ผลลัพธ์
$var_global 1 :
$var_local 1: 75
$var_global 2: 10
$var_local 2:
ตามตัวอย่างนี้ ตัวแปรระดับฟังก์ชัน $var_local ไม่สามารถแสดงผลในการพิมพ์ภายนอกฟังก์ชัน show_value() และ $var_global ที่เป็นตัวแปรระดับ global ไม่สามารถแสดงผลภายใน show_value() เพราะมี scope ต่างกัน

ตัวแปรระดับ global

ถ้าต้องการนำตัวแปรระดับ global มาใช้ภายในฟังก์ชันต้องประกาศด้วยคีย์เวิร์ด global ก่อนประโยคคำสั่งที่ใช้ตัวแปรนั้น ตัวอย่าง ฟังก์ชัน show_value() ใช้ $newline จากภายนอกฟังก์ชัน
global $newline;

ตัวแปรสถิตย์

การประกาศตัวแปรสถิตย์ใช้ คีย์เวิร์ด static เมื่อมีการเรียกใช้ฟังก์ชัน โปรแกรมจะกำหนดค่าตัวแปรตามที่ระบุเพียงครั้งเดียว ถ้าเรียกซ้ำอย่างต่อเนื่องค่านี้จะเปลี่ยนแปลงตามการคำนวณ
<?php
function increment()
{
static $increase = 5 ;
$increase++;
echo $increase."<br/>\n";
}
$end = 5 ;
for ($i = 1 ; $i < $end; $i++)
    increment();
?>
ผลลัพธ์
6
7
8
9
ค่าของตัวแปรสถิตย์ได้รับการตั้งทุกครั้งเมื่อเรียกใช้ในครั้งต่อไป

การส่งออกค่าจากฟังก์ชัน

การส่งค่าออกจากฟังก์ชันใช้คีย์เวิร์ด return เช่นเดียวกับการออกจากฟังก์ชันได้ ถ้าไม่มีการระบุส่งออกฟังก์ชันจะส่งค่า NULL
ตัวอย่าง ฟังก์ชัน get_larger () สาธิตการส่งออกค่า
<?
function get_larger($x=NULL, $y=NULL)
{
if (!isset($x) || !isset($y))
    return " ไม่มีการส่งค่า" ;
if ($x > $y)
    return $x;
else if ($x < $y)
    return $y;
else
    return " ค่าเท่ากัน" ;
}
$sends = array();
$sends[0] = array('x' =>5);
$sends[1] = array('x' =>9, 'y'=>3);
$sends[2] = array('x' =>5, 'y'=>8);
$sends[3] = array('x' =>4, 'y'=>4);
foreach ($sends as $send)
{
echo "x = ".$send['x']." y = ".$send['y']." : ค่า - > "
.get_larger($send['x'], $send['y']);
echo "<br/>\n";
}
?>
ผลลัพธ์
x = 5 y = : ค่า - > ไม่มีการส่งค่า
x = 9 y = 3 : ค่า - > 9
x = 5 y = 8 : ค่า - > 8
x = 4 y = 4 : ค่า - > ค่าเท่ากัน
ฟังก์ชันที่ทำงานอาจเดียว แต่ไม่จำเป็นต้องส่งออกค่า มักจะส่งออก TRUE หรือ FALSE เพื่อระบุความสำเร็จหรือล้มเหลว ค่า TRUE หรือ FALSE สามารถได้รับการแสดงแทนด้วย 1 หรือ 0

Recursion

recursion ได้รับการสนับสนุนใน PHP ฟังก์ชันชนิดนี้เป็นการเรียกตัวเองและเป็นประโยชน์กับการบังคับโครงสร้างข้อมูลไดนามิคส์ เช่น รายการเชื่อมโยงและโครงสร้างต้นไม้ (tree)
โปรแกรมประยุกต์เว็บจำนวนไม่มากต้องการโครงสร้างข้อมูลซับซ้อนมากและจำกัดการใช้ เนื่องจาก recursion ช้ากว่าและใช้หน่วยความจำมากกว่าการทำงานวนรอบ ดังนั้นควรเลือกการทำงานแบบวนรอบปกติ ถ้าเป็นไปได้
ตัวอย่างการประยุกต์แบบย้อนกลับตัวอักษร
<?php
function word_reverse_r($str)
{
if (strlen($str)>0)
    word_reverse_r(substr($str, 1));

echo substr($str, 0, 1);
return;
}
function word_reverse_i($str)
{
for ($i=1; $i<=strlen($str); $i++)
{

echo substr($str, -$i, 1);
}
return;
}
?>
รายการคำสั่งของ 2 ฟังก์ชันนี้จะพิมพ์ข้อความย้อนกลับ ฟังก์ชัน word_reverse_r เป็น recursion ฟังก์ชัน word_reverse_i เป็นการวนรอบ
ฟังก์ชัน word_reverse_r ใช้ข้อความเป็นพารามิเตอร์ เมื่อมีการเรียกฟังก์ชันนี้ จะเกิดการเรียกตัวเองแต่ละครั้งส่งผ่านตัวอักษรที่ 2 ไปถึงตัวอักษรสุดท้าย
การเรียกฟังก์ชันแต่ละครั้งจะทำสำเนาใหม่ของคำสั่งในหน่วยความจำของแม่ข่าย แต่ด้วยพารามิเตอร์ต่างกัน ดังนั้นจึงเหมือนกับการเรียกคนละฟังก์ชัน



PHP เบื้องต้น

7. Object Oriented Programming

ภาษาโปรแกรมสมัยใหม่ มักจะสนับสนุนหรือต้องการวิธีแบบ Object oriented programming เพื่อพัฒนาซอฟต์แวร์ ซึ่ง PHP สามารถพัฒนาโปรแกรมประยุกต์ประเภทนี้ได้

ject oriented programming (OOP) มีจุดสำคัญคือ ความสามารถสร้างประเภทข้อมูลใหม่ที่มีข้อมูลและการทำงานร่วมกัน การพัฒนาแบบนี้ใช้การจัดความสัมพันธ์และคุณสมบัติของอ๊อบเจคในระบบในปฏิบัติงาน

Class และอ๊อบเจค

ในบริบทซอฟต์แวร์ OOP อ๊อบเจคสามารถเป็นสิ่งของหรือแนวคิดได้แก่ วัตถุทางกายภาค เช่น โต๊ะ ลูกค้า หรือวัตถุทางแนวคิดที่มีอยู่ในซอฟต์แวร์ เช่น พื้นที่ป้อนข้อความ ไฟล์ โดยทั่วไปความสนใจส่วนมากในวัตถุทางแนวคิด รวมถึงวัตถุในโลกจริงที่ต้องการนำเสนอในซอฟต์แวร์
ซอฟต์แวร์ OOP เป็นชุดของอ๊อบเจคเก็บคุณลักษณะและปฏิบัติการ โดย คุณลักษณะคือ คุณสมบัติหรือตัวแปรที่สัมพันธ์กับอ๊อบเจค ปฏิบัติการคือ เมธอดการกระทำหรือฟังก์ชันที่อ๊อบเจคสามารถทำการปรับปรุงตัวเองหรือผลกระทบภายนอก
ซอฟต์แวร์แบบนี้ สนับสนุนและช่วยการห่อหุ้ม (encapsulation) ที่เรียกว่าการซ่อนข้อมูล ส่วนสำคัญคือ การเข้าถึงข้อมูลภายในอ๊อบเจคมีให้เฉพาะการผ่านปฏิบัติการของอ๊อบเจคที่เรียกว่าอินเตอร์เฟซของอ ๊ อบเจค
class แสดงแทนชุดของอ๊อบเจคที่อาจจะแปรผันจากแต่ละอ๊อบเจค แต่ต้องมีผลร่วมกัน ถึงแม้ว่าค่าของคุณลักษณะเหล่านั้นจะแปรผันตามอ๊อบเจค ตัวอย่าง จักรยาน สามารถคิดเป็น class ของอ๊อบเจคที่อธิบายจักรยานหลายประเภทด้วยส่วนการทำงานรวมหรือคุณลักษณะ เช่น 2 ล้อ สี ขนาด และปฏิบัติการ เช่น การเคลื่อนย้าย

Polymorphism

ภาษา Object oriented programming ต้องสนับสนุน polymorphism ซึ่งหมายความว่า แต่ละ class สามารถมีพฤติกรรมต่างสำหรับปฏิบัติการเดียวกัน เช่น มี class รถยนต์ และ class จักรยาน ทั้งคู่มีปฏิบัติการเคลื่อนย้ายต่างกัน วัตถุในโลกจริงมีปัญหาน้อย อย่างไรก็ตาม ภาษาโปรแกรมไม่คิดเหมือนโลกจริง ดังนั้นภาษาต้องสนับสนุน polymorphism เพื่อทราบถึงปฏิบัติการที่ใช้โดยอ๊อบเจคเฉพาะ
polymorphism มีพฤติกรรมมากกว่าอ๊อบเจคใน PHP เฉพาะฟังก์ชันสมาชิกของ class สามารถเป็น polymorphism เปรียบเทียบกับโลกจริงคือ กริยาในภาษาธรรมชาติ ซึ่งเทียบเท่ากับฟังก์ชันสมาชิก พิจารณาการใช้จักรยานในชีวิตจริง คือ การทำความสะอาด การแยกชิ้น การซ่อม ทาสี เป็นต้น
การอินเฮอริต ยอมให้สร้างความสัมพันธ์ตามลำดับชั้น ระหว่าง class ด้วยการใช้ subclass โดย subclass ทำอินเฮอริต คุณลักษณะและปฏิบัติการจาก superclass
การอินเฮอริต ทำให้สามารถสร้างและเพิ่มไปยัง class ที่มีอยู่ จาก class ฐานอย่างง่าย สามารถทำได้มาจากให้ซับซ้อนมากขึ้นและเจาะจง class ตามความต้องการ สิ่งนี้ทำให้ใช้คำสั่งใหม่ได้ และเป็นข้อได้เปรียบสำคัญของ object oriented programming



PHP เบื้องต้น > Object Oriented Programming

การประยุกต์เบื้องต้น

การเรียนรู้โปรแกรมแบบ OOP เริ่มต้นจากการสร้างและทำงาน class ในฐานะอ๊อบเจคที่ประกอบด้วยคุณสมบัติ (หรือคุณลักษณะ) และปฏิบัติการ (หรือเมธอด)

Class

การประกาศ class ใช้คีย์เวิร์ด class รายละเอียดของ class ได้รับการหุ้มในวงเล็กปีกกา ({ })
<?php
class myclass
{

// รายละเอียด รวมถึง คุณสมบัติ และเมธอด เป็นต้น
}
?>
class นี้ให้ชื่อว่า myclass
class สร้างคุณลักษณะเป็นการประกาศตัวแปรภายในข้อกำหนด class ด้วยคีย์เวิร์ด var และการสร้างปฏิบัติการใช้การประกาศฟังก์ชัน
ตัวอย่างการสร้าง Employee class ที่ประกอบ 4 คุณลักษณะ ใน PHP สามารถสร้างค่าเริ่มต้นได้
<?php
class Employee
{

public $id;
public $firstname = “unknown”;
public $lastname;
public $sex = 1;
}
?>

Instance

การสร้างอ๊อบเจคที่ใช้ทำงานด้วยที่เรียกว่า instance ของอ๊อบเจค การสร้างใช้คีย์เวิร์ด new ต้องมีการระบุ class ที่อ๊อบเจคจะเป็น instance
<?php
$emp = new Employee();
?>

คุณลักษณะ

การเข้าถึงตัวแปรสมาชิกใช้ ชื่อ instance กับ -> operator ตามด้วยชื่อตัวแปรสมาชิก
<?php
$emp_name = $prod->firstname;
?>
ภายใน class การเข้าถึงตัวแปรสมาชิกใช้ -> operator และเข้าถึงด้วยพอยเตอร์พิเศษเรียกว่า $this
<?php
class Employee
{

public firstname;

// คำสั่งอื่น
$new_name = $this->firstname;
}
?>

การตั้งค่าให้กับตัวแปรสมาชิก
<?php
$emp->firstname = " อัศวิน ";
?>

เมธอด

ชื่อฟังก์ชันที่เป็นเมธอดต้องไม่ซ้ำกัน ตัวอย่างการสร้างเมธอดดูได้ฟังก์ชัน get_firstname() สำหรับการอ่านชื่อพนักงานและฟังก์ชัน set_firstname สำหรับการตั้งชื่อพนักงาน
การเรียกเมธอดของ class เหมือนกับการเรียกคุณลักษณะของ class ถ้าเมธอดต้องการพารามิเตอร์ให้วางไว้ในวงเล็บ และระบุชื่อเจ้าของอ๊อบเจค
<?php
$new_emp = new Employee();
$first_name = $new_emp->get_firstname();
$new_emp-> set_firstname($new_name);
?>
การเริ่มต้นและทำความสะอาดอ๊อบเจค
เมื่อเริ่มต้นอ๊อบเจค Employee จากการสร้าง instance ของ Employee class สิ่งที่ลำบากคือการเริ่มค่า ตามตัวอย่างนี้
< ?php
$emp = new Employee();
$emp->id = "A321500"
$emp->name = " สุพจน์ ";
// และอื่นๆ ...
?>
การแก้ไขปัญหานี้ทำได้ด้วยแนวคิด constructor

Constructor

constructor เป็นวิธีการประมวลผลเมื่อ instance ใหม่ได้รับการสร้างขึ้น โดย constructor รับพารามิเตอร์ที่ส่งผ่าน new operator ด้วยการวางไว้ในวงเล็บหลังชื่อ class
<?php
class Employee
{

// ตัวแปรสมาชิก
public function __construct ($m_empid, $m_empfname, $m_emplname, $m_sex, $m_salary)
{

$this->id = $m_empid;
$this->firstname = $m_empfname;
$this->lastname = $m_emplname;
$this->salary = $m_salary;
$this->sex = $m_sex;
}
// คำสั่งอื่น
}
?>

การประกาศ constructor ให้กำหนดเป็น __construct ( เส้นใต้หรือ underscore 2 ตัวติดกัน) ถึงแม้ว่าสามารถเรียก constructor ได้เอง แต่วัตถุประสงค์หลักคือ การเรียกอย่างอัตโนมัติ เมื่ออ๊อบเจคได้รับการสร้างคำสั่งต่อไปประกาศ class ด้วย constructor

Destructor

เมธอด destructor ใช้ลบอ๊อบเจค การกำหนดใน PHP ผ่านฟังกชัน __destruct ถ้าไม่ได้กำหนดไว้ PHP จะดำเนินการทำความสะอาดและทำงานต่อ
<?php
// คำสั่งอื่น...
public function __destruct()
{

// วางคำสั่งทำความสะอาด
}
?>

Visibility

PHP ได้วิธีการควบคุมการดูหรือปรับปรุงข้อมูลกับตัวแปรสมาชิก รวมถึงการเรียกฟังก์ชันสมาชิก ทำให้กำหนดวิธีการดูข้อมูล การเก็บหรือแก้ไขข้อมูลได้ visibility มี 3 modifier คือ
  • public ทุกคนสามารถอ่านและปรับปรุงตัวแปรสมาชิกนี้ หรือเรียกเมธอดนี้ รวมทั้งสามารถใช้ได้โดยคำสั่งภายนอก คำสั่งภายใน class หรือ class ที่ขยายการทำงานกับ class ที่ระบุ
  • private เฉพาะคำสั่งภายใน class นี้สามารถอ่านหรือปรับปรุงตัวแปรสมาชิก private หรือเรียกฟังก์ชันสมาชิก private ส่วนคำสั่ง, class และ class ที่ขยายการทำงานกับ class นี้ไม่สามารถใช้รายการ private นี้ได้
  • protected คำสั่งภายนอกและ class อื่นที่ไม่มีความสัมพันธ์กับ class ที่กำหนดไม่สามารถอ่านและเขียนตัวแปรสมาชิก protected ได้ หรือเรียกฟังก์ชันสมาชิก protected แต่ class ที่ขยายการทำงานกับ class นี้ได้รับอนุญาตให้เข้าถึงหรือเรียกได้
ถ้าไม่ต้องการบุคคลอื่นแก้ไขข้อมูลให้เปลี่ยน visibility จาก public เป็น private หรือ protected แต่ให้คำสั่งภายนอกสามารถดูได้
<?php
class Employee
{

protected $id;
protected $firstname;
protected $lastname;
protected $sex;
protected $salary;

public function __construct ($m_empid, $m_empfname, $m_emplname, $m_sex, $m_salary)
{

$this->id = $m_empid;
$this->firstname = $m_empfname;
$this->lastname = $m_emplname;
$this->salary = $m_salary;
$this->sex = $m_sex;
}
public function __destruct()
{

// clean up
}
public function get_EmployeeID()
{

return $this->id;
}
public function get_EmployeeFullName()
{

return $this->firstname." ".$this->lastname;
}
//
// ฟังก์ชันอื่นๆ
//

public function get_EmployeeSex()
{

if ($this->sex == 1)
    return "Male";
else if ($this->sex == 2)
    return "Female";
else
    return "Unknow";
}
}
?>

ค่าคงที่และข้อมูลสถิตย์

ในบางกรณีอาจจะมีการกำหนดและใช้ค่าคงที่กับอ๊อบเจค ดังนั้นเรียนรู้วิธีการติดต่อกับค่าคงที่ ตัวแปรสถิตย์ (static variable) และเมธอดสถิตย์ (static method)

ค่าคงที่ของ Class

การกำหนดค่าคงที่ของ class
<?php
class Employee
{

const THAI = 1;
const FOREIGN = 2;

// คำสั่งอื่น...
}
?>
ค่าคงที่ไม่มีความสัมพันธ์กับอ๊อบเจค จึงไม่สามารถใช้ -> operator ได้ การเข้าถึงขึ้นกับแหล่งของค่าคงที่
•  ภายนอก class การเข้าถึงค่าจากภายนอก class ให้ระบุเริ่มต้นชื่อ class ตามด้วย scope resolution operator ที่เป็น colon คู่ (::) และชื่อค่าคงที่
<?php
$emp = new Employee("321500", " สุพจน์" , " แสงไพบูลย์" , 1, 15000, Employee::THAI);
?>
•  ภายใน class การเข้าถึงจากภายใน class ใช้คีย์เวิร์ด self เพื่อบอกให้ PHP มองหาใน class ปัจจุบันตามด้วย scope resolution operator และชื่อค่าคงที่
<?php
class Employee
{

// คำสั่งอื่น...
public function get_EmployeeNation()
{

if ($this->nation == self::THAI)
    return " ไทย" ;
else if ($this->nation == self::FOREIGN)
    return " ต่างชาติ" ;
else
    return "Unknow";
}
}
?>

ตัวแปรสมาชิกสถิตย์

ความต้องการข้อมูลบางอย่างสัมพันธ์กับทั้ง class ของอ๊อบเจค แต่ข้อมูลนี้ไม่ตายตัว ตัวแปรสมาชิกแบบนี้สามารถสร้างให้เป็น global กับทั้ง class แต่ไม่ใช่ instance ตัวแปรสมาชิกแบบนี้ PHP เรียกว่าตัวแปรสมาชิกสถิตย์ ( Static member variable) ประกาศด้วยคีย์เวิร์ด static
การเข้าถึงตัวแปรสมาชิกสถิตย์เหมือนกับการเข้าถึงค่าคงที่จากภายใน class คือ ใช้คีย์เวิร์ด self ตามด้วย ด้วย scope resolution operator และชื่อตัวแปรสมาชิก
<?php
class Employee
{

private static $num_instance = 0;
public function __construct ($m_empid, $m_empfname, $m_emplname, $m_sex, $m_salary, $m_nation)
{

$this->id = $m_empid;
$this->firstname = $m_empfname;
$this->lastname = $m_emplname;
$this->salary = $m_salary;
$this->sex = $m_sex;
$this->nation = $m_nation;

self:: $num_instance++;
echo " การสร้าง instance จำนวน ".self:: $num_instance."<br/>\n";
}
}
?>
ตัวแปรสมาชิกสถิตย์สามารถกำหนดระดับ scope นอกจาก public และไม่ใช่อ่านอย่างเดียว
ตัวแปรสมาชิกแบบนี้จะตั้งค่าใหม่ที่สคริปต์ประมวลผลใหม่ ในกรณีการนับตามตัวอย่างถ้าเป็นการเรียกคนละครั้งจะเป็น 1 แต่การป้อนต่อเนื่องโดยไม่ได้ออกจากสคริปต์จึงจะนับต่อเนื่องได้

เมธอดสถิตย์

ความต้องการปฏิบัติการกับระเภทงานที่ไม่จำเป็นต้องเจาะจง instance แต่ปฏิบัติงานตามประเภทงาน ตัวอย่าง ต้องการสร้างเมธอดบน Employee class ที่สร้างอ๊อบเจค Employee จำนวนหนึ่ง
การประกาศเมธอดใช้คีย์เวิร์ด static
<?php
class Employee
{

// คำสั่งอื่น...
public static function search_employee($search_value)
{

// คำสั่งค้นหา... กำหนดตาม $search_value
}
}
?>


PHP เบื้องต้น > Object Oriented Programming

การขยายอ๊อบเจค

Object oriented programming มีความสามารถในการห่อหุ้มข้อมูลเป็นประเภทข้อมูลใหม่ เมื่อมีการสร้าง Employee class ขึ้นมา ที่อินเฮอริตคุณสมบัติของพนักงานขึ้นมาได้

อินเฮอริต

ในทางปฏิบัติ ข้อมูลหลายประเภทอาจจะมีจำกัดขอบเขตผู้เข้าถึง เช่น ระบบจ่ายเงินเดือน ระบบโบนัส สิ่งเหล่านี้ไม่จำเป็นต้องเข้าสู่ระบบรวม แต่สามารถแบ่งส่วนออกมาได้
ถ้า class เป็น subclass ของอีก class สามารถใช้คีย์เวิร์ด extend เพื่อระบุการขยาย คำสั่งต่อไปนี้สร้าง Bonus class ที่อินเฮอริตจาก Employee class
<?php
class Bonus Extends Employee
{

protected static $bonus_rate = 1;
}
?>
การอินเฮอริตทำงานเพียง 1 ทิศทาง subclass หรือลูกอินเฮอริตส่วนการทำงานจากแม่หรือ class ฐาน แต่แม่ไม่สามารถใช้ส่วนการทำงานของลูก

Overriding

การให้ class ลูกสามารถปรับปรุงข้อมูลจากการ class ฐานหรือแม่ ตัวอย่าง Bonus class สามารถเพิ่มอัตราโบนัสเป็นพารามิเตอร์ PHP ยอมให้ทำได้และใช้ constructor จาก class ฐานด้วยการใช้คีย์เวิร์ด parent โดยรวมกับ scope resolution operator เพื่อเรียกเมธอดจาก class ฐาน วิธีนี้เรียกว่า Overriding เมธอดจาก class ฐาน ได้รับการแทนที่โดยเมธอดใหม่ของ class
<?php
class Bonus Extends Employee
{

protected $bonus_rate = 0.5;
public function __construct($m_empid, $m_empfname, $m_emplname, $m_sex, $m_salary, $m_nation, $m_bonus)
{

parent::__construct($m_empid, $m_empfname,
$m_emplname, $m_sex, $m_salary, $m_nation);
$this->bonus_rate = $m_bonus;
}
}
?>
เมธอด destructor ควรได้รับ overriding
<?php
public function __destruct()
{

// ควรเรียก destructor จากแม่
parent::__destruct();
}
?>
เมื่อ Bonus class ทำงานได้แล้ว ควรมีการปรับปรุงเมธอด get_EmployeePayroll() ใหม่ด้วยการ overriding จาก class ฐาน
<?php
public function get_EmployeePayroll()
{

return parent::get_EmployeeSalary()*(1+ $this->bonus_rate);
}
?>

การทำให้ Class ทำงานเหมือนกัน

หลักการสำคัญของ Object oriented programming ประการหนึ่งคือ ทำให้อินเตอร์เฟซเหมือนกันหรือ polymorphism ดังนั้นจึงต้องทำให้คำสั่งได้รับการเปลี่ยนแปลงนอกเหนือการควบคุม
โครงสร้างตามลำดับชั้นของ Class
โครงสร้างตามลำดับของสามารถขยายตามแนวดิ่งได้ด้วยอินเฮอริตได้ และสามารถปรับปรุงเมธอดจาก class ฐานด้วยการ overriding ได้สำหรับความเหมาะสมในการทำงาน ดังนั้นเมธอดบน class ฐานควรทำหน้าที่เป็นต้นแบบ (template) การกำหนดนี้ทำได้ด้วยการใช้คีย์เวิร์ด abstract
<?php
abstract class Employee
{

// คำสั่งอื่น...
}
?>

การป้องกันอินเฮอริตและ Overriding

บางเมธอดหรือ class อาจจะเกิดจากโครงสร้างตามลำดับชั้นของอ๊อบเจค ตัวอย่าง ป้องกันไม่ให้บุคคลทั่วไป overriding เมธอด get_EmployeeID ใน Employee class
การป้องกันใช้ คีย์เวิร์ด final
<?php
abstract class Employee
{

// คำสั่งอื่น...
final public function get_EmployeeID()
{

return $this->id;
}
}
?>




ไม่มีความคิดเห็น:

แสดงความคิดเห็น