วิธีปรับแต่งคลาส wpdb และเพิ่มวิธีการใหม่

เผยแพร่แล้ว: 2018-07-10

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

การแก้ไขคลาส #wpdb เริ่มต้นนั้นไม่ซับซ้อน คุณสามารถเพิ่ม ลบ หรือแก้ไขได้อย่างง่ายดายเพียงไม่กี่วิธี ไม่จำเป็นต้องเปลี่ยนทั้งชั้น #เวิร์ดเพรส

คลิกเพื่อทวีต

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

ทำไมต้องแก้ไขคลาส wpdb?

แน่นอน wpdb มีทุกสิ่งที่คุณต้องการ!? WP ทั้งหมดถูกสร้างขึ้นบนนั้น ในทางเทคนิคนั้นถูกต้อง โดยใช้ $wpdb->query() คุณสามารถรันคำสั่ง SQL ใดๆ ก็ได้ แต่ด้วยตรรกะนั้น เราจะไม่มีทางมีหรือต้องการวิธีการเช่น $wpdb->insert() หรือ $wpdb->get_var() แต่ที่เราทำ เพราะพวกเขาประหยัดเวลา ลดจุดบกพร่อง และขจัดคำถามที่ไม่ดีออกไป แล้วฟังก์ชั่นไหนที่ขาดหายไป? ขึ้นอยู่กับโครงการที่คุณกำลังทำงานอยู่ เราต้องการการสนับสนุนสำหรับคำถามสองข้อนี้:

INSERT IGNORE INTO tbl_name ...
INSERT INTO tbl_name ... ON DUPLICATE KEY UPDATE ...

ขั้นตอนที่ #1 – สร้างดรอปอิน

ขั้นตอนการสร้าง DB drop-in นั้นเรียบง่าย และผลลัพธ์สุดท้ายก็จะถูกรวมเข้ากับ WP อย่างราบรื่น
สร้างไฟล์ชื่อ db.php และวางไว้ในโฟลเดอร์ /wp-content/ ให้ไฟล์เป็นส่วนหัวของปลั๊กอินมาตรฐานและสร้างคลาสที่ขยาย wpdb บางอย่างเช่นนี้:

<?php
/*
  Plugin Name: Extended wpdb
  Description: A few extra functions for wpdb
  Version: 1.0
  Author: WebFactory Ltd
*/

class wpdb_extended extends wpdb {

  public function __construct(){
    parent::__construct( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
  }

  public function test() {
    echo 'Extended wpdb is running.';
  }
}


global $wpdb;
$wpdb = new wpdb_extended();

ส่วนหัวค่อนข้างอธิบายตนเองได้ วิธีการสร้างทำให้แน่ใจว่าเราสร้างการเชื่อมต่อฐานข้อมูลใหม่เมื่อวัตถุถูกสร้างขึ้นและใช้ตัวสร้าง wpdb ดั้งเดิมสำหรับสิ่งนั้น ค่าคงที่ DB เหล่านั้นถูกกำหนดใน wp-config.php ดังที่เราได้กล่าวไปแล้วในตอนต้น เราเพียงแค่เพิ่มฟังก์ชันบางอย่างและนำอย่างอื่นมาใช้ใหม่ วิธีการ test() เป็นเพียงเพื่อดูว่าทุกอย่างถูกต้องหรือไม่

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

ขั้นตอน #2 – ทดสอบก่อนขุดลึก

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

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

global $wpdb;
$wpdb->test();
die;

เรียกใช้ admin หรือ front-end page แล้วคุณเห็นอะไร? “ wpdb แบบขยายกำลังทำงานอยู่ " สมบูรณ์แบบ. ตอนนี้สำหรับการทำงานในโลกแห่งความเป็นจริงของเรา

ขั้นตอน #3 – สร้าง แก้ไข หรือแทนที่ฟังก์ชัน

แบบสอบถาม INSERT IGNORE ดูเหมือนจะทำได้ง่าย เรามี $wpdb->insert() แล้ว ดังนั้นเราจึงขาดเพียงคำเดียว น่าเสียดาย เนื่องจากไม่มีตัวกรองในที่ที่ถูกต้อง โค้ดนี้จึงไม่ใช่โค้ดสองบรรทัด

หากคุณเปิด wp-db.php และไปที่เมธอด insert() ในบรรทัด #2100 คุณจะเห็นว่าใช้ _insert_replace_helper() จากบรรทัด #2151 และฟังก์ชันนั้นไม่มีตัวกรองหรือการดำเนินการเดียว เราไม่สามารถห่อฟังก์ชันได้ เนื่องจากฟังก์ชันจะส่งกลับผลลัพธ์ของคิวรีทันที ไม่ใช่ตัวคิวรีที่เราปรับเปลี่ยนได้ คนเกียจคร้าน เราจะต้องแทนที่ทั้งเมธอด insert() และ _insert_replace_helper() เราจะเพิ่มพารามิเตอร์พิเศษ – $ignore บูลีนที่มีค่าเริ่มต้น false

public function insert( $table, $data, $format = null, $ignore = false ) {
  return $this->_insert_replace_helper( $table, $data, $format, 'INSERT', $ignore = false );
}

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

function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT', $ignore = false ) {
  $this->insert_id = 0;

  if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) {
    return false;
  }

  $data = $this->process_fields( $table, $data, $format );
  if ( false === $data ) {
    return false;
  }

  $formats = $values = array();
  foreach ( $data as $value ) {
    if ( is_null( $value['value'] ) ) {
      $formats[] = 'NULL';
      continue;
    }

    $formats[] = $value['format'];
    $values[]  = $value['value'];
  }

  $fields  = '`' . implode( '`, `', array_keys( $data ) ) . '`';
  $formats = implode( ', ', $formats );
  
  // modification for IGNORE keyword
  if (true == $ignore && 'INSERT' == $type) {
    $type = 'INSERT IGNORE';
  }

  $sql = "$type INTO `$table` ($fields) VALUES ($formats)";

  $this->check_current_query = false;
  return $this->query( $this->prepare( $sql, $values ) );
}

ทำไมนักพัฒนาไม่ทำเช่นนี้บ่อยขึ้น?

หากคุณต้องการเคียวรีแบบกำหนดเองเพียงไม่กี่ครั้ง คุณสามารถใช้ $wpdb->query() ได้อย่างง่ายดาย ไม่จำเป็นต้องเปลี่ยนคลาสเริ่มต้น คุณยังสามารถเขียนคลาสแบบกำหนดเองที่ขยายคลาสดีฟอลต์แต่ไม่แทนที่อ็อบเจ็กต์ wpdb ในกรณีนั้น คุณจะต้องใช้ $mycustomclass->method() แต่นั่นไม่ใช่จุดจบของโลก

นอกจากปัจจัยด้านความเย็นที่เห็นได้ชัดซึ่งขยายคลาส wpdb เริ่มต้นเป็นสิ่งที่ควรทำใน WP และไม่แฮ็ก ดังนั้นอย่าลังเลที่จะเล่นกับมัน จำไว้สองสิ่ง:

  • เมื่อคุณส่งโครงการของคุณให้ใครบางคน อย่าลืมรวมไฟล์ db.php ; มันจะไม่อยู่ในโฟลเดอร์ธีมหรือปลั๊กอินใด ๆ
  • จับตาดูการเปลี่ยนแปลงใน wp-db.php เนื่องจากอาจส่งผลต่อคลาสที่คุณกำหนดเอง (แม้ว่าจะไม่น่าเป็นไปได้สูง)