Bagian 5 – WordPress dan Pemrograman Berorientasi Objek: Contoh WordPress – Implementasi: Menu Administrasi

Diterbitkan: 2022-02-04

Dalam artikel kami sebelumnya tentang Pemrograman Berorientasi Objek, kami membahas desain yang akhirnya kami buat untuk plugin berorientasi objek kami.

Sekarang, kita akan masuk ke bagian yang paling menarik di mana kita akan menggali lebih dalam bagaimana kita mengimplementasikannya!

Kami akan memandu Anda melalui beberapa bagian implementasi, selangkah demi selangkah, berbicara tentang dasar-dasar pemrograman berorientasi objek, sintaks PHP, beberapa konsep inti, dan kami bahkan akan melihat sekilas prinsip-prinsip SOLID.

Pada akhir artikel ini, semoga Anda memiliki pemahaman yang lebih baik tentang OOP dan bersemangat untuk menulis plugin berorientasi objek Anda sendiri!

Mulai

Kami menganggap Anda sudah familiar dengan pengembangan plugin WordPress secara umum, jadi kami akan fokus pada aspek berorientasi objek dari plugin kami. Jika Anda baru dalam pengembangan plugin atau membutuhkan penyegaran, Anda harus mempelajari cara membuat plugin WordPress pertama Anda terlebih dahulu.

Mari kita mulai seperti biasa, dengan membuat file prsdm-limit-login-attempts.php baru, di bawah direktori plugin kita (yaitu /wp-content/plugins/prsdm-limit-login-attempts).

File plugin utama akan menyertakan Header Plugin yang sudah Anda kenal:

 /** * Plugin Name: PRSDM Limit Login Attempts * Plugin URI: https://pressidium.com * Description: Limit rate of login attempts, including by way of cookies, for each IP. * Author: Pressidium * Author URI: https://pressidium.com * Text Domain: prsdm-limit-login-attempts * License: GPL-2.0+ * Version: 1.0.0 */

Dan pernyataan if sederhana untuk mencegah akses langsung ke sana.

 if ( ! defined( 'ABSPATH' ) ) { exit; }

Itu saja yang kita butuhkan untuk saat ini. Kami akan meninjau kembali file ini nanti!

Membangun Menu Administrasi

Saat mengembangkan plugin, Anda sering kali perlu menyediakan cara untuk mengonfigurasinya kepada pengguna. Di situlah halaman pengaturan masuk. Untuk membuatnya, kita akan menambahkan menu administrasi yang menggunakan API Pengaturan WordPress.

Jadi, mari kita mulai memikirkan bagaimana tampilan API berorientasi objek kita.

Idealnya, kami ingin membuat instance Pressidium_LLA_Settings_Page kami dan menyelesaikannya. Untuk membuat instance kelas, kata kunci new harus digunakan.

 new Pressidium_LLA_Settings_Page();

Sekarang, mari kita pikirkan bagaimana tampilan kelas Pressidium_LLA_Settings_Page kita.

Kita akan mulai dengan membuat kelas baru, menggunakan kata kunci class :

 class Pressidium_LLA_Settings_Page {}

Nama kelas kami harus diawali dengan pengenal unik, Pressidium_LLA_ untuk mencegah tabrakan penamaan dengan plugin WordPress lainnya. Prefiks mencegah plugin lain menimpa dan/atau secara tidak sengaja memanggil kelas kita. Selama nama kelas kita unik—atau kita menggunakan ruang nama—tidak akan ada konflik dengan plugin lain.

Konstruktor

Sekarang, kita akan menghubungkan ke admin_menu dan admin_init. Untuk mempermudah, kami hanya akan memanggil add_action() di konstruktor kami (peringatan spoiler: kami akan mengubahnya nanti).

 class Pressidium_LLA_Settings_Page { /** * Settings_Page constructor. */ public function __construct() { add_action( 'admin_menu', array( $this, 'add_page' ) ); add_action( 'admin_init', array( $this, 'register_sections' ) ); } }

Kelas yang memiliki konstruktor, panggil metode ini saat objek dipakai. Jadi, metode __construct() sangat bagus untuk inisialisasi apa pun yang mungkin ingin kita lakukan.

Mari kita lihat lebih dekat panggilan add_action() kita. Jika Anda pernah mengembangkan plugin WordPress, Anda mungkin mengharapkan sesuatu seperti ini:

 add_action( 'admin_menu', 'my_plugin_prefix_add_page' );

Tapi sebaliknya, kita punya:

 add_action( 'admin_menu', array( $this, 'add_page' ) );

Anda mungkin bingung tentang penggunaan array di sini. Kapan pun kita ingin meneruskan metode objek yang dipakai sebagai panggilan balik/panggilan, kita bisa menggunakan array yang berisi objek pada indeks 0, dan nama metode pada indeks 1.

Apa $ini?

Ini adalah variabel semu yang tersedia saat metode dipanggil dari dalam konteks objek. $this adalah nilai dari objek pemanggil. Dalam hal ini, $this adalah turunan dari Pressidium_LLA_Settings_Page .

Plus, semua "fungsi" kami sekarang adalah metode, dibungkus dalam kelas, jadi tidak perlu memberi awalan nama metode kami.

Ruang nama

Ruang nama di PHP memungkinkan kita untuk mengelompokkan kelas terkait, antarmuka, fungsi, dll., mencegah tabrakan penamaan antara kode kita, dan kelas/fungsi internal PHP atau pihak ketiga.

Mari kita lanjutkan dan gunakan mereka, jadi kita tidak perlu mengawali salah satu kelas kita untuk bergerak maju.

Kami akan mendeklarasikan namespace menggunakan kata kunci namespace .

 namespace Pressidium;

Namespaces dapat didefinisikan dengan sub-level.

 namespace Pressidium\Limit_Login_Attempts;

Karena kami sedang membangun halaman pengaturan, kami akan mendeklarasikan sub-namespace "halaman" untuk mengelompokkan apa pun yang terkait dengan halaman administrasi.

 namespace Pressidium\Limit_Login_Attempts\Pages;

Kami akhirnya bisa menyingkirkan awalan Pressidium_LLA_ !

 namespace Pressidium\Limit_Login_Attempts\Pages; class Settings_Page { // ...

Plugin WordPress lain yang berisi kelas Settings_Page tidak menjadi masalah lagi, karena kelasnya dan kelas kita tidak akan tinggal di namespace yang sama.

Saat membuat instance Settings_Page kami dalam namespace yang sama, kami dapat menghilangkannya:

 namespace Pressidium\Limit_Login_Attempts\Pages; $settings_page = new Settings_Page();

Saat membuat instance Settings_Page kami di luar namespace, kami harus menentukannya seperti ini:

 namespace Another\Namespace; $settings_page = new \Pressidium\Limit_Login_Attempts\Pages\Settings_Page();

Atau, kita bisa mengimpor kelas kita dengan operator use :

 use Pressidium\Limit_Login_Attempts\Pages\Settings_Page; $settings_page = new Settings_Page();

Menambahkan Panggilan Balik Kait

Sekarang, mari kita deklarasikan add_page() dan register_sections() ini.

 class Settings_Page { /** * Settings_Page constructor. */ public function __construct() { add_action( 'admin_menu', array( $this, 'add_page' ) ); add_action( 'admin_init', array( $this, 'register_sections' ) ); } /** * Add this page as a top-level menu page. */ public function add_page() { // TODO: Implement this method. } /** * Register sections. */ public function register_sections() { // TODO: Implement this method. } }

Metode add_page() kami hanya akan memanggil fungsi add_menu_page() WordPress.

 public function add_page() { add_menu_page( __( 'Limit Login Attempts Settings', 'prsdm-limit-login-attempts' ), __( 'Limit Login Attempts', 'prsdm-limit-login-attempts' ), 'manage_options', 'prsdm_limit_login_attempts_settings', array( $this, 'render' ), 'dashicons-shield-alt', null ); }

Itu sepertinya cara yang berbelit-belit untuk mengembangkan plugin WordPress. Ini hanya memanggil fungsi WordPress, dengan langkah-langkah ekstra.

Yah, itu tidak sepenuhnya "dapat digunakan kembali", kita masih harus menulis semua kode tambahan ini untuk setiap menu/halaman administrasi yang ingin kita tambahkan.

Pemfaktoran ulang

Mari kita lanjutkan dan refactor kode kita sedikit untuk memanfaatkan pemrograman berorientasi objek dan membuat kode kita dapat digunakan kembali . Kami akan mulai dengan mengganti nilai hardcoded kami di add_page() dengan beberapa metode, seperti:

 public function add_page() { add_menu_page( $this->get_page_title(), // page_title $this->get_menu_title(), // menu_title $this->get_capability(), // capability $this->get_slug(), // menu_slug array( $this, 'render' ), // callback function $this->get_icon_url(), // icon_url $this->get_position() // position ); }

Kami akan mendefinisikan metode ini sebagai protected , sehingga mereka hanya dapat diakses di dalam kelas itu sendiri dan oleh kelas anak/induknya.

 protected function get_page_title() { /* ... */ } protected function get_menu_title() { /* ... */ } protected function get_capability() { /* ... */ } protected function get_slug() { /* ... */ } protected function get_icon_url() { /* ... */ } protected function get_position() { /* ... */ }

Besar! Kita sekarang dapat menggunakan kelas ini sebagai kelas generik yang dapat digunakan kembali untuk diperluas.

Mendesain ulang

Kami memberi tahu Anda bahwa ini mungkin akan terjadi pada akhirnya. Di sinilah kita, memikirkan kembali desain kelas kita saat membangunnya.

Karena ini akan menjadi kelas dasar kami , kami akan mengganti namanya menjadi nama yang lebih umum, seperti Admin_Page . Sejauh ini, terlihat seperti ini:

 class Admin_Page { /** * Admin_Page constructor. */ public function __construct() { add_action( 'admin_menu', array( $this, 'add_page' ) ); add_action( 'admin_init', array( $this, 'register_sections' ) ); } /** * Add this page as a top-level menu page. */ public function add_page() { add_menu_page( $this->get_page_title(), // page_title $this->get_menu_title(), // menu_title $this->get_capability(), // capability $this->get_slug(), // menu_slug array( $this, 'render' ), // callback function $this->get_icon_url(), // icon_url $this->get_position() // position ); } /** * Register sections. */ public function register_sections() { // TODO: Implement this method. } protected function get_page_title() { /* ... */ } protected function get_menu_title() { /* ... */ } protected function get_capability() { /* ... */ } protected function get_slug() { /* ... */ } protected function get_icon_url() { /* ... */ } protected function get_position() { /* ... */ } }

Kita sekarang dapat membuat Settings_Page terpisah yang memperluas kelas dasar Admin_Page .

 class Settings_Page extends Admin_Page { // ... }

Itu adalah contoh yang bagus dari pewarisan , salah satu konsep inti dari pemrograman berorientasi objek. Saat memperluas kelas, kelas anak— Settings_Page , dalam hal ini—mewarisi semua metode, properti, dan konstanta publik dan terproteksi dari kelas induk.

Kita dapat memanfaatkan ini dan menetapkan beberapa nilai default. Misalnya, kami akan menetapkan ikon umum untuk semua halaman menu, dengan mendefinisikan metode get_icon_url() kami seperti ini:

 class Admin_Page { // ... /** * Return the menu icon to be used for this menu. * * @link https://developer.wordpress.org/resource/dashicons/ * * @return string */ protected function get_icon_url() { return 'dashicons-admin-generic'; } }

Kecuali jika kelas menimpa metode tersebut, mereka akan mempertahankan fungsionalitas aslinya. Jadi, secara default, semua kelas anak akan menggunakan ikon generik itu.

Namun, jika kita ingin menyetel ikon lain untuk halaman menu tertentu, kita cukup mengganti metode get_icon_url() di kelas anak kita, seperti:

 class Settings_Page extends Admin_Page { protected function get_icon_url() { return 'dashicons-shield-alt'; } }

Namun, ada beberapa nilai yang harus berbeda untuk setiap kelas anak. Misalnya, slug menu—argumen keempat dari add_menu_page() —harus unik untuk setiap halaman menu.

Jika kami akan mendefinisikan metode ini di kelas dasar Admin_Page kami, kami akan membutuhkan cara untuk memastikan bahwa setiap kelas anak menggantikan metode ini. Yah, kita bisa melakukan sesuatu yang lebih baik. Kita dapat mendeklarasikan tanda tangan metode dan melewatkan implementasinya sepenuhnya.

Masukkan metode abstrak!

Kelas dan Metode Abstrak

Metode yang didefinisikan sebagai abstrak hanya mendeklarasikan tanda tangan metode dan mereka tidak dapat mendefinisikan implementasinya.

 /** * Return page slug. * * @return string */ abstract protected function get_slug();

Setiap kelas yang berisi setidaknya satu metode abstrak juga harus abstrak. Itu berarti, kelas Admin_Page kita harus didefinisikan sebagai abstrak juga.

 abstract class Admin_Page { // ...

Penting juga untuk menunjukkan di sini bahwa kelas yang didefinisikan sebagai abstrak tidak dapat dipakai. Jadi, kita tidak bisa lagi langsung membuat instance Admin_Page .

Berikut juga visualisasi kelasnya:

Saat mewarisi dari kelas abstrak, kelas anak harus mendefinisikan semua metode yang ditandai abstrak dalam deklarasi kelas induknya. Artinya, Settings_Page kita harus mengimplementasikan metode get_slug() .

 class Settings_Page extends Admin_Page { // ... protected function get_slug() { return 'prsdm_limit_login_attempts_settings'; } // ... }

Dengan cara yang sama, kita harus mengimplementasikan sisa metode terproteksi yang add_page() .

Sebelum melanjutkan tentang bagaimana kita akan mendaftarkan bagian dan bidang halaman admin dan merender kontennya, mari kita bicara sedikit tentang pengaturan di WordPress.

API Pengaturan

Kami akan menganggap Anda sudah terbiasa dengan Settings API. Tapi, untuk jaga-jaga, inilah intinya:

  • settings_fields() — Menampilkan bidang nonce, action, dan option_page untuk halaman pengaturan. Pada dasarnya, bidang formulir tersembunyi.
  • do_settings_sections() — Mencetak semua bagian pengaturan (dan bidangnya) yang ditambahkan ke halaman pengaturan tertentu.
  • add_settings_section() — Menambahkan bagian baru ke halaman pengaturan.
  • add_settings_field() — Menambahkan bidang baru ke bagian halaman pengaturan.
  • register_setting() — Mendaftarkan pengaturan dan datanya.

Jika Anda belum terbiasa dengan ini, Anda dapat berhenti membaca artikel ini dan memeriksa artikel terkait kami tentang cara membuat halaman pengaturan untuk plugin khusus.

Sekarang kita berada di halaman yang sama, mari kembali ke metode register_sections() kita. Sekali lagi, kita harus mundur selangkah dan memikirkan API kita.

Karena kita telah mendefinisikan metode add_page() di kelas Admin_Page , kita juga akan mendefinisikan metode render() di sana. Kami akan meneruskan nilai pengembalian metode kami yang lain sebagai argumen ke fungsi WordPress.

 abstract class Admin_Page { // ... /** * Render this admin page. */ public function render() { ?> <div class="wrap"> <form action="options.php" method="post"> <h1><?php echo esc_html( $this->get_page_title() ); ?></h1> <?php settings_fields( $this->get_slug() ); do_settings_sections( $this->get_slug() ); submit_button( __( 'Change Options', 'prsdm-limit-login-attempts' ) ); ?> </form> </div> <?php } }

Dengan begitu, kita tidak perlu repot langsung dengan fungsi-fungsi WordPress ini lagi. Itu karena setiap halaman admin yang mungkin kita tambahkan di masa mendatang akan dibangun melalui kelas anak seperti Settings_Page , dan renderingnya akan dilakukan melalui metode render() yang diwarisi dari kelas induk Admin_Page .

Kesimpulan

Besar! Kami membuat kelas yang bertanggung jawab untuk mendaftarkan menu administrasi dan menambahkan halaman pengaturan.

Dalam artikel seri berikutnya, kami akan terus membangun halaman pengaturan kami dan mendaftarkan bagian, bidang, dan elemennya.

Klik di sini untuk membaca Bagian 6 dalam Seri Pemrograman Berorientasi Objek kami

Lihat juga

  • WordPress dan Pemrograman Berorientasi Objek – Gambaran Umum
  • Bagian 2 – WordPress dan Pemrograman Berorientasi Objek: Contoh Dunia Nyata
  • Bagian 3 – WordPress dan Pemrograman Berorientasi Objek: Contoh WordPress – Mendefinisikan Ruang Lingkup
  • Bagian 4 – WordPress dan Pemrograman Berorientasi Objek: Contoh WordPress – Desain