บ้าน - หน้าต่าง
จะทำงานร่วมกับ PDO ได้อย่างไร? คู่มือฉบับสมบูรณ์ การติดตั้งส่วนขยาย OCI8 และ PDO_OCI สำหรับ PHP5 การติดตั้ง pdo

ปัจจุบันฉันทำงานให้กับบริษัทที่ชอบใช้ Oracle DBMS ในโครงการ PHP ซึ่งบางครั้งก็เป็นเวอร์ชัน 11g

นักพัฒนาส่วนใหญ่ของบริษัทนี้ทำงานภายใต้ Windows OS ในช่วงเดือนที่ผ่านมา หลายคนตัดสินใจเข้าร่วม Linux และติดตั้ง Ubuntu หลายวันหลังจากติดตั้งระบบปฏิบัติการพวกเขาต้องเผชิญกับงานติดตั้งไดรเวอร์ PHP สำหรับการทำงานกับ Oracle DBMS - OCI8 และ PDO_OCI ที่ใช้ Oracle Instant Client 11.2 ซึ่งพวกเขาไม่สามารถแก้ไขได้ด้วยตัวเอง

ฉันไม่พบคู่มือภาษารัสเซียที่มีรายละเอียดและใช้งานได้ครบถ้วนตามที่ผู้มาใหม่ของ Linux สามารถดำเนินการจัดการทั้งหมดได้ด้วยตัวเอง ด้วยเหตุนี้ ฉันจึงต้องดำเนินการแบบเดียวกันหลายครั้งในเครื่องของพวกเขา และเขียนคู่มือซึ่งฉันนำเสนอให้คุณทราบ

คู่มือนี้เขียนขึ้นสำหรับผู้ใช้ Ubuntu Linux แต่ด้วยการปรับเปลี่ยนบางอย่าง จะเหมาะสำหรับผู้ใช้ระบบ Linux ส่วนใหญ่

กำลังเตรียมการติดตั้ง

  1. คุณต้องสามารถรันคำสั่งในฐานะผู้ดูแลระบบได้
  2. คุณต้องติดตั้ง php5 ด้วยแพ็คเกจต่อไปนี้ (คำสั่งการติดตั้งพร้อมรายการ):
    sudo apt-get ติดตั้ง php5 php5-dev php-pear php5-cli
    sudo pecl ติดตั้ง pdo
  3. คุณต้องติดตั้งไลบรารี libaio1:
    sudo apt-get ติดตั้ง libaio1

การติดตั้งไคลเอนต์ทันทีของ Oracle

ดาวน์โหลด Instant Client Oracle จากเว็บไซต์อย่างเป็นทางการ http://oracle.com สำหรับสถาปัตยกรรมโปรเซสเซอร์และระบบปฏิบัติการของคุณ
สำหรับ Linux Instant Client มีสองเวอร์ชัน:
  • แพ็คเกจ RPM - Linux, CentOS, Fedora, Red Hat Enterprise Linux, Mandriva Linux, SUSE Linux ฯลฯ ที่รองรับ RPM;
  • ไฟล์ ZIP - สำหรับคนอื่นๆ
คุณต้องดาวน์โหลดไฟล์ 2 ไฟล์:
  • Instantclient-basic - ไคลเอนต์ทันทีของ Oracle นั่นเอง
  • Instantclient-sdk - ชุดไลบรารีสำหรับการพัฒนาแอปพลิเคชันสำหรับ Oracle Instant Client
คุณยังสามารถดาวน์โหลด:
  • ไคลเอ็นต์ทันที-sqlplus - SQL*Plus
สร้างไดเร็กทอรีที่จะเก็บไฟล์ Oracle Instant Client (ไดเร็กทอรี /opt ซึ่งสงวนไว้สำหรับแพ็คเกจซอฟต์แวร์เพิ่มเติม เหมาะสำหรับสิ่งนี้):
sudo mkdir -p /opt/oracle/

ย้ายไฟล์ที่ดาวน์โหลดไปที่ /opt/oracle และไปที่โฟลเดอร์ปลายทาง (สมมติว่าคุณดาวน์โหลด “ไฟล์ zip” ไปยังโฟลเดอร์ “ดาวน์โหลด” ของผู้ใช้ของคุณ):
sudo mv ~/downloads/instantclient-*.zip /opt/oracle/
ซีดี /opt/oracle/

คลายซิปไฟล์เก็บถาวรที่ดาวน์โหลดทั้งหมด:
sudo unzip Instantclient-basic-*-*.zip
sudo unzip Instantclient-sdk-*-*.zip
หากคุณดาวน์โหลด SQL*Plus:
sudo unzip Instantclient-sqlplus-*-*.zip

ด้วยเหตุนี้ ในไดเร็กทอรี /opt/oracle ไดเร็กทอรี Instantclient_11_2 จึงถูกสร้างขึ้นสำหรับ Oracle Instant Client 11.2.0.2.0 มาเปลี่ยนชื่อไดเร็กทอรีนี้เป็น Instantclient (หากคุณมีเวอร์ชัน/ไดเร็กทอรีอื่น ให้เปลี่ยนคำสั่ง) และไปที่:
sudo mv Instantclient_11_2 ไคลเอนต์ทันที
ซีดีไคลเอนต์ทันที

ถัดไป คุณต้องสร้างไดเร็กทอรีเพิ่มเติมและลิงก์สัญลักษณ์เพื่อให้ไคลเอ็นต์ทำงานได้ตามปกติ (โปรดใส่ใจกับเวอร์ชันและหากคุณมีเวอร์ชันอื่น ให้เปลี่ยนคำสั่ง):
sudo ln -s /opt/oracle/instantclient/libclntsh.so.* /opt/oracle/instantclient/libclntsh.so
sudo ln -s /opt/oracle/instantclient/libocci.so.* /opt/oracle/instantclient/libocci.so
sudo ln -s /opt/oracle/instantclient/ /opt/oracle/instantclient/lib

Sudo mkdir -p รวม/oracle/11.2/
ซีดีรวม/oracle/11.2/
sudo ln -s ../../../sdk/include ไคลเอนต์
ซีดี-

Sudo mkdir -p lib/oracle/11.2/client
ซีดี lib/oracle/11.2/client
sudo ln -s ../../../ lib
ซีดี-

เราสร้างไฟล์การกำหนดค่าที่จะระบุไดเร็กทอรีสำหรับการค้นหาไลบรารีไคลเอ็นต์ทันทีของ Oracle และเชื่อมต่อ:
echo /opt/oracle/instantclient/ | sudo tee -a /etc/ld.so.conf.d/oracle.conf
sudo ldconfig.php

เนื่องจากไม่มีไดเร็กทอรี /usr/include/php ใน Ubuntu และไคลเอนต์ยังคงมองหาไดเร็กทอรีนี้ เรามาสร้างลิงก์สัญลักษณ์ที่เทียบเท่ากับ php5 กันดีกว่า:
sudo ln -s /usr/include/php5 /usr/include/php.ini

ติดตั้ง OCI8

หลังจากการดัดแปลงทั้งหมดของเรา ส่วนขยาย oci8 จะติดตั้งอย่างน่าอัศจรรย์โดยใช้คำสั่ง pecl:
sudo pecl ติดตั้ง oci8
เราถูกขอให้ป้อนเส้นทางไปยังไคลเอนต์ทันทีของ Oracle ซึ่งเราต้องตอบ:
ไคลเอนต์ทันที /opt/oracle/instantclient

สร้างไฟล์การเชื่อมต่อส่วนขยาย:
echo "; การกำหนดค่าสำหรับโมดูล php oci8" | sudo ที /etc/php5/conf.d/oci8.ini
ส่วนขยายเสียงก้อง=oci8.so | sudo tee -a /etc/php5/conf.d/oci8.ini

ติดตั้ง PDO_OCI

ในการติดตั้ง PDO_OCI เราต้องดาวน์โหลดจากที่เก็บลูกแพร์ก่อน
มาอัพเดตรายการแพ็คเกจลูกแพร์กันดีกว่า:
อัปเดตช่อง sudo pecl pear.php.net

ดาวน์โหลดและวางไฟล์เก็บถาวรในไดเร็กทอรีชั่วคราว:
sudo mkdir -p /tmp/pear/ดาวน์โหลด/
ซีดี /tmp/ลูกแพร์/ดาวน์โหลด/
sudo pecl ดาวน์โหลด pdo_oci

มาแยกเนื้อหาของไฟล์เก็บถาวรแล้วไปที่:
sudo tar xvf PDO_OCI*.tgz
ซีดี PDO_OCI*

ที่นี่เราจำเป็นต้องปรับไฟล์ config.m4 เนื่องจากไม่มีข้อมูลเกี่ยวกับ Oracle Instant Client เวอร์ชันของเรา การเปลี่ยนแปลงล่าสุดย้อนกลับไปในปี 2548 เปิดตัวโปรแกรมแก้ไขที่คุณชื่นชอบและทำการเปลี่ยนแปลงที่มีเครื่องหมาย "+" (ให้ความสนใจกับเวอร์ชันและหากคุณมีเวอร์ชันอื่น ให้เปลี่ยนบรรทัด):
sudo vim config.m4

ต่อไปนี้เป็นส่วนต่างของสองไฟล์:
***************
*** 7,12 ****
--- 7,14 ----
ถ้าการทดสอบ -s "$PDO_OCI_DIR/orainst/unix.rgs"; แล้ว
PDO_OCI_VERSION=`grep ""ocommon"" $PDO_OCI_DIR/orainst/unix.rgs | sed "s/*/:/g" | ตัด -d: -f 6 | ตัด -c 2-4`
ทดสอบ -z "$PDO_OCI_VERSION" && PDO_OCI_VERSION=7.3
+ การทดสอบเอลิฟ -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.11.2; แล้ว
+ PDO_OCI_VERSION=11.2
การทดสอบเอลิฟ -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; แล้ว
PDO_OCI_VERSION=10.1
การทดสอบเอลิฟ -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; แล้ว
***************
*** 119,124 ****
--- 121,129 ----
10.2)
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
;;
+ 11.2)
+ PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
+ ;;
*)
AC_MSG_ERROR(เวอร์ชัน Oracle ไม่รองรับ! $PDO_OCI_VERSION)
;;
***************

เราเตรียมสภาพแวดล้อมสำหรับส่วนขยาย php โดยใช้คำสั่ง phpize (โปรดใส่ใจกับเวอร์ชันนี้ หากคุณมีเวอร์ชันอื่น ให้เปลี่ยน):
sudo phpize

เรากำหนดค่าตัวติดตั้งแพ็คเกจและติดตั้งแพ็คเกจ (ให้ความสนใจกับเวอร์ชันหากคุณมีรุ่นอื่นให้เปลี่ยน):
sudo ./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient/,11.2
ซูโดะทำ
sudo ทำการติดตั้ง

เราสร้างไฟล์การเชื่อมต่อสำหรับมัน:
echo "; การกำหนดค่าสำหรับโมดูล php PDO_OCI" | sudo ที /etc/php5/conf.d/pdo_oci.ini
ส่วนขยายเสียงสะท้อน=pdo_oci.so | sudo tee -a /etc/php5/conf.d/pdo_oci.ini

มาสรุปกัน

รีสตาร์ท apache และตรวจสอบส่วนขยายที่ติดตั้ง:
sudo /etc/init.d/apache2 รีสตาร์ท
PHP -ม

บทสรุป

คู่มือนี้อิงจากโพสต์นี้ ซึ่งได้รับการแก้ไขเล็กน้อย - ข้อผิดพลาดได้รับการแก้ไขแล้วและมีการเพิ่มเติม

ฉันหวังว่าบทความนี้จะมีประโยชน์ไม่เฉพาะกับเพื่อนร่วมงานของฉันเท่านั้น


3 มิถุนายน 2018 อันเดรย์ เชอร์นิชอฟ การสอนการแปล 1736 0

PDO เป็นตัวย่อสำหรับ PHP Data Objects: มันเป็นส่วนขยาย PHP สำหรับการทำงานกับฐานข้อมูลโดยใช้วัตถุ ข้อดีประการหนึ่งอยู่ที่ความจริงที่ว่ามันไม่ได้เชื่อมโยงโดยตรงกับฐานข้อมูลเฉพาะ: อินเทอร์เฟซของมันช่วยให้คุณเข้าถึงสภาพแวดล้อมที่แตกต่างกันมากมาย รวมถึง: MySQL, SQLite, PostgreSQL, Microsoft SQL Server

คู่มือนี้มีจุดมุ่งหมายเพื่อให้ภาพรวมโดยสมบูรณ์ของ PDO และแนะนำผู้อ่านทีละขั้นตอนตั้งแต่การสร้างและการเชื่อมต่อกับฐานข้อมูล ไปจนถึงการเลือกวิธีการดึงข้อมูลที่เหมาะสมที่สุด สาธิตวิธีสร้างแบบสอบถามที่เตรียมไว้ และอธิบายโหมดข้อผิดพลาดที่เป็นไปได้

การสร้างฐานข้อมูลทดสอบและตาราง

ก่อนอื่นเราจะสร้างฐานข้อมูล:

สร้างฐานข้อมูล Solar_system; ให้สิทธิ์ทั้งหมดบน Solar_system.* แก่ "testuser"@"localhost" ที่ระบุโดย "testpassword";

เราได้ให้สิทธิ์แก่ผู้ใช้ testuser ในฐานข้อมูล Solar_system โดยใช้ testpassword เป็นรหัสผ่าน ตอนนี้เรามาสร้างตารางและกรอกข้อมูลบางส่วนกัน:

ใช้ระบบสุริยะ; สร้างดาวเคราะห์ตาราง (id TINYINT (1) UNSIGNED NOT NULL AUTO_INCREMENT, คีย์หลัก (id), ชื่อ VARCHAR (10) NOT NULL, สี VARCHAR (10) NOT NULL); ใส่เข้าไปในดาวเคราะห์(ชื่อ, สี) VALUES("earth", "blue"), ("mars", "red"), ("jupiter", "แปลก");

คำอธิบายของการเชื่อมต่อ DSN (ชื่อแหล่งข้อมูล)

ตอนนี้เรามีฐานข้อมูลแล้ว เราต้องตั้งค่า DSN DSN ย่อมาจาก Data Source Name และเป็นชุดข้อมูลที่จำเป็นในการเชื่อมต่อกับฐานข้อมูล DSN จะอยู่ในรูปแบบของสตริง ไวยากรณ์จะแตกต่างกันไปขึ้นอยู่กับฐานข้อมูลที่คุณต้องการเชื่อมต่อ แต่เนื่องจากเราใช้ MySQL/MariaDB เราจึงต้องตั้งค่าต่อไปนี้:

  • ประเภทของไดรเวอร์ที่ใช้สำหรับการเชื่อมต่อ
  • ชื่อของคอมพิวเตอร์แม่ข่ายที่ฐานข้อมูลกำลังทำงานอยู่
  • พอร์ตเชื่อมต่อ (อุปกรณ์เสริม);
  • ชื่อฐานข้อมูล
  • การเข้ารหัส (ไม่บังคับ)

รูปแบบสตริงในกรณีของเราจะเป็นแบบนี้ (เราจะเก็บไว้ในตัวแปร $dsn):

$dsn = "mysql:host=localhost;port=3306;dbname=solar_system;charset=utf8";

ก่อนอื่น เราตั้งค่าคำนำหน้าฐานข้อมูลหรือคำนำหน้าฐานข้อมูล ในกรณีนี้ เนื่องจากเรากำลังเชื่อมต่อกับฐานข้อมูลประเภท MySQL/MariaDB เราจึงใช้ mysql จากนั้นเราแยกคำนำหน้าออกจากส่วนที่เหลือของบรรทัดด้วยเครื่องหมายทวิภาค และแต่ละส่วนที่ตามมาจะถูกแยกออกจากส่วนที่เหลือด้วยเครื่องหมายอัฒภาค

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

การสร้างวัตถุ PDO

เมื่อ DSN ของเราพร้อมแล้ว เราจะเริ่มสร้างวัตถุ PDO ตัวสร้าง PDO ใช้สตริง DSN เป็นพารามิเตอร์แรก ชื่อผู้ใช้ฐานข้อมูลเป็นพารามิเตอร์ที่สอง รหัสผ่านเป็นพารามิเตอร์ที่สาม และอาร์เรย์การตั้งค่าเผื่อเลือกเป็นพารามิเตอร์ที่สี่

$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO ใหม่($dsn, "testuser", "testpassword", $options);

การตั้งค่ายังสามารถตั้งค่าได้หลังจากสร้างวัตถุแล้ว โดยใช้เมธอด SetAttribute():

$pdo->SetAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

การตั้งค่า PDO สำหรับการดูข้อผิดพลาด

ลองมาดูตัวเลือกบางส่วนที่มีให้สำหรับ PDO::ATTR_ERRMODE ตัวเลือกเหล่านี้มีความสำคัญอย่างยิ่งเนื่องจากเป็นตัวกำหนดว่า PDO ทำงานอย่างไรเมื่อเกิดข้อผิดพลาด ตัวเลือกที่เป็นไปได้:

PDO::ERRMODE_SILENT

ตัวเลือกเริ่มต้น PDO จะส่งรหัสข้อผิดพลาดและข้อความแสดงข้อผิดพลาด สามารถรับได้โดยใช้เมธอด errorCode() และ errorInfo()

PDO::ERRMODE_EXCEPTION

ในความคิดของฉันแนะนำให้ใช้ตัวเลือกนี้ ด้วยความช่วยเหลือ นอกเหนือจากการออกรหัสข้อผิดพลาดและข้อมูลแล้ว PDO จะส่ง PDOException ซึ่งจะขัดขวางการทำงานของสคริปต์ และยังมีประโยชน์สำหรับธุรกรรม PDO ด้วย (เราจะดูในภายหลัง)

PDO::ERRMODE_WARNING

ด้วยตัวเลือกนี้ PDO จะแสดงรหัสข้อผิดพลาดและข้อความเหมือนกับ PDO::ERRMODE_SILENT แต่จะแสดงคำเตือนคำเตือนที่ไม่ขัดจังหวะสคริปต์ด้วย

การตั้งค่าวิธีการสุ่มตัวอย่างเริ่มต้น

การตั้งค่าที่สำคัญอีกประการหนึ่งได้รับการควบคุมโดยใช้ค่าคงที่ PDO::DEFAULT_FETCH_MODE ช่วยให้คุณสามารถกำหนดค่าการดำเนินการเริ่มต้นของเมธอด fetch() ซึ่งจะถูกใช้เพื่อรับผลลัพธ์ของการร้องขอ นี่คือตัวเลือกที่ใช้บ่อยที่สุด:

PDO::FETCH_BOTH

เมื่อใช้งาน ผลลัพธ์ที่ได้จะถูกจัดทำดัชนีทั้งจำนวนเต็มและชื่อคอลัมน์ การใช้มันในวิธีการดึงแถวจากตารางดาวเคราะห์จะให้ผลลัพธ์ดังต่อไปนี้:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->ดึงข้อมูล (PDO::FETCH_BOTH);

อาร์เรย์ ( => 1 => 1 => ดิน => ดิน => สีน้ำเงิน => สีน้ำเงิน)

ด้วยค่าคงที่นี้ ผลลัพธ์จะถูกเขียนลงในอาร์เรย์ที่เชื่อมโยง โดยแต่ละคีย์จะเป็นชื่อคอลัมน์ และแต่ละค่าจะแสดงค่าเฉพาะในแถว:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->ดึงข้อมูล (PDO::FETCH_ASSOC);

อาร์เรย์ ( => 1 => ดิน => สีน้ำเงิน)

PDO::FETCH_NUM

การใช้ค่าคงที่ PDO::FETCH_NUM เราได้รับอาร์เรย์ที่มีดัชนี 0:

อาร์เรย์ ( => 1 => ดิน => สีน้ำเงิน)

PDO::FETCH_COLUMN

ค่าคงที่นี้มีประโยชน์ในการรับเฉพาะค่าจากคอลัมน์ และเมธอดจะส่งคืนผลลัพธ์ทั้งหมดภายในอาร์เรย์หนึ่งมิติแบบธรรมดา ตัวอย่างเช่น นี่คือคำขอ:

$stmt = $pdo->query("เลือกชื่อจากดาวเคราะห์");

เป็นผลให้:

อาร์เรย์ ( => โลก => ดาวอังคาร => ดาวพฤหัสบดี)

PDO::FETCH_KEY_PAIR

ค่าคงที่นี้มีประโยชน์เมื่อคุณต้องการรับค่าจากสองคอลัมน์ เมธอด fetchAll() จะส่งกลับผลลัพธ์เป็นอาร์เรย์ที่เชื่อมโยง ในอาร์เรย์นี้ข้อมูลจากคอลัมน์แรกจะถูกระบุในรูปแบบของคีย์และจากคอลัมน์ที่สอง - เป็นค่า:

$stmt = $pdo->query("เลือกชื่อจากดาวเคราะห์");

$stmt = $pdo->query("เลือกชื่อ, สีจากดาวเคราะห์"); $result = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

อาร์เรย์ ( => สีน้ำเงิน => สีแดง => แปลก)

PDO::FETCH_OBJECT

เมื่อใช้ค่าคงที่ PDO::FETCH_OBJECT ออบเจ็กต์ที่ไม่ระบุชื่อจะถูกสร้างขึ้นสำหรับการดึงข้อมูลแต่ละแถว คุณสมบัติ (สาธารณะ) ของมันจะถูกตั้งชื่อเหมือนกับคอลัมน์ และผลลัพธ์ของแบบสอบถามจะถูกใช้เป็นค่า การใช้วิธีนี้กับแบบสอบถามเดียวกันกับข้างต้นจะให้ผลลัพธ์ดังต่อไปนี้:

$results = $stmt->ดึงข้อมูล (PDO::FETCH_OBJ);

วัตถุ stdClass ( => ดิน => สีน้ำเงิน)

PDO::FETCH_CLASS

เช่นเดียวกับค่าคงที่ก่อนหน้า สิ่งนี้จะกำหนดค่าคอลัมน์ให้กับคุณสมบัติของวัตถุ แต่ในกรณีนี้ เราต้องกำหนดค่าคลาสที่มีอยู่ซึ่งจะใช้ในการสร้างวัตถุ สำหรับการสาธิต ก่อนอื่นเราจะสร้างคลาส:

Class Planet ( private $name; private $color; public function setName($planet_name) ( $this->name = $planet_name; ) public function setColor($planet_color) ( $this->color = $planet_color; ) public function getName () ( return $this->name; ) ฟังก์ชั่นสาธารณะ getColor() ( return $this->color; ) )

$stmt = $pdo->query("เลือกชื่อ, สีจากดาวเคราะห์"); $stmt->setFetchMode(PDO::FETCH_CLASS, "ดาวเคราะห์");

เราระบุค่าคงที่ PDO::FETCH_CLASS เป็นอาร์กิวเมนต์แรกของเมธอด setFetchMode() และชื่อของคลาสที่ใช้ในการสร้างวัตถุ (ในกรณีของเรา “Planet”) เป็นอาร์กิวเมนต์ที่สอง ตอนนี้เรามารันโค้ดกัน:

$planet = $stmt->ดึงข้อมูล();

สิ่งนี้จะส่งผลให้วัตถุ Planet:

Var_dump($ดาวเคราะห์);

วัตถุดาวเคราะห์ ( => โลก => สีน้ำเงิน)

สังเกตว่าค่าที่ส่งคืนจากแบบสอบถามถูกกำหนดให้กับคุณสมบัติที่สอดคล้องกันของวัตถุแม้ว่าจะเป็นแบบส่วนตัวก็ตาม

การกำหนดลักษณะหลังจากสร้างวัตถุ

คลาส "Planet" ไม่มีตัวสร้างเฉพาะ ดังนั้นจึงไม่มีปัญหาในการกำหนดคุณลักษณะ แต่จะเกิดอะไรขึ้นถ้าคลาสมีคอนสตรัคเตอร์ที่มีการตั้งค่าและเปลี่ยนแปลงคุณสมบัติ? เนื่องจากมีการกำหนดค่าก่อนที่ Constructor จะรัน ค่าเหล่านั้นจะถูกเขียนทับ

PDO ช่วยให้ค่าคงที่ FETCH_PROPS_LATE: เมื่อใช้แล้ว ค่าจะถูกกำหนดค่าหลังจากสร้างวัตถุแล้ว ตัวอย่าง:

Class Planet ( private $name; private $color; public function __construct($name = moon, $color = grey) ( $this->name = $name; $this->color = $color; ) ฟังก์ชั่นสาธารณะ setName($ planet_name) ( $this->name = $planet_name; ) ฟังก์ชั่นสาธารณะ setColor($planet_color) ( $this->color = $planet_color; ) ฟังก์ชั่นสาธารณะ getName() ( return $this->name; ) ฟังก์ชั่นสาธารณะ getColor() ( return $this->color; ) )

เราได้แก้ไขคลาส Planet ของเราเพื่อสร้าง Constructor ที่จะรับอาร์กิวเมนต์สองรายการ: name name และ color อาร์กิวเมนต์เหล่านี้มีค่าฐานพระจันทร์และสีเทาซึ่งหมายความว่าหากไม่มีค่าอื่นใดจะได้รับค่าเหล่านี้จะถูกตั้งค่า

ในกรณีนี้ถ้าเราไม่ใช้ FETCH_PROPS_LATE ไม่ว่าค่าใดที่ได้รับจากฐานข้อมูล คุณลักษณะทั้งหมดจะยังคงเป็นพื้นฐาน เพราะในระหว่างกระบวนการสร้างวัตถุ คุณสมบัติเหล่านั้นจะถูกเขียนทับ เมื่อต้องการตรวจสอบนี้ ให้เรียกใช้แบบสอบถามต่อไปนี้:

$stmt = $pdo->query("เลือกชื่อ, สีจากระบบสุริยะ WHERE name = "earth""); $stmt->setFetchMode(PDO::FETCH_CLASS, "ดาวเคราะห์"); $planet = $stmt->ดึงข้อมูล();

ตอนนี้เรามาดูวัตถุ Planet และตรวจสอบว่าค่าใดที่สอดคล้องกับลักษณะของมัน:

ตามที่คาดไว้ ค่าที่ดึงมาจากฐานข้อมูลจะถูกเขียนทับด้วยค่าเริ่มต้น ตอนนี้ เราจะสาธิตวิธีแก้ไขปัญหาโดยใช้ค่าคงที่ FETCH_PROPS_LATE (และแบบสอบถามเดียวกันกับแบบสอบถามก่อนหน้า):

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "ดาวเคราะห์"); $planet = $stmt->ดึงข้อมูล(); var_dump($ดาวเคราะห์);

object(Planet)#4 (2) ( ["ชื่อ":Planet":private]=> string(5) "earth" ["color"Planet":private]=> string(4) "blue" )

ในที่สุดก็ได้ผลลัพธ์ที่ต้องการ แต่จะเกิดอะไรขึ้นถ้าตัวสร้างคลาสไม่มีค่าฐานและต้องระบุล่ะ? สิ่งนี้ง่ายกว่าอยู่แล้ว: เราสามารถตั้งค่าพารามิเตอร์ตัวสร้างในรูปแบบของอาร์เรย์เป็นอาร์กิวเมนต์ที่สามหลังจากชื่อคลาส โดยใช้เมธอด setFetchMode() ตัวอย่างเช่น ลองเปลี่ยน Constructor:

Class Planet ( private $name; private $color; public function __construct($name, $color) ( $this->name = $name; $this->color = $color; ) [...] )

ตอนนี้จำเป็นต้องมีอาร์กิวเมนต์ของ Constructor ดังนั้นเราจึงดำเนินการ:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "ดาวเคราะห์", ["ดวงจันทร์", "สีเทา"]);

ในกรณีนี้ พารามิเตอร์ที่เราระบุทำหน้าที่เป็นค่าพื้นฐานที่จำเป็นสำหรับวัตถุในการทำงานโดยไม่มีข้อผิดพลาดเท่านั้น โดยจะถูกเขียนทับด้วยค่าจากฐานข้อมูล

การดึงข้อมูลหลายวัตถุ

แน่นอนว่าเป็นไปได้ที่จะได้รับผลลัพธ์หลายรายการพร้อมกันในรูปแบบของวัตถุ ไม่ว่าจะใช้วิธี fetch() หรือผ่านการวนซ้ำ:

ในขณะที่ ($planet = $stmt->fetch()) ( // บางอย่างเกี่ยวข้องกับผลลัพธ์ )

หรือรับผลทั้งหมดในคราวเดียว ในกรณีนี้ ตามที่กล่าวไว้ข้างต้น เมื่อใช้วิธีการ fetchAll() คุณจะต้องระบุโหมดการดึงข้อมูล ไม่ใช่ก่อนที่จะเรียกใช้เมธอด แต่ในขณะที่มันรัน:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE, "ดาวเคราะห์", ["ดวงจันทร์", "สีเทา"]);

PDO::FETCH_INTO

เมื่อใช้ค่าคงที่นี้ PDO จะไม่สร้างวัตถุใหม่ แต่จะอัปเดตคุณสมบัติของวัตถุที่มีอยู่แทน แต่เฉพาะในกรณีที่เป็นแบบสาธารณะหรือหากใช้เมธอด __set() ภายในวัตถุ

จัดทำขึ้นเพื่อต่อต้านการร้องขอโดยตรง

PDO มีสองวิธีในการทำงานกับแบบสอบถาม: การใช้โดยตรงและแบบที่เตรียมไว้ที่เชื่อถือได้มากกว่า

คำขอโดยตรง

วิธีที่สองส่งคืนหมายเลขแถวที่แก้ไขโดยการสืบค้นแทน: เราใช้สิ่งนี้ในกรณีที่แทนที่แถว เช่น INSERT, DELETE หรือ UPDATE ควรใช้การสืบค้นโดยตรงเฉพาะในกรณีที่ไม่มีตัวแปรในการสืบค้น และไม่มีข้อสงสัยเกี่ยวกับความปลอดภัยของวิธีการนี้

แบบสอบถามที่เตรียมไว้

PDO ยังรองรับการสืบค้นแบบสองขั้นตอนที่เตรียมไว้: สิ่งเหล่านี้มีประโยชน์เมื่อการสืบค้นมีตัวแปร และปลอดภัยกว่าโดยทั่วไปเนื่องจากเมธอด wait() จะทำงานที่จำเป็นทั้งหมดให้เรา มาดูวิธีการใช้ตัวแปรกัน ลองนึกภาพเราต้องการแทรกคุณลักษณะของดาวเคราะห์ลงในตารางดาวเคราะห์ ก่อนอื่น มาเตรียมคำขอกันก่อน:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(?, ?)");

ตามที่ระบุไว้ก่อนหน้านี้ เราใช้เมธอดเตรียม () ซึ่งใช้แบบสอบถาม SQL เป็นอาร์กิวเมนต์ โดยใช้ค่าชั่วคราวสำหรับตัวแปร ค่าชั่วคราวสามารถมีได้สองประเภท: ตำแหน่งและค่าระบุ

ตำแหน่ง

โดยใช้? ค่าตำแหน่งชั่วคราว รหัสจะกระชับมากขึ้น แต่เราต้องระบุข้อมูลที่จะแทรกในลำดับเดียวกันกับชื่อคอลัมน์ในอาร์เรย์ที่ให้มาเป็นอาร์กิวเมนต์ของวิธีการดำเนินการ ():

$stmt->execute([$planet->ชื่อ, $planet->สี]);

ส่วนบุคคล

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

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->execute(["name" => $planet->name, "color" => $planet->color]);

สามารถใช้ทั้งวิธีการเตรียม () และดำเนินการ () สำหรับการสืบค้นที่แก้ไขหรือดึงข้อมูลจากฐานข้อมูล ในกรณีแรก เราใช้วิธีการดึงข้อมูลที่แสดงด้านบนเพื่อรับข้อมูล และในกรณีที่สอง เราใช้วิธี rowCount()

วิธีbindValue() และbindParam()

เมธอด bindValue() และ bindParam() ยังสามารถใช้เพื่อจัดเตรียมค่าที่จะแทรกลงในคำขอ ขั้นแรกผูกค่าของตัวแปรที่กำหนดกับค่าตำแหน่งหรือชื่อชั่วคราวที่ใช้ในการเตรียมคำขอ เราจะยกตัวอย่างกรณีก่อนหน้านี้:

$stmt->bindValue("ชื่อ", $planet->ชื่อ, PDO::PARAM_STR);

เราผูกค่าของ $planet->name เข้ากับค่าชั่วคราว:name โปรดทราบว่าการใช้ทั้งวิธีbindValue() และbindParam() เรายังสามารถระบุประเภทของตัวแปรเป็นอาร์กิวเมนต์ที่สามโดยใช้ค่าคงที่ PDO ที่เหมาะสม ในกรณีนี้คือ PDO::PARAM_STR

โดยใช้bindParam() แทนเราสามารถผูกตัวแปรให้เป็นค่าชั่วคราวที่เหมาะสมซึ่งใช้ในการเตรียมแบบสอบถาม โปรดทราบว่าในกรณีนี้ ตัวแปรถูกผูกไว้กับการอ้างอิง และค่าของมันจะถูกเปลี่ยนเป็นชั่วคราวเมื่อเรียกใช้เมธอดดำเนินการ () เท่านั้น ไวยากรณ์เหมือนกับครั้งล่าสุด:

$stmt->bindParam("ชื่อ", $planet->ชื่อ, PDO::PARAM_STR)

เราได้ผูกตัวแปรไว้ ไม่ใช่ค่าของมัน $planet->name to:name ! ตามที่กล่าวไว้ข้างต้น การแทนที่จะเกิดขึ้นเมื่อมีการเรียกใช้เมธอดดำเนินการ () เท่านั้น ดังนั้นค่าชั่วคราวจะถูกแทนที่ด้วยค่าของตัวแปรในขณะนั้น

ธุรกรรม PDO

ธุรกรรมช่วยให้คุณรักษาความสอดคล้องเมื่อเรียกใช้หลายแบบสอบถาม การสืบค้นทั้งหมดจะดำเนินการเป็นชุดและนำไปใช้กับฐานข้อมูลก็ต่อเมื่อการสืบค้นทั้งหมดสำเร็จ ธุรกรรมจะไม่ทำงานกับฐานข้อมูลทั้งหมด และไม่ใช่กับโครงสร้าง SQL ทั้งหมด เนื่องจากบางฐานข้อมูลทำให้เกิดปัญหา

เป็นตัวอย่างที่รุนแรงและแปลกประหลาด ลองนึกภาพว่าผู้ใช้ต้องเลือกรายการดาวเคราะห์ และทุกครั้งที่เขาทำการเลือกใหม่ คุณจะต้องลบอันก่อนหน้าออกจากฐานข้อมูลก่อนจึงจะแทรกอันใหม่ได้ จะเกิดอะไรขึ้นถ้าการลบเกิดขึ้นแต่การแทรกไม่เกิดขึ้น? เราจะได้ผู้ใช้ที่ไม่มีดาวเคราะห์! โดยพื้นฐานแล้ว ธุรกรรมจะถูกนำไปใช้ในลักษณะนี้:

$pdo->beginTransaction(); ลอง ( $stmt1 = $pdo->exec("DELETE FROM planets"); $stmt2 = $pdo->prepare("INSERT INTO planets(name, color) VALUES (?, ?)"); foreach ($planets as $planet) ( $stmt2->execute([$planet->getName(), $planet->getColor()]); ) $pdo->commit() ) catch (PDOException $e) ( $pdo-> rollBack ();

ประการแรก เมธอด beginningTransaction() บนออบเจ็กต์ PDO จะปิดใช้งานการส่งคำขออัตโนมัติ จากนั้นคำขอจะเริ่มต้นตามลำดับที่ต้องการ ณ จุดนี้ เว้นแต่ว่า PDOException จะเกิดขึ้น คำขอจะถูกส่งผ่านเมธอด commit() โดยอัตโนมัติ มิฉะนั้น ธุรกรรมจะถูกยกเลิกผ่านเมธอด rollBack() และคอมมิตอัตโนมัติจะถูกกู้คืน

ด้วยวิธีนี้ เมื่อมีคำขอหลายรายการ ก็จะมีความสอดคล้องกันเสมอ สิ่งนี้ค่อนข้างชัดเจน แต่ธุรกรรม PDO สามารถใช้งานได้โดย PDO::ATTR_ERRMODE ที่ตั้งค่าเป็น PDO::ERRMODE_EXCEPTION เท่านั้น

ขั้นแรก เรามาสร้างฐานข้อมูลสำหรับบทช่วยสอนนี้:

สร้างฐานข้อมูล Solar_system; ให้สิทธิ์ทั้งหมดบน Solar_system.* แก่ "testuser"@"localhost" ที่ระบุโดย "testpassword";

ผู้ใช้ที่มีการเข้าสู่ระบบ testuser และรหัสผ่าน testpassword ได้รับสิทธิ์การเข้าถึงฐานข้อมูล Solar_system อย่างเต็มรูปแบบ

ตอนนี้เรามาสร้างตารางและกรอกข้อมูลด้วยความแม่นยำทางดาราศาสตร์ซึ่งไม่ได้บอกเป็นนัย:

ใช้ระบบสุริยะ; สร้างดาวเคราะห์ตาราง (id TINYINT (1) UNSIGNED NOT NULL AUTO_INCREMENT, คีย์หลัก (id), ชื่อ VARCHAR (10) NOT NULL, สี VARCHAR (10) NOT NULL); ใส่เข้าไปในดาวเคราะห์(ชื่อ, สี) VALUES("earth", "blue"), ("mars", "red"), ("jupiter", "แปลก");

คำอธิบายการเชื่อมต่อ

เมื่อสร้างฐานข้อมูลแล้ว เรามากำหนด DSN () - ข้อมูลสำหรับการเชื่อมต่อกับฐานข้อมูลซึ่งแสดงเป็นสตริง ไวยากรณ์คำอธิบายจะแตกต่างกันไปขึ้นอยู่กับ DBMS ที่ใช้ ในตัวอย่าง เรากำลังทำงานกับ MySQL/MariaDB ดังนั้นเราจึงระบุว่า:

  • ชื่อโฮสต์ที่ DBMS ตั้งอยู่
  • พอร์ต (เป็นทางเลือกหากใช้พอร์ตมาตรฐาน 3306)
  • ชื่อฐานข้อมูล
  • การเข้ารหัส (ไม่จำเป็น)

บรรทัด DSN ในกรณีนี้มีลักษณะดังนี้:

$dsn = "mysql:host=localhost;port=3306;dbname=solar_system;charset=utf8";

คำนำหน้าฐานข้อมูลจะถูกระบุก่อน ในตัวอย่าง - mysql คำนำหน้าจะถูกแยกออกจากส่วนที่เหลือของบรรทัดด้วยเครื่องหมายโคลอน และแต่ละพารามิเตอร์ที่ตามมาจะถูกคั่นด้วยเครื่องหมายอัฒภาค

การสร้างวัตถุ PDO

ตอนนี้สตริง DSN พร้อมแล้ว มาสร้างวัตถุ PDO กันดีกว่า ตัวสร้างอินพุตยอมรับพารามิเตอร์ต่อไปนี้:

  1. สตริง DSN
  2. ชื่อของผู้ใช้ที่มีสิทธิ์เข้าถึงฐานข้อมูล
  3. รหัสผ่านของผู้ใช้รายนี้
  4. อาร์เรย์ที่มีพารามิเตอร์เพิ่มเติม (ไม่บังคับ)
$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; $pdo = PDO ใหม่($dsn, "testuser", "testpassword", $options);

พารามิเตอร์เพิ่มเติมสามารถกำหนดได้หลังจากสร้างวัตถุโดยใช้เมธอด SetAttribute:

$pdo->SetAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

การกำหนดวิธีการสุ่มตัวอย่างเริ่มต้น

PDO::DEFAULT_FETCH_MODE เป็นพารามิเตอร์สำคัญที่กำหนดวิธีการดึงข้อมูลเริ่มต้น วิธีการที่ระบุจะใช้เมื่อได้รับผลลัพธ์ของการร้องขอ

PDO::FETCH_BOTH

โหมดเริ่มต้น ผลลัพธ์ของการเลือกจะถูกจัดทำดัชนีด้วยทั้งตัวเลข (เริ่มจาก 0) และชื่อคอลัมน์:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->ดึงข้อมูล (PDO::FETCH_BOTH);

หลังจากดำเนินการค้นหาด้วยโหมดนี้กับตารางทดสอบของดาวเคราะห์ เราจะได้ผลลัพธ์ดังต่อไปนี้:

อาร์เรย์ ( => 1 => 1 => ดิน => ดิน => สีน้ำเงิน => สีน้ำเงิน)

PDO::FETCH_ASSOC

ผลลัพธ์จะถูกจัดเก็บไว้ในอาเรย์แบบเชื่อมโยงโดยคีย์คือชื่อคอลัมน์ และค่าคือค่าแถวที่สอดคล้องกัน:

$stmt = $pdo->query("SELECT * FROM planets"); $results = $stmt->ดึงข้อมูล (PDO::FETCH_ASSOC);

เป็นผลให้เราได้รับ:

อาร์เรย์ ( => 1 => ดิน => สีน้ำเงิน)

PDO::FETCH_NUM

เมื่อใช้โหมดนี้ ผลลัพธ์จะแสดงเป็นอาร์เรย์ที่จัดทำดัชนีตามหมายเลขคอลัมน์ (เริ่มจาก 0):

อาร์เรย์ ( => 1 => ดิน => สีน้ำเงิน)

PDO::FETCH_COLUMN

ตัวเลือกนี้มีประโยชน์หากคุณต้องการรับรายการค่าสำหรับหนึ่งฟิลด์ในรูปแบบของอาร์เรย์หนึ่งมิติซึ่งการกำหนดหมายเลขจะเริ่มต้นจาก 0 ตัวอย่างเช่น:

$stmt = $pdo->query("เลือกชื่อจากดาวเคราะห์");

เป็นผลให้เราได้รับ:

อาร์เรย์ ( => โลก => ดาวอังคาร => ดาวพฤหัสบดี)

PDO::FETCH_KEY_PAIR

เราใช้ตัวเลือกนี้หากเราต้องการรับรายการค่าของสองฟิลด์ในรูปแบบของอาร์เรย์ที่เชื่อมโยง คีย์อาร์เรย์คือข้อมูลในคอลัมน์แรกของการเลือก ส่วนค่าอาร์เรย์คือข้อมูลในคอลัมน์ที่สอง ตัวอย่างเช่น:

$stmt = $pdo->query("เลือกชื่อ, สีจากดาวเคราะห์"); $result = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

เป็นผลให้เราได้รับ:

อาร์เรย์ ( => สีน้ำเงิน => สีแดง => แปลก)

PDO::FETCH_OBJECT

เมื่อใช้ PDO::FETCH_OBJECT ออบเจ็กต์ที่ไม่ระบุชื่อจะถูกสร้างขึ้นสำหรับแต่ละแถวที่ดึงข้อมูล คุณสมบัติสาธารณะของมันคือชื่อของคอลัมน์ตัวอย่าง และผลลัพธ์แบบสอบถามจะถูกใช้เป็นค่า:

$stmt = $pdo->query("เลือกชื่อ, สีจากดาวเคราะห์"); $results = $stmt->ดึงข้อมูล (PDO::FETCH_OBJ);

เป็นผลให้เราได้รับ:

วัตถุ StdClass ( => ดิน => สีน้ำเงิน)

PDO::FETCH_CLASS

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

Class Planet ( private $name; private $color; public function setName($planet_name) ( $this->name = $planet_name; ) public function setColor($planet_color) ( $this->color = $planet_color; ) public function getName () ( return $this->name; ) ฟังก์ชั่นสาธารณะ getColor() ( return $this->color; ) )

โปรดทราบว่าคลาส Planet มีคุณสมบัติส่วนตัวและไม่มีตัวสร้าง ตอนนี้เรามาดำเนินการตามคำขอกัน

หากคุณใช้วิธีดึงข้อมูลกับ PDO::FETCH_CLASS คุณต้องใช้วิธี setFetchMode ก่อนที่จะส่งคำขอเพื่อดึงข้อมูล:

$stmt = $pdo->query("เลือกชื่อ, สีจากดาวเคราะห์"); $stmt->setFetchMode(PDO::FETCH_CLASS, "ดาวเคราะห์");

พารามิเตอร์แรกที่เราส่งไปยังเมธอด setFetchMode คือค่าคงที่ PDO::FETCH_CLASS พารามิเตอร์ตัวที่สองคือชื่อของคลาสที่จะใช้เมื่อสร้างวัตถุ ตอนนี้เรามาทำกัน:

$planet = $stmt->ดึงข้อมูล(); var_dump($ดาวเคราะห์);

เป็นผลให้เราได้รับวัตถุ Planet:

วัตถุดาวเคราะห์ ( => โลก => สีน้ำเงิน)

ค่าที่ส่งคืนโดยแบบสอบถามถูกกำหนดให้กับคุณสมบัติที่สอดคล้องกันของวัตถุ แม้แต่คุณสมบัติส่วนตัวก็ตาม

การกำหนดคุณสมบัติหลังการดำเนินการคอนสตรัคเตอร์

คลาส Planet ไม่มี Constructor ที่ชัดเจน ดังนั้นจึงไม่มีปัญหาในการกำหนดคุณสมบัติ หากคลาสมีตัวสร้างที่กำหนดหรือเปลี่ยนแปลงคุณสมบัติ คุณสมบัติเหล่านั้นจะถูกเขียนทับ

เมื่อใช้ค่าคงที่ FETCH_PROPS_LATE ค่าคุณสมบัติจะถูกกำหนดค่าหลังจากดำเนินการตัวสร้าง:

Class Planet ( private $name; private $color; public function __construct($name = moon, $color = grey) ( $this->name = $name; $this->color = $color; ) ฟังก์ชั่นสาธารณะ setName($ planet_name) ( $this->name = $planet_name; ) ฟังก์ชั่นสาธารณะ setColor($planet_color) ( $this->color = $planet_color; ) ฟังก์ชั่นสาธารณะ getName() ( return $this->name; ) ฟังก์ชั่นสาธารณะ getColor() ( return $this->color; ) )

เราแก้ไขคลาส Planet โดยเพิ่มตัวสร้างที่รับอาร์กิวเมนต์สองตัวเป็นอินพุต: ชื่อและสี ค่าเริ่มต้นสำหรับฟิลด์เหล่านี้คือพระจันทร์และสีเทาตามลำดับ

หากคุณไม่ได้ใช้ FETCH_PROPS_LATE คุณสมบัติจะถูกเขียนทับด้วยค่าเริ่มต้นเมื่อวัตถุถูกสร้างขึ้น เรามาตรวจสอบกัน ขั้นแรกให้เรียกใช้แบบสอบถาม:

$stmt = $pdo->query("เลือกชื่อ, สีจากระบบสุริยะ WHERE name = "earth""); $stmt->setFetchMode(PDO::FETCH_CLASS, "ดาวเคราะห์"); $planet = $stmt->ดึงข้อมูล(); var_dump($ดาวเคราะห์);

เป็นผลให้เราได้รับ:

Object(Planet)#2 (2) ( ["name":Planet":private]=> string(4) "moon" ["color"Planet":private]=> string(4) "gray" )

ตามที่คาดไว้ ค่าที่ดึงมาจากฐานข้อมูลจะถูกเขียนทับ ตอนนี้เรามาดูการแก้ปัญหาโดยใช้ FETCH_PROPS_LATE (คำขอที่คล้ายกัน):

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "ดาวเคราะห์"); $planet = $stmt->ดึงข้อมูล(); var_dump($ดาวเคราะห์);

เป็นผลให้เราได้รับสิ่งที่เราต้องการ:

Object(Planet)#4 (2) ( ["name":Planet":private]=> string(5) "earth" ["color"Planet":private]=> string(4) "blue" )

หากตัวสร้างคลาสไม่มีค่าเริ่มต้น แต่จำเป็น พารามิเตอร์ตัวสร้างจะถูกตั้งค่าเมื่อเรียกใช้เมธอด setFetchMode ด้วยอาร์กิวเมนต์ที่สามในรูปแบบของอาร์เรย์ ตัวอย่างเช่น:

Class Planet ( private $name; private $color; public function __construct($name, $color) ( $this->name = $name; $this->color = $color; ) [...] )

จำเป็นต้องมีอาร์กิวเมนต์ของ Constructor ดังนั้นมาเริ่มกันเลย:

$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, "ดาวเคราะห์", ["ดวงจันทร์", "สีเทา"]);

พารามิเตอร์ขาเข้ายังทำหน้าที่เป็นค่าเริ่มต้นที่จำเป็นสำหรับการเริ่มต้นอีกด้วย ในอนาคตจะถูกเขียนทับด้วยค่าจากฐานข้อมูล

ในกรณีนี้ พารามิเตอร์ที่เราระบุทำหน้าที่เป็นค่าพื้นฐานที่จำเป็นสำหรับวัตถุในการทำงานโดยไม่มีข้อผิดพลาดเท่านั้น โดยจะถูกเขียนทับด้วยค่าจากฐานข้อมูล

ผลลัพธ์หลายรายการจะถูกดึงออกมาเป็นวัตถุโดยใช้วิธีการดึงข้อมูลภายในลูป while:

ในขณะที่ ($planet = $stmt->fetch()) ( // การประมวลผลผลลัพธ์ )

หรือโดยการสุ่มตัวอย่างผลลัพธ์ทั้งหมดพร้อมกัน ในกรณีที่สอง จะใช้เมธอด fetchAll และโหมดจะถูกระบุในขณะที่มีการโทร:

$stmt->fetchAll(PDO::FETCH_CLASS|PDO_FETCH_PROPS_LATE, "ดาวเคราะห์", ["ดวงจันทร์", "สีเทา"]);

PDO::FETCH_INTO

เมื่อเลือกตัวเลือกการเลือกนี้ PDO จะไม่สร้างออบเจ็กต์ใหม่ แต่จะอัปเดตคุณสมบัติของออบเจ็กต์ที่มีอยู่ อย่างไรก็ตาม สิ่งนี้เป็นไปได้สำหรับทรัพย์สินสาธารณะหรือเมื่อใช้เมธอด __set magic กับออบเจ็กต์เท่านั้น

จัดทำและร้องขอโดยตรง

มีสองวิธีในการดำเนินการค้นหาใน PDO:

  • ตรงซึ่งประกอบด้วยขั้นตอนเดียว
  • เตรียมไว้ซึ่งประกอบด้วยสองขั้นตอน

คำขอโดยตรง

มีสองวิธีในการสืบค้นโดยตรง:

  • แบบสอบถามใช้สำหรับคำสั่งที่ไม่ทำการเปลี่ยนแปลง เช่น SELECT ส่งกลับวัตถุ PDOStatemnt ซึ่งดึงผลลัพธ์แบบสอบถามโดยใช้วิธีการดึงข้อมูลหรือ fetchAll
  • exec ใช้สำหรับคำสั่งเช่น INSERT, DELETE หรือ UPDATE ส่งกลับจำนวนแถวที่ประมวลผลตามคำขอ

ตัวดำเนินการโดยตรงจะใช้เฉพาะในกรณีที่ไม่มีตัวแปรในการสืบค้น และคุณมั่นใจว่าการสืบค้นนั้นปลอดภัยและมีการหลีกอย่างเหมาะสม

แบบสอบถามที่เตรียมไว้

PDO รองรับคำสั่งที่เตรียมไว้ซึ่งมีประโยชน์ในการปกป้องแอปพลิเคชันจาก : วิธีการเตรียมดำเนินการหลบหนีที่จำเป็น

ลองดูตัวอย่าง คุณต้องการแทรกคุณสมบัติของวัตถุ Planet ลงในตาราง Planets ขั้นแรก มาเตรียมคำขอกันก่อน:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(?, ?)");

เราใช้วิธีการจัดเตรียม ซึ่งใช้แบบสอบถาม SQL ที่มีตัวแปรเทียม (ตัวยึดตำแหน่ง) เป็นอาร์กิวเมนต์ Pseudovariables สามารถมีได้สองประเภท: ไม่มีชื่อและตั้งชื่อ

ตัวแปรหลอกที่ไม่มีชื่อ

ตัวแปรหลอกที่ไม่มีชื่อ (ตัวยึดตำแหน่ง) จะมีเครื่องหมาย ? - แบบสอบถามผลลัพธ์มีขนาดกะทัดรัด แต่ต้องทดแทนค่าในลำดับเดียวกัน พวกเขาจะถูกส่งผ่านเป็นอาร์เรย์ผ่านวิธีการดำเนินการ:

$stmt->execute([$planet->ชื่อ, $planet->สี]);

ชื่อตัวแปรหลอก

เมื่อใช้ตัวยึดตำแหน่งที่มีชื่อ ลำดับการส่งค่าสำหรับการทดแทนนั้นไม่สำคัญ แต่โค้ดในกรณีนี้จะมีขนาดกะทัดรัดน้อยลง ข้อมูลจะถูกส่งผ่านไปยังวิธีการดำเนินการในรูปแบบของอาเรย์แบบเชื่อมโยง ซึ่งแต่ละคีย์สอดคล้องกับชื่อของตัวแปรเทียม และค่าของอาเรย์สอดคล้องกับค่าที่ต้องทดแทนในคำขอ เรามาทำซ้ำตัวอย่างก่อนหน้านี้:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->execute(["name" => $planet->name, "color" => $planet->color]);

วิธีการจัดเตรียมและดำเนินการจะใช้ทั้งเมื่อดำเนินการร้องขอการเปลี่ยนแปลงและเมื่อดึงข้อมูล

และข้อมูลเกี่ยวกับจำนวนแถวที่ประมวลผล หากจำเป็น จะได้รับจากวิธี rowCount

การควบคุมพฤติกรรมข้อผิดพลาด PDO

พารามิเตอร์การเลือกโหมดข้อผิดพลาด PDO::ATTR_ERRMODE ใช้เพื่อกำหนดว่า PDO ทำงานอย่างไรในกรณีที่เกิดข้อผิดพลาด มีสามตัวเลือกให้เลือก: PDO::ERRMODE_SILENT , PDO::ERRMODE_EXCEPTION และ PDO::ERRMODE_WARNING

PDO::ERRMODE_SILENT

ตัวเลือกเริ่มต้น PDO จะบันทึกข้อมูลเกี่ยวกับข้อผิดพลาด ซึ่งวิธี errorCode และ errorInfo จะช่วยให้คุณได้รับ

PDO::ERRMODE_EXCEPTION

นี่คือตัวเลือกที่ต้องการโดยที่ PDO ส่งข้อยกเว้น (PDOException) นอกเหนือจากข้อมูลข้อผิดพลาด ข้อยกเว้นขัดจังหวะการทำงานของสคริปต์ ซึ่งมีประโยชน์เมื่อใช้ธุรกรรม PDO ตัวอย่างระบุไว้ในคำอธิบายของธุรกรรม

PDO::ERRMODE_WARNING

ในกรณีนี้ PDO จะบันทึกข้อมูลข้อผิดพลาดด้วย โฟลว์สคริปต์ไม่ถูกขัดจังหวะ แต่มีการออกคำเตือน

วิธีbindValueและbindParam

คุณยังสามารถใช้วิธีbindValueและbindParamเพื่อทดแทนค่าในแบบสอบถามได้ ประการแรกเชื่อมโยงค่าของตัวแปรกับตัวแปรหลอกที่ใช้ในการเตรียมคำขอ:

$stmt = $pdo->prepare("INSERT INTO planets(name, color) VALUES(:name, :color)"); $stmt->bindValue("ชื่อ", $planet->ชื่อ, PDO::PARAM_STR);

เชื่อมโยงค่าของตัวแปร $planet->name กับตัวแปรหลอก:name โปรดทราบว่าเมื่อใช้เมธอดbindValueและbindParam ประเภทของตัวแปรจะถูกระบุเป็นอาร์กิวเมนต์ที่สามโดยใช้ค่าคงที่ PDO ที่เหมาะสม ในตัวอย่าง - PDO::PARAM_STR

วิธีการbindParamผูกตัวแปรกับตัวแปรหลอก ในกรณีนี้ ตัวแปรจะเชื่อมโยงกับการอ้างอิงตัวแปรหลอก และค่าจะถูกแทรกลงในแบบสอบถามหลังจากเรียกใช้เมธอดการดำเนินการเท่านั้น ลองดูตัวอย่าง:

$stmt->bindParam("ชื่อ", $planet->ชื่อ, PDO::PARAM_STR);

การทำธุรกรรมใน PDO

ลองนึกภาพตัวอย่างที่ไม่ธรรมดา ผู้ใช้จำเป็นต้องเลือกรายการดาวเคราะห์ และทุกครั้งที่ดำเนินการคำขอ ข้อมูลปัจจุบันจะถูกลบออกจากฐานข้อมูล จากนั้นจึงแทรกข้อมูลใหม่เข้าไป หากเกิดข้อผิดพลาดหลังจากการลบ ผู้ใช้รายถัดไปจะได้รับรายการว่าง เพื่อหลีกเลี่ยงปัญหานี้ เราใช้ธุรกรรม:

$pdo->beginTransaction(); ลอง ( $stmt1 = $pdo->exec("DELETE FROM planets"); $stmt2 = $pdo->prepare("INSERT INTO planets(name, color) VALUES (?, ?)"); foreach ($planets as $planet) ( $stmt2->execute([$planet->getName(), $planet->getColor()]); ) $pdo->commit() ) catch (PDOException $e) ( $pdo-> rollBack ();

เมธอด beginningTransaction จะปิดใช้งานการดำเนินการคำขอโดยอัตโนมัติ และภายในโครงสร้าง try-catch คำขอจะถูกดำเนินการตามลำดับที่ต้องการ หากไม่มี PDOExceptions ถูกส่งออกไป การร้องขอจะเสร็จสมบูรณ์โดยใช้วิธีการคอมมิต มิฉะนั้น พวกเขาจะถูกย้อนกลับโดยใช้วิธีการย้อนกลับ และการดำเนินการค้นหาอัตโนมัติจะถูกกู้คืน

สิ่งนี้สร้างความสอดคล้องในการดำเนินการค้นหา เห็นได้ชัดว่าเพื่อให้สิ่งนี้เกิดขึ้น PDO::ATTR_ERRMODE จะต้องตั้งค่าเป็น PDO::ERRMODE_EXCEPTION

บทสรุป

ตอนนี้เราได้อธิบายการทำงานกับ PDO แล้ว เรามาดูข้อดีหลักๆ กัน:

  • ด้วย PDO ทำให้ง่ายต่อการถ่ายโอนแอปพลิเคชันไปยัง DBMS อื่น
  • รองรับ DBMS ยอดนิยมทั้งหมด
  • ระบบการจัดการข้อผิดพลาดในตัว
  • ตัวเลือกต่าง ๆ สำหรับการนำเสนอผลลัพธ์ตัวอย่าง
  • รองรับการสืบค้นที่เตรียมไว้ซึ่งทำให้โค้ดสั้นลงและทำให้ทนทานต่อการฉีด SQL
  • รองรับธุรกรรม ซึ่งช่วยรักษาความสมบูรณ์ของข้อมูลและความสอดคล้องของแบบสอบถามเมื่อผู้ใช้ทำงานแบบขนาน

อเล็กซานเดอร์ นาลิไวโก นักแปล

Yandex ใช้ข้อมูลและการเรียนรู้ของเครื่องของคุณเพื่อปรับแต่งบริการอย่างไร -












PDO มีวิธีการเชื่อมต่อที่ชาญฉลาดของตัวเองที่เรียกว่า . นอกจากนี้ ในระหว่างการเชื่อมต่อ คุณยังสามารถตั้งค่าตัวเลือกต่าง ๆ มากมาย ซึ่งบางตัวเลือกก็มีประโยชน์อย่างมาก คุณสามารถดูรายการทั้งหมดได้ แต่มีเพียงไม่กี่รายการเท่านั้นที่สำคัญ

ตัวอย่างการเชื่อมต่อที่ถูกต้อง:

$โฮสต์ = "127.0.0.1" ;
$db = "ทดสอบ" ;
$user = "รูท" ;
$ผ่าน = "" ;
$charset = "utf8" ;

$dsn = "mysql:host= $host ;dbname= $db ;charset= $charset " ;
$เลือก = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => เท็จ
];
$pdo = PDO ใหม่ ($dsn, $ผู้ใช้, $pass, $opt);

เกิดอะไรขึ้นที่นี่?

$dsn ระบุประเภทของฐานข้อมูลที่เราจะใช้งาน (mysql) โฮสต์ ชื่อฐานข้อมูล และชุดอักขระ
- ตามด้วยชื่อผู้ใช้และรหัสผ่าน
- หลังจากนั้นจะมีการระบุอาร์เรย์ของตัวเลือกต่างๆ ซึ่งไม่ได้ระบุไว้ในคู่มือใดๆ

แม้ว่าอาเรย์นี้จะมีประโยชน์อย่างมากดังที่กล่าวไว้ข้างต้น สิ่งที่สำคัญที่สุดคือควรตั้งค่าโหมดข้อผิดพลาดในรูปแบบของข้อยกเว้นเท่านั้น
- ประการแรก เนื่องจากในโหมดอื่นๆ ทั้งหมด PDO จะไม่รายงานสิ่งที่เข้าใจได้เกี่ยวกับข้อผิดพลาด
- ประการที่สอง เนื่องจากข้อยกเว้นจะมีการติดตามสแต็กที่ไม่สามารถถูกแทนที่ได้เสมอ
- ประการที่สาม ข้อยกเว้นสะดวกอย่างยิ่งในการจัดการ

นอกจากนี้ การตั้งค่า FETCH_MODE เป็นค่าเริ่มต้นยังสะดวกมาก เพื่อไม่ให้เขียนลงในทุกคำขอ เนื่องจากแฮมสเตอร์ที่ขยันหมั่นเพียรชอบทำ
นอกจากนี้คุณยังสามารถตั้งค่าโหมด pconnect การจำลองสำนวนที่เตรียมไว้ และคำที่น่ากลัวอื่น ๆ อีกมากมายได้ที่นี่

เป็นผลให้เราได้รับตัวแปร $pdo ซึ่งเราใช้งานตลอดทั้งสคริปต์

คุณสามารถใช้สองวิธีในการดำเนินการค้นหา
หากไม่มีการส่งตัวแปรไปยังคำขอ คุณสามารถใช้ฟังก์ชัน query() ได้ มันจะดำเนินการตามคำขอและส่งคืนออบเจ็กต์พิเศษ - คำสั่ง PDO โดยคร่าวๆ คุณสามารถเปรียบเทียบกับทรัพยากร mysql ซึ่งส่งคืนโดย mysql_query() คุณสามารถรับข้อมูลจากออบเจ็กต์นี้ได้ด้วยวิธีดั้งเดิม ผ่าน while หรือผ่าน foreach() คุณยังสามารถขอให้ส่งคืนข้อมูลที่ได้รับในรูปแบบพิเศษซึ่งจะกล่าวถึงด้านล่างนี้
$stmt = $pdo -> แบบสอบถาม ("เลือกชื่อจากผู้ใช้" );
ในขณะที่ ($row = $stmt -> fetch())
{
}

หากมีการส่งผ่านตัวแปรอย่างน้อยหนึ่งรายการไปยังคำขอ การร้องขอนี้จะต้องดำเนินการผ่านเท่านั้น การแสดงออกที่เตรียมไว้- มันคืออะไร? นี่คือแบบสอบถาม SQL ปกติซึ่งมีการวางเครื่องหมายพิเศษแทนตัวแปร - ตัวยึดตำแหน่ง PDO รองรับตัวยึดตำแหน่ง (?) ซึ่งลำดับของตัวแปรที่ส่งผ่านมีความสำคัญ และตัวยึดตำแหน่งที่มีชื่อ (:name) ซึ่งลำดับนั้นไม่สำคัญ ตัวอย่าง:
$sql = ;
$sql = ;

หากต้องการดำเนินการค้นหาดังกล่าว จะต้องเตรียมโดยใช้ฟังก์ชันเตรียม () ก่อน นอกจากนี้ยังส่งคืนคำสั่ง PDO แต่ยังไม่มีข้อมูลใดๆ คุณต้องดำเนินการตามคำขอนี้โดยส่งตัวแปรเข้าไปก่อนหน้านี้เพื่อให้ได้มา คุณสามารถโอนได้สองวิธี:
บ่อยครั้ง คุณสามารถดำเนินการกับเมธอดดำเนินการ () โดยส่งผ่านอาร์เรย์ของตัวแปรไปให้กับมัน:
$stmt = $pdo -> เตรียม ( "เลือกชื่อจากผู้ใช้โดยที่อีเมล = ?");
$stmt -> ดำเนินการ (อาร์เรย์($อีเมล ));

$stmt = $pdo -> เตรียม ( "เลือกชื่อจากผู้ใช้ WHERE email = :email");
$stmt -> ดำเนินการ (array("email" => $email ));
อย่างที่คุณเห็น ในกรณีของตัวยึดที่มีชื่อ จะต้องส่งอาร์เรย์ที่คีย์จะต้องตรงกับชื่อของตัวยึดตำแหน่งเพื่อดำเนินการ ()

บางครั้งอาจต้องใช้วิธีที่สองซึ่งแทบจะไม่จำเป็นเลย เมื่อตัวแปรถูกผูกไว้กับคำขอครั้งแรกทีละรายการ โดยใช้ bindValue() / bindParam() จากนั้นจึงดำเนินการเท่านั้น ในกรณีนี้ ไม่มีสิ่งใดถูกส่งผ่านไปยังการดำเนินการ() ตัวอย่างสามารถพบได้ในคู่มือ
เมื่อใช้วิธีนี้ ควรใช้ bindValue() เสมอหรือไม่ เนื่องจากพฤติกรรมของ bindParam() ไม่ชัดเจนสำหรับผู้เริ่มต้นและจะนำไปสู่ปัญหา

จากนั้นคุณสามารถใช้คำสั่ง PDO ได้ในลักษณะเดียวกับข้างต้น ตัวอย่างเช่น ผ่าน foreach:
$stmt = $pdo -> เตรียม ( "เลือกชื่อจากผู้ใช้โดยที่อีเมล = ?");
$stmt ->
foreach ($stmt เป็น $row )
{
echo $row [ "ชื่อ" ] "\n" ;
}

สำคัญ:สำนวนที่เตรียมไว้เป็นเหตุผลหลักที่ต้องใช้ PDO เพราะมัน วิธีเดียวที่ปลอดภัยการดำเนินการค้นหา SQL ที่เกี่ยวข้องกับตัวแปร

นอกจากนี้ยังสามารถใช้เตรียม () / ดำเนินการ () เพื่อดำเนินการแบบสอบถามที่เตรียมไว้ซ้ำ ๆ ด้วยชุดข้อมูลที่แตกต่างกัน ในทางปฏิบัติสิ่งนี้มีความจำเป็นน้อยมากและไม่ทำให้ความเร็วเพิ่มขึ้นมากนัก แต่ในกรณีที่คุณต้องการสร้างแบบสอบถามประเภทเดียวกันจำนวนมาก คุณสามารถเขียนได้ดังนี้:

$ข้อมูล = อาร์เรย์(
1 => 1000,
5 => 300,
9 => 200,
);

$stmt = $pdo -> เตรียม ( "อัปเดตผู้ใช้ ตั้งค่าโบนัส = โบนัส + ? WHERE id = ?");
foreach ($ข้อมูลเป็น $id => $โบนัส)
{
$stmt -> ดำเนินการ ([ $โบนัส , $id ]);
}

ที่นี่เราเตรียมคำขอหนึ่งครั้งแล้วดำเนินการหลายครั้ง

เราคุ้นเคยกับเมธอด fetch() แล้ว ซึ่งใช้เพื่อรับแถวจากฐานข้อมูลตามลำดับ เมธอดนี้เป็นอะนาล็อกของฟังก์ชัน mysq_fetch_array() และฟังก์ชันที่คล้ายกัน แต่ทำหน้าที่แตกต่างออกไป แทนที่จะใช้หลายฟังก์ชัน กลับใช้ฟังก์ชันหนึ่งที่นี่ แต่ลักษณะการทำงานของวิธีนี้ถูกระบุโดยพารามิเตอร์ที่ส่งผ่าน ฉันจะเขียนเกี่ยวกับพารามิเตอร์เหล่านี้โดยละเอียดในภายหลัง แต่ตามคำแนะนำสั้นๆ ฉันขอแนะนำให้ใช้ fetch() ในโหมด FETCH_LAZY:
$stmt = $pdo -> เตรียม ( "เลือกชื่อจากผู้ใช้โดยที่อีเมล = ?");
$stmt -> ดำเนินการ([ $_GET [ "อีเมล" ]]);
ในขณะที่ ($row = $stmt -> ดึงข้อมูล (PDO :: FETCH_LAZY ))
{
เสียงสะท้อน $ แถว [ 0 ] . "\n" ;
echo $row [ "ชื่อ" ] "\n" ;
echo $row -> ชื่อ "\n" ;
}

ในโหมดนี้ จะไม่เปลืองหน่วยความจำเพิ่มเติม และนอกจากนั้น คอลัมน์ยังสามารถเข้าถึงได้ด้วยวิธีใดวิธีหนึ่งจากสามวิธี - ผ่านดัชนี ชื่อ หรือคุณสมบัติ

คำสั่ง PDO ยังมีฟังก์ชันตัวช่วยในการรับค่าของคอลัมน์เดียว จะสะดวกมากหากเราขอเพียงฟิลด์เดียว - ในกรณีนี้ จำนวนการเขียนจะลดลงอย่างมาก:
$stmt = $pdo -> เตรียม ( "เลือกชื่อจากตาราง โดยที่ id=?");
$stmt -> ดำเนินการ (อาร์เรย์($id ));
$name = $stmt -> fetchColumn();

แต่ฟังก์ชันที่น่าสนใจที่สุดซึ่งมีฟังก์ชันการทำงานที่ดีที่สุดคือ fetchAll() ด้วยเหตุนี้เองที่ทำให้ PDO เป็นไลบรารีระดับสูงสำหรับการทำงานกับฐานข้อมูล ไม่ใช่แค่ไดรเวอร์ระดับต่ำเท่านั้น

FetchAll() ส่งคืนอาร์เรย์ที่ประกอบด้วยแถวทั้งหมดที่แบบสอบถามส่งคืน ซึ่งสามารถสรุปได้ 2 ประการ คือ
1. ไม่ควรใช้ฟังก์ชันนี้เมื่อแบบสอบถามส่งคืนข้อมูลจำนวนมาก ในกรณีนี้ ควรใช้การวนซ้ำแบบดั้งเดิมพร้อมกับ fetch()
2. เนื่องจากในแอปพลิเคชัน PHP ยุคใหม่ ข้อมูลจะไม่ถูกส่งออกทันทีที่ได้รับ แต่จะถูกถ่ายโอนไปยังเทมเพลตเพื่อจุดประสงค์นี้ fetchAll() จึงกลายเป็นสิ่งที่ไม่สามารถถูกแทนที่ได้ ช่วยให้คุณหลีกเลี่ยงการเขียนลูปด้วยตนเอง และด้วยเหตุนี้ จึงช่วยลดจำนวนโค้ด

รับอาร์เรย์อย่างง่าย
ฟังก์ชันนี้ถูกเรียกโดยไม่มีพารามิเตอร์ โดยจะส่งกลับอาร์เรย์ที่จัดทำดัชนีปกติซึ่งมีแถวจากฐานข้อมูล ในรูปแบบที่ระบุใน FETCH_MODE ตามค่าเริ่มต้น ค่าคงที่ PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ สามารถเปลี่ยนรูปแบบได้ทันที

รับคอลัมน์
บางครั้งคุณจำเป็นต้องได้อาร์เรย์หนึ่งมิติง่ายๆ โดยการขอฟิลด์เดียวจากสตริงจำนวนมาก เมื่อต้องการทำเช่นนี้ ให้ใช้โหมด PDO::FETCH_COLUMN
$data = $pdo -> แบบสอบถาม ("เลือกชื่อจากผู้ใช้" ) -> fetchAll (PDO :: FETCH_COLUMN );
อาร์เรย์ (
0 => "จอห์น" ,
1 => "ไมค์" ,
2 => "แมรี่" ,
3 => "แคธี่" ,
)

กำลังดึงข้อมูลคู่คีย์-ค่า
เป็นรูปแบบยอดนิยมเมื่อต้องการรับคอลัมน์เดียวกัน แต่ไม่ได้จัดทำดัชนีตามตัวเลข แต่ตามฟิลด์ใดฟิลด์หนึ่ง ค่าคงที่ PDO::FETCH_KEY_PAIR มีหน้าที่รับผิดชอบในเรื่องนี้
$data = $pdo -> แบบสอบถาม ("เลือก id, ชื่อจากผู้ใช้" ) -> fetchAll (PDO :: FETCH_KEY_PAIR );
อาร์เรย์ (
104 => "จอห์น" ,
110 => "ไมค์" ,
120 => "แมรี่" ,
121 => "แคธี่" ,
)

รับแถวทั้งหมดจัดทำดัชนีโดยเขตข้อมูล
บ่อยครั้งที่จำเป็นต้องดึงแถวทั้งหมดจากฐานข้อมูล แต่ไม่ได้จัดทำดัชนีด้วยตัวเลข แต่ตามเขตข้อมูลเฉพาะ ค่าคงที่ PDO::FETCH_UNIQUE ทำสิ่งนี้
$data = $pdo -> แบบสอบถาม ("เลือก * จากผู้ใช้") -> fetchAll (PDO :: FETCH_UNIQUE );
อาร์เรย์ (
104 => อาร์เรย์ (
"name" => "จอห์น" ,
"รถยนต์" => "โตโยต้า" ,
),
110 => อาร์เรย์ (
"ชื่อ" => "ไมค์" ,
"รถยนต์" => "ฟอร์ด" ,
),
120 => อาร์เรย์ (
"name" => "แมรี่" ,
"รถยนต์" => "มาสด้า" ,
),
121 => อาร์เรย์ (
"name" => "เคธี่" ,
"รถยนต์" => "มาสด้า" ,
),
)

ควรจำไว้ว่าคุณต้องเลือกฟิลด์ที่ไม่ซ้ำกันก่อนในคอลัมน์

มีโหมดการเก็บข้อมูลที่แตกต่างกันมากกว่าหนึ่งและครึ่งโหลใน PDO นอกจากนี้คุณยังสามารถรวมมันเข้าด้วยกันได้! แต่นี่เป็นหัวข้อสำหรับบทความแยกต่างหาก

เมื่อทำงานกับนิพจน์ที่เตรียมไว้ คุณควรเข้าใจว่าตัวยึดตำแหน่งสามารถแทนที่ได้เฉพาะสตริงหรือตัวเลขเท่านั้น ไม่สามารถแทนที่คำหลัก ตัวระบุ หรือส่วนหนึ่งของสตริงหรือชุดสตริงผ่านตัวยึดตำแหน่งได้ ดังนั้น สำหรับ LIKE คุณต้องเตรียมสตริงการค้นหาทั้งหมดก่อน จากนั้นจึงแทนที่ลงในข้อความค้นหา:

$ชื่อ = "% $ชื่อ %" ;
$stm = $pdo -> เตรียม ( "SELECT * จากตาราง ชื่อ LIKE อยู่ที่ไหน?");
$stm -> ดำเนินการ (อาร์เรย์($ชื่อ ));
$data = $stm -> fetchAll();

คุณก็เข้าใจแล้ว ทุกอย่างก็แย่ที่นี่เช่นกัน PDO ไม่มีเครื่องมือใด ๆ สำหรับการทำงานกับตัวระบุ และจะต้องจัดรูปแบบด้วยวิธีที่ล้าสมัยด้วยตนเอง (หรืออย่างไรก็ตาม ให้มองไปที่ SafeMysql ซึ่งเช่นเดียวกับปัญหาอื่น ๆ อีกมากมาย ได้รับการแก้ไขอย่างง่ายดายและสวยงาม)
ควรจำไว้ว่ากฎสำหรับการจัดรูปแบบตัวระบุจะแตกต่างกันไปสำหรับฐานข้อมูลที่ต่างกัน

ใน mysql หากต้องการจัดรูปแบบตัวระบุด้วยตนเอง คุณต้องทำสองสิ่ง:
- ใส่ไว้ใน backticks ("`")
- ค้นหาอักขระเหล่านี้ภายในตัวระบุโดยการเพิ่มเป็นสองเท่า

$ฟิลด์ = "`" . str_replace ("`" , "``" , $_GET [ "ฟิลด์" ]) -
$sql = $ฟิลด์ " ;

อย่างไรก็ตามมีข้อแม้ประการหนึ่งที่นี่ การจัดรูปแบบเพียงอย่างเดียวอาจไม่เพียงพอ โค้ดด้านบนปกป้องเราจากการแทรกแบบคลาสสิก แต่ในบางกรณี ศัตรูยังสามารถเขียนสิ่งที่ไม่ต้องการได้ หากเราแทนที่ชื่อฟิลด์และตารางลงในแบบสอบถามโดยตรงโดยไม่ไตร่ตรอง ตัวอย่างเช่น ในตารางผู้ใช้จะมีช่องผู้ดูแลระบบ หากไม่มีการกรองชื่อฟิลด์ที่เข้ามา คนโง่จะเขียนสิ่งที่น่ารังเกียจลงในฟิลด์นี้เมื่อสร้างคำขอจาก POST โดยอัตโนมัติ

ดังนั้นจึงแนะนำให้ตรวจสอบชื่อตารางและช่องที่มาจากผู้ใช้ว่าถูกต้องหรือไม่ ดังตัวอย่างด้านล่าง

โค้ดฝังตัวใด ๆ ที่สามารถเห็นได้ในบทช่วยสอนจำนวนมากนำมาซึ่งความเศร้าโศกและความปรารถนาที่จะฆ่าคนไม่พร่อง การก่อสร้างระยะทางหลายกิโลเมตรโดยใช้ชื่อเดียวกันซ้ำกัน - ในดัชนี $_POST ในชื่อตัวแปร ในชื่อฟิลด์ในคำขอ ในชื่อตัวยึดตำแหน่งในคำขอ ในชื่อตัวยึดตำแหน่งและชื่อตัวแปรเมื่อเชื่อมโยง
การดูโค้ดนี้ทำให้ฉันอยากจะฆ่าใครสักคน หรืออย่างน้อยก็ทำให้มันสั้นลงหน่อย

ซึ่งสามารถทำได้โดยใช้แบบแผนว่าชื่อฟิลด์ในแบบฟอร์มตรงกับชื่อฟิลด์ในตาราง จากนั้นชื่อเหล่านี้สามารถแสดงได้เพียงครั้งเดียว (เพื่อป้องกันการทดแทนดังที่กล่าวไว้ข้างต้น) และฟังก์ชันตัวช่วยขนาดเล็กสามารถใช้เพื่อรวบรวมแบบสอบถามซึ่งเนื่องจากลักษณะเฉพาะของ mysql จึงเหมาะสำหรับทั้ง INSERT และ UPDATE แบบสอบถาม:

ฟังก์ชั่น pdoSet ($allowed , & $values ​​​​, $source = array()) (
$set = "" ;
$values ​​​​= array();
ถ้า (! $source ) $source = & $_POST ;
foreach ($อนุญาตเป็น $field) (
ถ้า (isset($source [ $field ])) (
$set .= "`" . str_replace ("`" , "``" , $ฟิลด์ ) - "=: $ฟิลด์ , " ;
$values ​​​​[ $field ] = $source [ $field ];
}
}
กลับ substr ($ชุด, 0, - 2);
}

ดังนั้นโค้ดฝังจะเป็น

$allowed = array("ชื่อ" , "นามสกุล" , "อีเมล" ); // ฟิลด์ที่อนุญาต
$sql = "INSERT INTO users SET" . pdoSet ($อนุญาต, $values);
$stm = $dbh -> เตรียม ($sql );
$stm -> ดำเนินการ ($values);

และสำหรับการอัพเดต - นี่คือ:

$allowed = array("ชื่อ" , "นามสกุล" , "อีเมล" , "รหัสผ่าน" ); // ฟิลด์ที่อนุญาต
$_POST["รหัสผ่าน"] = MD5($_POST["login"]. $_POST["รหัสผ่าน"]);
$sql = "อัปเดตชุดผู้ใช้" pdoSet ($อนุญาต, $values) "อยู่ที่ไหน id = :id" ;
$stm = $dbh -> เตรียม ($sql );
$values ​​["id" ] = $_POST ["id" ];
$stm -> ดำเนินการ ($values);

ไม่น่าประทับใจมาก แต่มีประสิทธิภาพมาก ฉันขอเตือนคุณว่าหากคุณใช้ Class เพื่อทำงานกับ MySQL อย่างปลอดภัยและสะดวกสบาย ทั้งหมดนี้ทำได้ในสองบรรทัด

PDO และคำสำคัญ
เป็นไปไม่ได้ที่จะเกิดขึ้นนอกเหนือจากการกรองที่นี่ ดังนั้นจึงเป็นเรื่องโง่ที่จะเรียกใช้ตัวดำเนินการทั้งหมดที่ไม่ได้ระบุไว้โดยตรงในคำขอผ่านรายการสีขาว:

$dirs = array("ASC" , "DESC" );
$key = array_search($_GET["dir"], $dirs));
$dir = $คำสั่งซื้อ [ $key ];
$sql= "เลือก * จาก `ตาราง` เรียงลำดับตาม$ฟิลด์ $dir " ;



 


อ่าน:



จะทำอย่างไรถ้าคุณพัฒนาแบบออฟไลน์

จะทำอย่างไรถ้าคุณพัฒนาแบบออฟไลน์

ในที่สุดเธอก็ไปเยี่ยมชมตลาดเกมคอมพิวเตอร์ โดยส่องสว่างด้วยแสงจากสัตว์ประหลาดเอเลี่ยนและปืนไฮเทค แน่นอนว่าเป็นเรื่องไม่ธรรมดาเช่นนี้...

การทดสอบโปรเซสเซอร์ว่ามีความร้อนสูงเกินไป

การทดสอบโปรเซสเซอร์ว่ามีความร้อนสูงเกินไป

คุณต้องตรวจสอบอุณหภูมิของโปรเซสเซอร์หรือการ์ดแสดงผลอย่างต่อเนื่อง เพราะหากร้อนเกินไป พีซีของคุณก็จะไม่เริ่มทำงาน เกี่ยวกับเรื่องนี้...

บริการสาธารณะของ Yesia คืออะไร

บริการสาธารณะของ Yesia คืออะไร

ไปเป็นวันที่ไม่สามารถรับบริการของรัฐหรือเทศบาลได้หากไม่ได้ไปพบผู้บริหารเป็นการส่วนตัว...

ตำแหน่งของหัวบนเสาอากาศ

ตำแหน่งของหัวบนเสาอากาศ

บทความนี้เปิดเผยวิธีการหลักในการกำหนดราบโดยใช้เข็มทิศแม่เหล็กและสถานที่ที่เป็นไปได้ การใช้งาน...

ฟีดรูปภาพ อาร์เอสเอส