Bölüm 5 – WordPress ve Nesne Yönelimli Programlama: Bir WordPress Örneği – Uygulama: Yönetim Menüsü

Yayınlanan: 2022-02-04

Nesneye Yönelik Programlama ile ilgili önceki makalemizde, nesne yönelimli eklentimiz için nihayetinde bulduğumuz tasarımı tartışmıştık.

Şimdi, onu nasıl uyguladığımızı derinlemesine inceleyeceğimiz en heyecan verici kısma geçeceğiz!

Nesne yönelimli programlamanın temelleri, PHP sözdizimi, bazı temel kavramlar hakkında konuşarak, uygulamanın bazı bölümlerinde adım adım size yol göstereceğiz ve hatta SOLID ilkelerine göz atacağız.

Bu makalenin sonunda, umarız OOP'yi daha iyi anlarsınız ve kendi nesne yönelimli eklentilerinizi yazmaktan heyecan duyarsınız!

Başlarken

Genel olarak WordPress eklenti geliştirmeye aşina olduğunuzu varsayıyoruz, bu nedenle eklentimizin nesne yönelimli yönlerine odaklanacağız. Eklenti geliştirmede yeniyseniz veya bir tazelemeye ihtiyacınız varsa, önce ilk WordPress eklentinizi nasıl oluşturacağınızı öğrenmelisiniz.

Her zaman yaptığımız gibi, eklenti dizinimizin altında (ör. /wp-content/plugins/prsdm-limit-login-attempts) yeni bir prsdm-limit-login-attempts.php dosyası oluşturarak başlayalım.

Ana eklenti dosyası, zaten aşina olduğunuz Eklenti Başlığını içerecektir:

 /** * 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 */

Ve ona doğrudan erişimi engellemek için basit bir if ifadesi.

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

Şimdilik ihtiyacımız olan tek şey bu. Bu dosyayı daha sonra tekrar gözden geçireceğiz!

Yönetim Menüsü Oluşturma

Bir eklenti geliştirirken, genellikle kullanıcılarınıza onu yapılandırmanın bir yolunu sağlamanız gerekir. İşte burada bir ayarlar sayfası devreye giriyor. Bir tane oluşturmak için WordPress Ayarları API'sini kullanan bir yönetim menüsü ekleyeceğiz.

Öyleyse nesne yönelimli API'mizin nasıl görüneceğini düşünmeye başlayalım.

İdeal olarak, Pressidium_LLA_Settings_Page sayfamızı somutlaştırmak ve onunla işimizi bitirmek isteriz. Bir sınıfın örneğini oluşturmak için new anahtar sözcüğü kullanılmalıdır.

 new Pressidium_LLA_Settings_Page();

Şimdi Pressidium_LLA_Settings_Page sınıfımızın nasıl görüneceğini düşünelim.

class anahtar sözcüğünü kullanarak yeni bir sınıf oluşturarak başlayacağız:

 class Pressidium_LLA_Settings_Page {}

Diğer WordPress eklentileriyle herhangi bir adlandırma çakışmasını önlemek için, sınıf adımızın önüne benzersiz bir tanımlayıcı olan Pressidium_LLA_ . Ön ekler, diğer eklentilerin üzerine yazmasını ve/veya yanlışlıkla sınıflarımızı çağırmasını engeller. Sınıf adlarımız benzersiz olduğu veya ad alanlarını kullandığımız sürece, diğer eklentilerle herhangi bir çakışma olmayacaktır.

yapıcı

Şimdi admin_menu ve admin_init'e bağlanacağız. İşleri basit tutmak için, yapıcımızda sadece add_action() öğesini çağıracağız (spoiler uyarısı: bunu daha sonra değiştireceğiz).

 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' ) ); } }

Bir yapıcıya sahip sınıflar, bir nesne başlatıldığında bu yöntemi çağırır. Bu nedenle, __construct() yöntemi, gerçekleştirmek isteyebileceğimiz herhangi bir başlatma için harikadır.

add_action() çağrılarımıza daha yakından bakalım. Geçmişte WordPress eklentileri geliştirdiyseniz, şöyle bir şey beklemiş olabilirsiniz:

 add_action( 'admin_menu', 'my_plugin_prefix_add_page' );

Ama bunun yerine elimizde:

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

Burada bir dizinin kullanımı konusunda kafanız karışmış olabilir. Ne zaman somutlaştırılmış bir nesnenin yöntemini geri çağırma/çağrılabilir olarak iletmek istersek, 0 dizininde bir nesne ve 1 dizininde bir yöntem adını içeren bir dizi kullanabiliriz.

$bu nedir?

Bir nesne bağlamından bir yöntem çağrıldığında kullanılabilen sözde bir değişkendir. $this , çağıran nesnenin değeridir. Bu durumda, $this , Pressidium_LLA_Settings_Page bir örneğidir.

Ayrıca, tüm "işlevlerimiz" artık bir sınıfa sarılmış yöntemlerdir, bu nedenle yöntem adlarımızın önüne eklemeye gerek yoktur.

Ad alanları

PHP'deki ad alanları, kodumuz ve dahili PHP veya üçüncü taraf sınıflar/işlevler arasındaki adlandırma çakışmalarını önleyerek ilgili sınıfları, arabirimleri, işlevleri vb.

Devam edelim ve onları kullanalım, böylece ilerlemekte olan sınıflarımızdan herhangi birinin ön ekini almamız gerekmez.

namespace anahtar sözcüğünü kullanarak bir ad alanı bildireceğiz.

 namespace Pressidium;

Ad alanları alt düzeylerle tanımlanabilir.

 namespace Pressidium\Limit_Login_Attempts;

Bir ayarlar sayfası oluşturduğumuz için, yönetim sayfalarıyla ilgili her şeyi gruplamak için bir "sayfalar" alt ad alanı ilan edeceğiz.

 namespace Pressidium\Limit_Login_Attempts\Pages;

Sonunda Pressidium_LLA_ önekinden kurtulabiliriz!

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

Settings_Page sınıfını içeren başka bir WordPress eklentisi, sınıfı ve sınıfımız aynı ad alanında yaşamayacağından artık sorun değil.

Settings_Page sayfamızı aynı ad alanı içinde başlatırken bunu atlayabiliriz:

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

Settings_Page sayfamızı ad alanının dışında başlatırken, bunu şu şekilde belirtmeliyiz:

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

Alternatif olarak, sınıfımızı use operatörüyle içe aktarabiliriz:

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

Hook Geri Aramaları Ekleme

Şimdi bu add_page() ve register_sections() metodlarını tanımlayalım.

 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. } }

add_page() yöntemimiz sadece add_menu_page() WordPress işlevini çağıracaktır.

 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 ); }

Bu, WordPress eklentileri geliştirmenin karmaşık bir yolu gibi görünüyor. Sadece ekstra adımlarla WordPress işlevlerini çağırıyor.

Pekala, bu tam olarak “tekrar kullanılabilir” değil, eklemek istediğimiz her yönetim menüsü/sayfası için yine de tüm bu ekstra kodu yazmamız gerekecek.

yeniden düzenleme

Devam edelim ve nesne yönelimli programlamadan yararlanmak ve kodumuzu yeniden kullanılabilir hale getirmek için kodumuzu biraz yeniden düzenleyelim. add_page() içindeki sabit kodlanmış değerlerimizi aşağıdaki gibi birkaç yöntemle değiştirerek başlayacağız:

 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 ); }

Bu yöntemleri protected olarak tanımlayacağız, böylece onlara yalnızca sınıfın içinden ve onun alt/üst sınıfları tarafından erişilebilirler.

 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() { /* ... */ }

Harika! Artık bu sınıfı, genişletmek için yeniden kullanılabilir, genel bir sınıf olarak kullanabiliriz.

Yeniden tasarlama

Size bunun muhtemelen eninde sonunda olacağını söylemiştik. İşte burada, sınıfımızın tasarımını inşa ederken yeniden düşünüyoruz.

Bu bizim temel sınıfımız olacağından, onu Admin_Page gibi daha genel bir adla yeniden adlandıracağız. Şimdiye kadar, şöyle görünüyor:

 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() { /* ... */ } }

Artık bu Admin_Page temel sınıfını genişleten ayrı bir Settings_Page oluşturabiliriz.

 class Settings_Page extends Admin_Page { // ... }

Bu, nesne yönelimli programlamanın temel kavramlarından biri olan kalıtımın harika bir örneğidir. Bir sınıfı genişletirken, alt sınıf — bu durumda Settings_Page — tüm genel ve korumalı yöntemleri, özellikleri ve sabitleri üst sınıftan devralır.

Bunu kullanabilir ve bazı varsayılan değerler ayarlayabiliriz. Örneğin, get_icon_url() yöntemimizi aşağıdaki gibi tanımlayarak tüm menü sayfaları için genel bir simge ayarlayacağız:

 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'; } }

Bir sınıf bu yöntemleri geçersiz kılmadıkça, orijinal işlevlerini koruyacaktır. Bu nedenle, varsayılan olarak, tüm alt sınıflar bu genel simgeyi kullanacak.

Ancak, belirli bir menü sayfası için başka bir simge ayarlamak istiyorsak, alt sınıfımızdaki get_icon_url() yöntemini şöyle geçersiz kılabiliriz :

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

Yine de her çocuk sınıfı için farklı olması gereken bazı değerler vardır. Örneğin, menü add_menu_page() işlevinin dördüncü argümanı) her menü sayfası için benzersiz olmalıdır.

Bu yöntemi Admin_Page temel sınıfımızda tanımlasaydık, her bir alt sınıfın bu yöntemi geçersiz kıldığından emin olmak için bir yola ihtiyacımız olurdu. Pekala, daha da iyisini yapabiliriz. Metodun imzasını ilan edebilir ve uygulamasını tamamen atlayabiliriz.

Soyut yöntemler girin!

Soyut Sınıflar ve Yöntemler

Soyut olarak tanımlanan yöntemler, yalnızca yöntemin imzasını bildirir ve uygulamasını tanımlayamazlar.

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

En az bir soyut yöntem içeren herhangi bir sınıf da soyut olmalıdır . Bu, Admin_Page sınıfımızın da soyut olarak tanımlanması gerektiği anlamına gelir.

 abstract class Admin_Page { // ...

Ayrıca soyut olarak tanımlanan sınıfların somutlaştırılamayacağını burada belirtmek de önemlidir. Bu nedenle, artık Admin_Page doğrudan somutlaştıramıyoruz.

İşte ayrıca sınıfın bir görselleştirmesi:

Soyut bir sınıftan miras alırken, alt sınıf, üst sınıfının bildiriminde soyut olarak işaretlenmiş tüm yöntemleri tanımlamalıdır. Bunun anlamı, Settings_Page get_slug() yöntemini uygulaması gerektiğidir.

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

Aynı şekilde, add_page() ihtiyaç duyduğu korunan yöntemlerin geri kalanını da uygulamalıyız.

Yönetici sayfasının bölümlerini ve alanlarını nasıl kaydedeceğimize ve içeriklerini nasıl oluşturacağımıza geçmeden önce WordPress'teki ayarlardan biraz bahsedelim.

Ayarlar API'sı

Ayarlar API'sını zaten bildiğinizi varsayacağız. Ancak, her ihtimale karşı, işte bunun özü:

  • settings_fields() — Bir ayarlar sayfası için nonce, action ve options_page alanlarının çıktısını alır. Temel olarak, gizli form alanları.
  • do_settings_sections() — Belirli bir ayarlar sayfasına eklenen tüm ayar bölümlerini (ve alanlarını) yazdırır.
  • add_settings_section() — Ayarlar sayfasına yeni bir bölüm ekler.
  • add_settings_field() — Ayarlar sayfasının bir bölümüne yeni bir alan ekler.
  • register_setting() — Bir ayarı ve verilerini kaydeder.

Buna henüz aşina değilseniz, bu makaleyi okumayı durdurabilir ve özel bir eklenti için ayarlar sayfasının nasıl oluşturulacağına ilişkin ilgili makalemize göz atabilirsiniz.

Artık aynı sayfada olduğumuza göre, register_sections() yöntemimize geri dönelim. Bir kez daha geri adım atıp API'mizi düşünmeliyiz.

Admin_Page sınıfında add_page() yöntemini tanımladığımız için, render() yöntemini de orada tanımlayacağız. Diğer metotlarımızın dönüş değerlerini WordPress fonksiyonlarına argüman olarak ileteceğiz.

 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 } }

Bu şekilde, bir daha asla bu WordPress işlevleriyle doğrudan uğraşmak zorunda kalmayacağız. Bunun nedeni, gelecekte ekleyebileceğimiz herhangi bir yönetici sayfasının, Settings_Page gibi bir alt sınıf aracılığıyla oluşturulacak ve bunun oluşturulmasının, Admin_Page üst sınıfının devralınan render() yöntemi aracılığıyla gerçekleştirileceğidir.

Çözüm

Harika! Bir yönetim menüsü kaydetmekten ve bir ayarlar sayfası eklemekten sorumlu olan sınıfları oluşturduk.

Serinin bir sonraki makalesinde, ayarlar sayfamızı oluşturmaya ve bölümlerini, alanlarını ve öğelerini kaydetmeye devam edeceğiz.

Nesneye Yönelik Programlama Serimizde Bölüm 6'yı okumak için buraya tıklayın

Ayrıca bakınız

  • WordPress ve Nesne Yönelimli Programlama – Genel Bakış
  • Bölüm 2 – WordPress ve Nesne Yönelimli Programlama: Gerçek Bir Dünya Örneği
  • Bölüm 3 – WordPress ve Nesne Yönelimli Programlama: Α WordPress Örneği – Kapsamın Tanımlanması
  • Bölüm 4 – WordPress ve Nesne Yönelimli Programlama: Bir WordPress Örneği – Tasarım