ใน PHP 4 โดยปกติแล้วตัวแปรจะถูกประกาศโดยใช้ var ในขณะที่ใน PHP 5 คุณสามารถใช้คุณสมบัติของการเขียนโปรแกรมเชิงวัตถุ (OOP) เพื่อปรับแต่งการมองเห็นข้อมูล กล่าวคือ การมองเห็นที่นี่จะคล้ายกับขอบเขตของตัวแปรมาก แต่มีกลไกการควบคุมที่ดีกว่า มีตัวแก้ไขการมองเห็นสามประเภท:
สาธารณะ (ค่าเริ่มต้น) -- ตัวแปรสามารถเข้าถึงได้หรือแก้ไขในขอบเขตส่วนกลาง
Protected--ตัวแปรสามารถเข้าถึงได้หรือแก้ไขภายในคลาสเองและคลาสที่ได้รับโดยตรง (โดยใช้คำสั่งขยาย)
ส่วนตัว - ตัวแปรสามารถเข้าถึงได้หรือแก้ไขภายในคลาสเท่านั้น
เช่นเดียวกับการใช้งานอินเทอร์เฟซ การละเมิดกฎเหล่านี้ในโปรแกรมจะนำไปสู่ข้อผิดพลาดร้ายแรง และเช่นเดียวกับอินเทอร์เฟซ สิ่งเหล่านี้มีอยู่เพื่อความสะดวกของโปรแกรมเมอร์เท่านั้น แต่ไม่ได้หมายความว่าสามารถละเว้นได้ การระบุการมองเห็นของตัวแปรสมาชิกคลาสบางตัวสามารถปกป้องข้อมูลภายในออบเจ็กต์จากอิทธิพลภายนอก
สมมติว่ามีคลาส MySqlDB และตัวแปร $link ถูกประกาศเป็นส่วนตัว ซึ่งหมายความว่าตัวแปรนี้สามารถเข้าถึงได้จากภายในออบเจ็กต์โดยใช้ตัวแปร $this เท่านั้น วิธีนี้จะช่วยป้องกันการเขียนทับโดยไม่ได้ตั้งใจโดยออบเจ็กต์หรือฟังก์ชันอื่นนอกคลาสที่นี่ เราจะใช้แอตทริบิวต์การมองเห็นเพื่อช่วยเราสร้างวัตถุแบบสอบถาม
คุณสามารถนึกถึงแบบสอบถามเป็นเอนทิตีแยกต่างหากที่สามารถดำเนินการและส่งกลับผลลัพธ์ได้ ระบบฐานข้อมูลบางระบบยังมีขั้นตอนการจัดเก็บคล้ายกับฟังก์ชันต่างๆ โดยจะจัดเก็บคำสั่งแบบสอบถามและยอมรับพารามิเตอร์ที่เกี่ยวข้องเมื่อถูกเรียก อย่างไรก็ตาม MySQL ไม่ได้มีฟังก์ชันที่คล้ายกันก่อนเวอร์ชัน 5.1 และระบบการจัดการฐานข้อมูลบางประเภทก็เช่นกัน
ในบทความนี้ คุณลักษณะทั้งสองข้างต้นจะถูกรวมเข้ากับวัตถุแบบสอบถามของตัวอย่าง ตัวอย่างจะจำลองขั้นตอนการจัดเก็บพื้นฐานและบันทึกตัวชี้ผลลัพธ์ภายใน ในตอนนี้ โฟกัสอยู่ที่การดำเนินการค้นหาจากออบเจ็กต์ ซึ่งคุณสามารถเรียกใช้ฟังก์ชัน query() ของออบเจ็กต์ MySqlDB ได้
ฟังก์ชั่นสาธารณะต่อไปนี้สามารถกำหนดได้ในวัตถุแบบสอบถาม:
__construct()--ตัวสร้างยอมรับพารามิเตอร์ที่มีการอ้างอิงอินสแตนซ์ไปยังวัตถุที่ใช้อินเทอร์เฟซ DB
เตรียม()--ฟังก์ชันเตรียม() เริ่มต้นขั้นตอนการจัดเก็บแบบสอบถาม อาจมีตัวยึดตำแหน่งที่จำกัดตั้งแต่หนึ่งตัวขึ้นไป ซึ่งจะถูกส่งเป็นพารามิเตอร์ไปยังฟังก์ชันดำเนินการ () ตัวยึดตำแหน่งถูกกำหนดให้เป็นโคลอนที่เกี่ยวข้องกับจำนวนพารามิเตอร์ตามด้วยจำนวนเต็มและตัวอักษรที่เกี่ยวข้องกับประเภทพารามิเตอร์
แบบสอบถามแบบง่ายที่มีตัวยึดตำแหน่งจะมีลักษณะดังนี้:
SELECT col1,col2 FROM table_name WHERE col1=:1I
ดำเนินการ()--ฟังก์ชัน ดำเนินการ() จะดำเนินการแบบสอบถาม หากมีการเตรียมใช้งานก่อนกำหนดเป็นกระบวนงานที่เก็บไว้โดยฟังก์ชันเตรียม () พารามิเตอร์ใดๆ ที่ส่งผ่านจะถูกใช้เป็นพารามิเตอร์การดำเนินการของกระบวนงานที่เก็บไว้ มิฉะนั้น พารามิเตอร์แรกจะถูกใช้เป็นข้อความแบบสอบถามเท่านั้น ฟังก์ชันดำเนินการ () จะส่งกลับผลลัพธ์หลังจากดำเนินการค้นหา
คอมไพล์()--ฟังก์ชันคอมไพล์() คล้ายกับฟังก์ชันดำเนินการ() จริงๆ แล้ว คิวรีไม่ได้ถูกดำเนินการ แต่จะแทนที่ตัวยึดตำแหน่งทั้งหมดในสตริงการสืบค้น ยอมรับพารามิเตอร์ของโพรซีเดอร์ที่เก็บไว้ และส่งกลับเวอร์ชันที่คอมไพล์แล้ว ของแบบสอบถาม
สมาชิกที่ได้รับการคุ้มครอง
ดังที่ได้กล่าวไว้ข้างต้น แนวคิดเรื่องการมองเห็นสามารถใช้เพื่อซ่อนการทำงานภายในของออบเจ็กต์ เพื่อปกป้องความสมบูรณ์ของข้อมูลที่จำเป็นสำหรับการทำงานภายใน ตามที่อธิบายไว้ก่อนหน้านี้ ตัวชี้ผลลัพธ์ที่ส่งคืนโดยแบบสอบถามจะถูกบันทึกเป็นแอตทริบิวต์ที่มีการป้องกันถูกใช้ที่นี่เนื่องจากวัตถุแบบสอบถามฐานข้อมูลเฉพาะที่ได้รับจากวัตถุแบบสอบถามอาจโอเวอร์โหลดฟังก์ชันหลักบางอย่าง
พอจะ
เจาะลึกถึงทฤษฎีโค้ด
แล้ว
เรามาเริ่มเขียนโค้ดกัน
ก่อน
-
-
*บันทึกการอ้างอิงไปยังออบเจ็กต์ที่ใช้อินเทอร์เฟซ DB
-
ป้องกัน $db;
/**
*หากเป็นขั้นตอนการจัดเก็บ ให้ตั้งค่าเป็นจริง
-
ป้องกัน $stored_procedure = false
;
*บันทึกแบบสอบถามโดยลบสตริงทั้งหมดแล้ว
-
แบบสอบถาม $ ส่วนตัว
/**
* ใช้เพื่อจับคู่เครื่องหมายคำพูดใน SQL
-
ส่วนตัวคงที่ $QUOTE_MATCH = "/(".*(?db = $db;
}
เตรียมฟังก์ชั่นสาธารณะ($แบบสอบถาม)
-
$นี่->stored_procedure = จริง;
}
คอมไพล์ฟังก์ชันสาธารณะ($args)
{}
ฟังก์ชั่นสาธารณะดำเนินการ ($ แบบสอบถาม)
-
}
ฟังก์ชันการจัดเตรียม
คือเทมเพลตในตัวอย่างที่ 1 สิ่งแรกที่คุณต้องทำคือสร้างฟังก์ชันการจัดเตรียม() เพื่อให้แน่ใจว่าอักขระที่ไม่มีเครื่องหมายคำพูดจะถูกแยกวิเคราะห์เป็นตัวยึดตำแหน่งโดยไม่ตั้งใจ ฟังก์ชันควรลบอักขระทั้งหมดในสตริงและ เก็บไว้ในอาร์เรย์ชั่วคราว ตัวสตริงจะถูกแทนที่ด้วยตัวยึดตำแหน่ง ซึ่งโดยปกติจะรับรู้ว่าเป็นลำดับสตริงที่ไม่ควรปรากฏในคำสั่ง SQL ในระหว่างการรวบรวมแบบสอบถาม ตัวยึดขั้นตอนจะถูกแทนที่ก่อน จากนั้นสตริงจะถูกใส่กลับเข้าไปในแบบสอบถาม ซึ่งทำได้ผ่านฟังก์ชัน preg_replace() และฟังก์ชันการเรียกกลับตัวช่วยอื่นที่ใช้เป็นฟังก์ชัน preg_replace()
ตัวอย่างที่ 2: ฟังก์ชันเตรียม()
/**
* เตรียมแบบสอบถามเป็นขั้นตอนการจัดเก็บ
* @param string $query ข้อความแบบสอบถามที่เตรียมไว้
* @return เป็นโมฆะ
-
เตรียมฟังก์ชั่นสาธารณะ ($ แบบสอบถาม)
-
$นี่->stored_procedure = จริง;
$this->quote_store = array(); // ล้างเครื่องหมายคำพูด $this->query = preg_replace(self::$QUOTE_MATCH, '$this->sql_quote_replace("1"?"1":'2')', $ แบบสอบถาม);
}
ฟังก์ชันส่วนตัว sql_quote_replace($match)
-
$number = count($this->query_strings);
$this->query_strings[] = $match;
กลับ "$||$$number";
}
โปรดทราบว่าการใช้แอตทริบิวต์ QUOTE_MATCH แบบคงที่แบบส่วนตัว รวมถึงแอตทริบิวต์ quote_store และฟังก์ชัน sql_quote_replace() เมื่อเปรียบเทียบกับการป้องกัน การกำหนดให้เป็นส่วนตัวที่นี่ทำให้มั่นใจได้ว่าคลาสย่อยใด ๆ ที่แทนที่วิธีการเตรียม () ของคลาสเคียวรีจะใช้กลไกของตัวเองในการลบเครื่องหมายคำพูด
ฟังก์ชั่นคอมไพล์
ขั้นตอนต่อไปคือการสร้างฟังก์ชั่นคอมไพล์() และดำเนินการ()
ฟังก์ชันคอมไพล์() ดังแสดงในตัวอย่างที่ 3 มีฟังก์ชันต่อไปนี้:
·จำนวนพารามิเตอร์ที่ยอมรับคือตัวแปร (เช่น พารามิเตอร์ตัวแปร) ซึ่งจะตรงกับตัวยึดตำแหน่งในการสืบค้น
· ตรวจสอบว่าตัวยึดตำแหน่งเป็นประเภทข้อมูลที่ถูกต้องและแทนที่ด้วยค่าในพารามิเตอร์
·ส่งคืนแบบสอบถามเป็นสตริงแต่ไม่ต้องดำเนินการ
·หากวัตถุแบบสอบถามไม่ได้เตรียมใช้งานเป็นขั้นตอนการจัดเก็บโดยใช้ฟังก์ชันเตรียม () ข้อยกเว้นจะถูกส่งออกไป
ตัวอย่างที่ 3: ฟังก์ชันคอมไพล์()
/**
* ส่งคืนแบบสอบถามที่คอมไพล์แล้ว แต่ไม่ได้ดำเนินการ
* @param ผสม $args,... พารามิเตอร์การค้นหา
* @return string แบบสอบถามที่คอมไพล์แล้ว
-
คอมไพล์ฟังก์ชั่นสาธารณะ ($ params)
-
ถ้า (! $this->stored_procedure) {
Throw new Exception("ขั้นตอนการจัดเก็บยังไม่ได้รับการเตรียมใช้งาน!");
}
/* พารามิเตอร์การทดแทน*/
$params = func_get_args(); // รับพารามิเตอร์ฟังก์ชัน $query = preg_replace("/(?query);
return $this->add_strings($query); // ใส่สตริงกลับเข้าไปในแบบสอบถาม
}
/**
* ใส่สตริงที่ถูกลบออกโดยฟังก์ชันเตรียม () อีกครั้ง
-
ฟังก์ชั่นส่วนตัว add_strings($string)
-
$numbers = array_keys($this->query_strings);
$count = จำนวน($ตัวเลข);
$การค้นหา = array();
สำหรับ($x = 0; $x < $count; $x++) {
$searches[$x] = "$||${$numbers[$x]}";
}
ส่งคืน str_replace($searches, $this->query_strings, $string);
}
/**
* แต่ละครั้งที่มีการดำเนินการ จะมีการเปลี่ยนตัวยึดตำแหน่งในขั้นตอนการจัดเก็บ
-
ฟังก์ชั่นที่ได้รับการป้องกัน Compile_callback($params, $index, $type)
-
--$index;
/* โยนข้อยกเว้น */
ถ้า (! isset($params[$index])) {
โยนข้อยกเว้นใหม่ ("ขั้นตอนการจัดเก็บไม่ได้รับพารามิเตอร์ตามจำนวนที่ต้องการ!");
}
/* คุณสามารถเพิ่มประเภทอื่นๆ ได้ที่นี่ เช่น วันที่และเวลา -
สวิตช์ ($ ประเภท) {
กรณี 'S':
return '"' . $this->db->escape_string($params[$index]) . '"';
หยุดพัก;
กรณี 'ฉัน':
กลับ (int) $params[$index];
หยุดพัก;
กรณี 'น':
กลับ (ลอย) $params[$index];
ค่าเริ่มต้น:
Throw new Exception("ประเภทข้อมูล '$type' ที่ระบุในขั้นตอนการจัดเก็บไม่ได้รับการยอมรับ");
-
}
มีการใช้ฟังก์ชันเพิ่มเติมสองฟังก์ชันในการคอมไพล์() ฟังก์ชันคอมไพล์_callback() ถูกใช้เป็นฟังก์ชันเรียกกลับในการเรียกฟังก์ชัน preg_replace() แต่ละครั้งที่พบตัวยึดตำแหน่งในการสืบค้น เมื่อรวบรวมค่าของฟังก์ชันก็จะถูกดำเนินการ
ฟังก์ชั่นดำเนินการ
ในที่สุดคุณจะต้องสร้างฟังก์ชั่นดำเนินการ () ฟังก์ชันดำเนินการ () รวบรวมแบบสอบถามและดำเนินการโดยใช้วัตถุ DB ซึ่งใช้ในการเริ่มต้นวัตถุ DBQuery ที่นี่ โปรดทราบในตัวอย่างที่ 4 ว่าฟังก์ชัน call_user_func_array() ถูกใช้อย่างไรเพื่อรับการสืบค้นที่คอมไพล์แล้ว เหตุผลก็คือฟังก์ชันเอ็กซีคิวต์() ไม่สามารถระบุจำนวนอาร์กิวเมนต์ที่ส่งผ่านไปได้จนกว่าจะรันไทม์
ตัวอย่างที่ 4: ฟังก์ชันดำเนินการ ()
/**
-
* ดำเนินการค้นหาปัจจุบันและแทนที่ตัวยึดตำแหน่งด้วยพารามิเตอร์ที่ให้มา
-
* @param ผสม $queryParams,... พารามิเตอร์การค้นหา
* ทรัพยากร @return การอ้างอิงถึงทรัพยากรที่แสดงถึงแบบสอบถามที่ดำเนินการ
-
ฟังก์ชั่นสาธารณะดำเนินการ ($queryParams = '')
-
//ตัวอย่าง: SELECT * FROM table WHERE name=:1S AND type=:2I AND level=:3N
$args = func_get_args();
ถ้า ($นี่->stored_procedure) {
/* ฟังก์ชั่นการคอมไพล์เพื่อรับแบบสอบถาม */
$query = call_user_func_array(array($this, 'compile'), $args);
} อื่น {
/* หากยังไม่ได้เตรียมใช้งานกระบวนงานที่เก็บไว้ ให้ดำเนินการเป็นแบบสอบถามมาตรฐาน -
$query = $queryParams;
}
$this->result = $this->db->query($query);
ส่งคืน $this->ผลลัพธ์;
}
รวบรวมทั้งหมดเข้าด้วยกัน
เพื่อสาธิตวิธีการใช้ออบเจ็กต์แบบสอบถาม มีการสร้างตัวอย่างเล็กๆ ไว้ด้านล่าง ซึ่งจะใช้ออบเจ็กต์ DBQuery เป็นขั้นตอนการจัดเก็บ และตรวจสอบว่ามีการป้อนชื่อผู้ใช้และรหัสผ่านที่ถูกต้องหรือไม่ โปรดดูตัวอย่างที่ 5:
ตัวอย่าง 5:
ต้องการ 'mysql_db.php5';
need_once 'query2.php5';
$db = MySqlDb ใหม่;
$db->connect('host', 'username', 'pass');
$db->query('use content_management_system');
$query = new DBQuery($db);
$query->prepare('SELECT fname,sname FROM users WHERE ชื่อผู้ใช้=:1S AND pword=:2S ANDexpired_time<:3I ');
if ($result = $query->execute("visualad", "apron", time())) {
ถ้า ($db->num_rows($result) == 1) {
echo('ข้อมูลประจำตัวถูกต้อง');
} อื่น {
echo('ข้อมูลประจำตัวไม่ถูกต้องและเซสชั่นหมดอายุ');
-
} อื่น {
echo('เกิดข้อผิดพลาดขณะดำเนินการค้นหา:' . $db->error());
}
ในบทความนี้ คุณได้เห็นวิธีการปกป้องข้อมูลและจำกัดการมองเห็นของออบเจ็กต์ข้อมูลโดยใช้ตัวแก้ไขการเข้าถึงแบบส่วนตัว ป้องกัน และสาธารณะ เมื่อประกาศตัวแปรคลาส ในเวลาเดียวกัน ใน PHP 5 แนวคิดเหล่านี้ก็สามารถใช้ได้เช่นกัน คลาสข้อมูลอื่นเพื่อปกป้องข้อมูลภายในที่สำคัญ