Cara terbaik untuk memulai kelas di plugin WP?

90

Saya telah membuat sebuah plugin, dan tentu saja saya, saya ingin menggunakan pendekatan OO yang bagus. Sekarang apa yang telah saya lakukan adalah membuat kelas ini dan kemudian tepat di bawah membuat instance dari kelas ini:

class ClassName {

    public function __construct(){

    }
}

$class_instance = new ClassName();  

Saya berasumsi ada cara WP lebih untuk memulai kelas ini, dan kemudian saya menemukan orang-orang mengatakan bahwa mereka lebih suka memiliki init()fungsi daripada yang __construct()satu. Dan juga saya menemukan beberapa orang menggunakan kait berikut:

class ClassName {

    public function init(){

    }
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );

Apa yang umumnya dianggap sebagai cara terbaik untuk membuat instance kelas WP pada beban dan menjadikannya sebagai variabel yang dapat diakses secara global?

CATATAN: Sebagai titik sisi yang menarik, saya perhatikan bahwa sementara register_activation_hook()dapat dipanggil dari dalam __construct, itu tidak dapat dipanggil dari dalam init()menggunakan contoh kedua. Mungkin seseorang dapat mencerahkan saya dalam hal ini.

Sunting: Terima kasih atas semua jawaban, jelas ada sedikit perdebatan tentang bagaimana menangani inisialisasi di dalam kelas itu sendiri, tapi saya pikir umumnya ada konsensus yang cukup bagus yang add_action( 'plugins_loaded', ...);merupakan cara terbaik untuk benar-benar memulai ...

Sunting: Hanya untuk membingungkan masalah, saya juga telah melihat ini digunakan (walaupun saya tidak akan menggunakan metode ini sendiri karena mengubah kelas OO yang baik menjadi fungsi tampaknya mengalahkan intinya):

// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
    global $class_name;
    $class_name = new ClassName();
}
kalpaitch
sumber
1
Mengenai pengeditan terakhir, jika itu terkandung dalam file plugin yang sama dengan kelas, itu menjadi agak tidak berguna. Anda dapat juga instantiate kelas sesuai metode yang saya jelaskan. Bahkan jika itu dalam file terpisah, masih agak tidak berguna. Hanya use case yang dapat saya lihat adalah jika Anda ingin membuat fungsi wrapper yang memungkinkan Anda membuat instance kelas di luar file plugin Anda, di dalam tema dan sebagainya. Meski begitu, saya harus bertanya logika apa yang melatarbelakangi hal itu karena penggunaan kondisional dan kait yang tepat harus memungkinkan kontrol butir halus atas instantiasi yang memungkinkan Anda untuk fokus menggunakan plugin sebagai gantinya.
Adam
Saya agak setuju dengan ini, tapi saya pikir itu layak dimasukkan ketika saya menemukannya di beberapa plugin WP.
kalpaitch

Jawaban:

60

Pertanyaan bagus, ada sejumlah pendekatan dan itu tergantung pada apa yang ingin Anda capai.

Saya sering melakukannya;

add_action( 'plugins_loaded', array( 'someClassy', 'init' ));

class someClassy {

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
           //construct what you see fit here...
    }

    //etc...
}

Contoh lebih mendalam yang muncul sebagai hasil dari beberapa diskusi baru-baru ini tentang topik ini di chat room dapat dilihat pada intisari ini oleh anggota WPSE, toscho .

Pendekatan konstruktor kosong.

Berikut adalah kutipan keuntungan / kerugian yang diambil dari intisari di atas yang mencontohkan pendekatan konstruktor kosong secara penuh.

  • Keuntungan:

    • Tes unit dapat membuat instance baru tanpa mengaktifkan kait apa pun secara otomatis. Bukan Singleton.

    • Tidak diperlukan variabel global.

    • Siapa pun yang ingin bekerja dengan instance plugin dapat menghubungi T5_Plugin_Class_Demo :: get_instance ().

    • Mudah dinonaktifkan.

    • Masih nyata OOP: tidak ada metode kerja yang statis.

  • Kerugian:

    • Mungkin lebih sulit dibaca?

Kerugian menurut saya adalah lemah karena itulah yang harus menjadi pendekatan yang saya sukai, namun bukan satu-satunya yang saya gunakan. Bahkan beberapa beban berat lainnya tidak akan diragukan lagi berpadu dengan topik ini dengan mengambil mereka pada subjek segera karena ada beberapa pendapat bagus seputar topik ini yang harus disuarakan.


catatan: Saya perlu menemukan contoh inti dari toscho yang berjalan melalui 3 atau 4 perbandingan tentang cara membuat instance kelas dalam sebuah plugin yang melihat pro dan kontra dari masing-masing, yang mana tautan di atas adalah cara yang disukai untuk melakukannya, tetapi contoh lain memberikan kontras yang bagus untuk topik ini. Semoga toscho masih menyimpannya di file.

Catatan: The WPSE Jawaban untuk topik ini dengan contoh-contoh yang relevan dan perbandingan. Juga solusi terbaik misalnya kelas di WordPress.

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
class My_Plugin {

    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance() {

        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo() {

        return $this->var; // never echo or print in a shortcode!
    }
}
Adam
sumber
apa perbedaan antara add_action ('plugins_loaded', ...); dan add_action ('load-plugins.php', ...); Contoh yang saya ambil menggunakan yang terakhir
kalpaitch
1
Dari apa yang saya mengerti load-plugins.php, meskipun berfungsi, dikaitkan dengan update.phpfile inti dan bukan bagian dari tindakan standar yang biasa yang harus diandalkan ketika mengenai urutan kejadian yang menyala selama inisialisasi dan karena alasan itu saya lebih suka untuk menggunakan kait yang berlaku, dalam hal ini plugins_loaded. Inilah yang sering saya sebut sebagai gambaran singkat tentang apa yang terjadi ketika Referensi Tindakan . Penjelasan saya tidak lengkap secara keseluruhan.
Adam
4
Saya suka pendekatan seperti ini. Namun, saya mempertanyakan menggunakan plugins_loaded sebagai hook tindakan inisialisasi Anda. Pengait ini dimaksudkan untuk dijalankan setelah semua plugin dimuat. Dengan menghubungkan setelah itu, Anda semacam membajak kait itu, dan mungkin bersenang-senang dalam konflik atau masalah urutan startup dengan plugin lain atau tema yang terhubung ke plugins_loaded. Saya tidak akan melakukan tindakan apa pun untuk menjalankan metode inisialisasi Anda. Arsitektur plugin dirancang untuk menjalankan inline, bukan pada tindakan.
Tom Auger
2
Perhatikan bahwa jika Anda menggunakan register_activation_hook()Anda harus memanggil fungsi itu sebelum plugins_loadedtindakan telah dipicu.
Geert
1
Sebagai informasi tambahan, lihat posting ini dari @mikeschinkel dan dicuss di komentar. hardcorewp.com/2012/…
bueltge
78

Tiba di sini tepat 2 tahun setelah pertanyaan awal diajukan, ada beberapa hal yang ingin saya tunjukkan. (Jangan tanya saya untuk menunjukkan banyak hal , selamanya).

Kait yang tepat

Untuk membuat instantiate kelas plugin, hook yang tepat harus digunakan. Tidak ada aturan umum untuk itu, karena itu tergantung pada apa yang dilakukan kelas.

Menggunakan hook yang sangat awal seperti "plugins_loaded"sering tidak masuk akal karena hook seperti itu dipecat untuk permintaan admin, frontend dan AJAX, tetapi sangat sering hook yang lebih baru jauh lebih baik karena memungkinkan untuk instantiate kelas plugin hanya jika diperlukan.

Misalnya kelas yang melakukan hal-hal untuk templat dapat digunakan di "template_redirect".

Secara umum sangat jarang suatu kelas perlu dipakai sebelum "wp_loaded"dipecat.

Tidak Ada Kelas Dewa

Sebagian besar dari semua kelas yang digunakan sebagai contoh dalam jawaban yang lebih lama menggunakan kelas bernama like "Prefix_Example_Plugin"atau "My_Plugin"... Ini menunjukkan bahwa mungkin ada kelas utama untuk plugin.

Ya, kecuali sebuah plugin dibuat oleh satu kelas tunggal (dalam hal ini penamaan setelah nama plugin benar-benar masuk akal), untuk membuat kelas yang mengelola seluruh plugin (misalnya menambahkan semua kait yang dibutuhkan plugin atau membuat instance semua kelas plugin lainnya ) dapat dianggap sebagai praktik buruk, sebagai contoh objek dewa .

Dalam kode pemrograman berorientasi objek harus cenderung SOLID di mana "S" berdiri untuk "Prinsip tanggung jawab tunggal" .

Ini berarti bahwa setiap kelas harus melakukan satu hal. Dalam pengembangan plugin WordPress itu berarti bahwa pengembang harus menghindari untuk menggunakan kait tunggal untuk membuat instantiate kelas plugin utama , tetapi kait yang berbeda harus digunakan untuk instantiate kelas yang berbeda, sesuai dengan tanggung jawab kelas.

Hindari kait di konstruktor

Argumen ini telah diperkenalkan dalam jawaban lain di sini, namun saya ingin berkomentar konsep ini dan menghubungkan jawaban lain ini di mana telah dijelaskan secara luas dalam bidang pengujian unit.

Hampir 2015: PHP 5.2 untuk zombie

Sejak 14 Agustus 2014, PHP 5.3 mencapai akhir hayatnya . Sudah pasti mati. PHP 5.4 akan didukung untuk tahun 2015, artinya untuk satu tahun lagi saat ini saya sedang menulis.

Namun, WordPress masih mendukung PHP 5.2, tetapi tidak ada yang harus menulis satu baris kode pun yang mendukung versi itu, terutama jika kode itu OOP.

Ada beberapa alasan berbeda:

  • PHP 5.2 sudah lama mati, tidak ada perbaikan keamanan yang dirilis untuk itu, itu berarti tidak aman
  • PHP 5.3 menambahkan banyak fitur ke PHP, fungsi anonim , dan ruang nama über alles
  • versi PHP yang lebih baru jauh lebih cepat . PHP gratis. Memperbarui itu gratis. Mengapa menggunakan versi yang lebih lambat dan tidak aman jika Anda dapat menggunakan yang lebih cepat, lebih aman secara gratis?

Jika Anda tidak ingin menggunakan kode PHP 5.4+, gunakan setidaknya 5.3+

Contoh

Pada titik ini saatnya untuk meninjau jawaban yang lebih lama berdasarkan apa yang saya katakan sampai di sini.

Setelah kita tidak perlu peduli lagi dengan 5.2, kita bisa dan harus menggunakan ruang nama.

Demi lebih menjelaskan prinsip tanggung jawab tunggal, contoh saya akan menggunakan 3 kelas, yang melakukan sesuatu di frontend, satu di backend dan yang ketiga digunakan dalam kedua kasus.

Kelas admin:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Kelas frontend:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Antarmuka alat:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

Dan kelas Tools, digunakan oleh dua lainnya:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

Dengan kelas ini, saya bisa instantiate mereka menggunakan kait yang tepat. Sesuatu seperti:

require_once plugin_dir_path( __FILE__ ) . 'src/ToolsInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'src/Tools.php';

add_action( 'admin_init', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/AdminStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $admin_stuff; // this is not ideal, reason is explained below
   $admin_stuff = new GM\WPSE\Example\AdminStuff( $tools ); 
} );

add_action( 'template_redirect', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/FrontStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $front_stuff; // this is not ideal, reason is explained below
   $front_stuff = new GM\WPSE\Example\FrontStuff( $tools );    
} );

Pembalikan Ketergantungan & Injeksi Ketergantungan

Dalam contoh di atas saya menggunakan ruang nama dan fungsi anonim untuk membuat instance kelas yang berbeda pada kait yang berbeda, mempraktikkan apa yang saya katakan di atas.

Perhatikan bagaimana ruang nama memungkinkan untuk membuat kelas bernama tanpa awalan.

Saya menerapkan konsep lain yang secara tidak langsung disebutkan di atas: Injeksi Ketergantungan , itu adalah salah satu metode untuk menerapkan Prinsip Pembalikan Ketergantungan , "D" dalam akronim SOLID.

The Toolskelas "disuntikkan" di dua kelas lainnya ketika mereka dipakai, sehingga dengan cara ini adalah mungkin untuk memisahkan tanggung jawab.

Selain itu, AdminStuffdan FrontStuffkelas menggunakan tipe petunjuk untuk menyatakan mereka membutuhkan kelas yang mengimplementasikan ToolsInterface.

Dengan cara ini kami atau pengguna yang menggunakan kode kami dapat menggunakan implementasi berbeda dari antarmuka yang sama, membuat kode kami tidak digabungkan ke kelas konkret tetapi ke abstraksi: itulah prinsip Ketergantungan Inversi.

Namun, contoh di atas dapat lebih ditingkatkan. Mari kita lihat caranya.

Pemuat otomatis

Cara yang baik untuk menulis kode OOP yang dapat dibaca lebih baik adalah tidak mencampur definisi tipe (Antarmuka, Kelas) dengan kode lain, dan menempatkan setiap jenis dalam file sendiri.

Aturan ini juga merupakan salah satu standar pengkodean PSR-1 1 .

Namun, untuk melakukannya, sebelum dapat menggunakan suatu kelas, seseorang harus memerlukan file yang berisi itu.

Ini mungkin luar biasa, tetapi PHP menyediakan fungsi utilitas untuk memuat kelas secara otomatis saat diperlukan, menggunakan panggilan balik yang memuat file berdasarkan namanya.

Menggunakan ruang nama menjadi sangat mudah, karena sekarang dimungkinkan untuk mencocokkan struktur folder dengan struktur namespace.

Itu tidak hanya mungkin, tetapi juga standar PSR lain (atau lebih baik 2: PSR-0 sekarang sudah tidak digunakan lagi, dan PSR-4 ).

Dengan mengikuti standar itu, dimungkinkan untuk menggunakan alat yang berbeda yang menangani pengisian otomatis, tanpa harus membuat kode autoloader khusus.

Saya harus mengatakan bahwa standar pengkodean WordPress memiliki aturan berbeda untuk penamaan file.

Jadi ketika menulis kode untuk inti WordPress, pengembang harus mengikuti aturan WP, tetapi ketika menulis kode khusus itu adalah pilihan pengembang, tetapi menggunakan standar PSR lebih mudah menggunakan alat yang sudah ditulis 2 .

Pola Akses Global, Registri, dan Penentu Lokasi Layanan.

Salah satu masalah terbesar ketika membuat instance kelas plugin di WordPress, adalah bagaimana mengaksesnya dari berbagai bagian kode.

WordPress sendiri menggunakan pendekatan global : variabel disimpan dalam lingkup global, membuatnya dapat diakses di mana saja. Setiap pengembang WP mengetik kata globalribuan kali dalam karier mereka.

Ini juga pendekatan yang saya gunakan untuk contoh di atas, tetapi itu jahat .

Jawaban ini sudah terlalu lama untuk memungkinkan saya untuk menjelaskan lebih lanjut mengapa, tetapi membaca hasil pertama di SERP untuk "variabel global jahat" adalah titik awal yang baik.

Tetapi bagaimana mungkin untuk menghindari variabel global?

Ada beberapa cara berbeda.

Beberapa jawaban lama di sini menggunakan pendekatan contoh statis .

public static function instance() {

  if ( is_null( self::$instance ) ) {
    self::$instance = new self;
  }

  return self::$instance;
}

Ini mudah dan cukup baik, tetapi memaksa untuk menerapkan pola untuk setiap kelas yang ingin kita akses.

Selain itu, banyak kali pendekatan ini menempatkan pada cara untuk jatuh dalam masalah kelas dewa, karena pengembang membuat diakses kelas utama menggunakan metode ini, dan kemudian menggunakannya untuk mengakses semua kelas lainnya.

Saya sudah menjelaskan betapa buruknya kelas dewa, jadi pendekatan instance statis adalah cara yang baik untuk dilakukan ketika sebuah plugin hanya perlu membuat satu atau dua kelas dapat diakses.

Ini tidak berarti bahwa itu dapat digunakan hanya untuk plugin yang hanya memiliki beberapa kelas, pada kenyataannya, ketika prinsip injeksi dependensi digunakan dengan benar, dimungkinkan untuk membuat aplikasi yang cukup kompleks tanpa perlu membuat secara global dapat diakses dalam jumlah besar benda.

Namun, kadang-kadang plugin perlu membuat beberapa kelas dapat diakses , dan dalam hal ini pendekatan instance statis sangat banyak.

Pendekatan lain yang mungkin adalah dengan menggunakan pola registri .

Ini adalah implementasi yang sangat sederhana:

namespace GM\WPSE\Example;

class Registry {

   private $storage = array();

   function add( $id, $class ) {
     $this->storage[$id] = $class;
   }

   function get( $id ) {
      return array_key_exists( $id, $this->storage ) ? $this->storage[$id] : NULL;
   }

}

Menggunakan kelas ini dimungkinkan untuk menyimpan objek dalam objek registri dengan id, jadi memiliki akses ke registri dimungkinkan untuk memiliki akses ke semua objek. Tentu saja ketika sebuah objek dibuat untuk pertama kali, ia perlu ditambahkan ke dalam registri.

Contoh:

global $registry;

if ( is_null( $registry->get( 'tools' ) ) ) {
  $tools = new GM\WPSE\Example\Tools;
  $registry->add( 'tools', $tools );
}

if ( is_null( $registry->get( 'front' ) ) ) {
  $front_stuff = new GM\WPSE\Example\FrontStuff( $registry->get( 'tools' ) );    
  $registry->add( 'front', front_stuff );
}

add_action( 'wp', array( $registry->get( 'front' ), 'wp' ) );

Contoh di atas menjelaskan bahwa agar berguna, registri harus dapat diakses secara global. Variabel global untuk registri tunggal tidak terlalu buruk, namun untuk puritan non-global dimungkinkan untuk menerapkan pendekatan contoh statis untuk registri, atau mungkin fungsi dengan variabel statis:

function gm_wpse_example_registry() {
  static $registry = NULL;
  if ( is_null( $registry ) ) {
    $registry = new GM\WPSE\Example\Registry;
  }
  return $registry;
}

Pertama kali fungsi dipanggil itu akan instantiate registri, pada panggilan berikutnya hanya akan mengembalikannya.

Metode khusus WordPress lainnya untuk membuat kelas dapat diakses secara global adalah mengembalikan instance objek dari filter. Sesuatu seperti ini:

$registry = new GM\WPSE\Example\Registry;

add_filter( 'gm_wpse_example_registry', function() use( $registry ) {
  return $registry;
} );

Setelah itu di mana-mana registri diperlukan:

$registry = apply_filters( 'gm_wpse_example_registry', NULL );

Pola lain yang dapat digunakan adalah pola locator layanan . Ini mirip dengan pola registri, tetapi pelacak layanan dilewatkan ke berbagai kelas menggunakan injeksi ketergantungan.

Masalah utama dengan pola ini adalah menyembunyikan dependensi kelas yang membuat kode lebih sulit untuk dipelihara dan dibaca.

Wadah DI

Tidak masalah metode yang digunakan untuk membuat pendaftar registri atau layanan dapat diakses secara global, benda-benda harus disimpan di sana, dan sebelum disimpan, mereka harus dibuat instantiated.

Dalam aplikasi yang kompleks, di mana terdapat cukup banyak kelas dan banyak dari mereka memiliki beberapa dependensi, kelas instantiating membutuhkan banyak kode, sehingga kemungkinan bug meningkat: kode yang tidak ada tidak dapat memiliki bug.

Dalam beberapa tahun terakhir, muncul beberapa perpustakaan PHP yang membantu pengembang PHP untuk dengan mudah membuat instance dan menyimpan instance objek, secara otomatis menyelesaikan dependensi mereka.

Perpustakaan ini dikenal sebagai Kontainer Injeksi Ketergantungan karena mereka mampu membuat instance kelas menyelesaikan dependensi dan juga untuk menyimpan objek dan mengembalikannya saat diperlukan, bertindak serupa dengan objek registri.

Biasanya, ketika menggunakan wadah DI, pengembang harus mengatur dependensi untuk setiap kelas aplikasi, dan kemudian pertama kali kelas diperlukan dalam kode itu instantiated dengan dependensi yang tepat dan instance yang sama dikembalikan lagi dan lagi pada permintaan berikutnya .

Beberapa kontainer DI juga mampu menemukan dependensi secara otomatis tanpa konfigurasi, tetapi menggunakan refleksi PHP .

Beberapa wadah DI yang terkenal adalah:

dan banyak lagi.

Saya ingin menunjukkan bahwa untuk plugin sederhana, yang hanya melibatkan beberapa kelas dan kelas tidak memiliki banyak dependensi, mungkin tidak layak menggunakan wadah DI: metode contoh statis atau registri yang dapat diakses global adalah solusi yang baik, tetapi untuk plugin kompleks manfaat wadah DI menjadi jelas.

Tentu saja, bahkan objek kontainer DI harus dapat diakses untuk digunakan dalam aplikasi dan untuk tujuan itu dimungkinkan untuk menggunakan salah satu metode yang terlihat di atas, variabel global, variabel instance statis, objek kembali melalui filter dan sebagainya.

Komposer

Untuk menggunakan wadah DI sering berarti menggunakan kode pihak ke-3. Saat ini, di PHP, ketika kita perlu menggunakan lib eksternal (jadi tidak hanya wadah DI, tetapi kode apa pun yang bukan bagian dari aplikasi), cukup mengunduhnya dan meletakkannya di folder aplikasi kita tidak dianggap sebagai praktik yang baik. Bahkan jika kita adalah penulis potongan kode lainnya.

Memisahkan kode aplikasi dari dependensi eksternal adalah tanda organisasi yang lebih baik, keandalan yang lebih baik, dan kewarasan kode yang lebih baik.

Komposer , adalah standar de-facto di komunitas PHP untuk mengelola dependensi PHP. Jauh untuk menjadi arus utama di komunitas WP juga, itu adalah alat yang setiap pengembang PHP dan WordPress setidaknya harus tahu, jika tidak digunakan.

Jawaban ini sudah sebesar buku untuk memungkinkan diskusi lebih lanjut, dan juga membahas Komposer di sini mungkin di luar topik, itu hanya disebutkan demi kelengkapan.

Untuk informasi lebih lanjut kunjungi situs Komposer dan itu juga layak memberikan membaca untuk ini Minisite dikuratori oleh @Rarst .


1 PSR adalah aturan standar PHP yang dirilis oleh PHP Framework Interop Group

2 Komposer (pustaka yang akan disebutkan dalam jawaban ini) antara lain juga berisi utilitas autoloader.

gmazzap
sumber
1
Catatan tambahan, bahwa PHP 5.3 juga adalah akhir hidup. Tuan rumah yang bertanggung jawab akan menawarkan setidaknya 5,4 sebagai opsi jika bukan default
Tom J Nowell
2
"Sejak 14 Agustus 2014, PHP 5.3 mencapai akhir hayatnya. Sudah pasti mati." Adalah baris pertama di bawah "PHP 5.2 is for zombie" @TomJNowell
gmazzap
3
Hanya ingin tahu, seperti apa Anda menunjukkan "banyak hal" ? ;-)
MikeSchinkel
Dalam upaya menghindari variabel global, saya menyukai ide pola Registry dengan fungsi & variabel statis. Pertama kali fungsi dipanggil itu akan instantiate registri, pada panggilan berikutnya hanya akan mengembalikannya.
Michael Ecklund
10

Saya menggunakan struktur berikut:

Prefix_Example_Plugin::on_load();

/**
 * Example of initial class-based plugin load.
 */
class Prefix_Example_Plugin {

    /**
     * Hooks init (nothing else) and calls things that need to run right away.
     */
    static function on_load() {

        // if needed kill switch goes here (if disable constant defined then return)

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    /**
     * Further hooks setup, loading files, etc.
     *
     * Note that for hooked methods name equals hook (when possible).
     */
    static function init(  ) {


    }
}

Catatan:

  • telah menetapkan tempat untuk hal-hal yang perlu segera dijalankan
  • menonaktifkan / mengganti untuk tweak mudah (melepas satu initmetode)
  • Saya rasa saya tidak pernah menggunakan / membutuhkan objek dari kelas plugin - perlu melacaknya, dll; ini benar-benar palsu dengan sengaja, bukan OOP (sebagian besar waktu)

Penafian Saya belum menggunakan unit test ( banyak hal di myplate ) dan saya dengar statis bisa kurang disukai. Lakukan riset tentang ini jika Anda perlu mengujinya.

Jarang
sumber
3
Saya tahu orang-orang besar pada pengujian unit benar-benar tidak suka solusi statis / tunggal. Saya pikir jika Anda benar-benar memahami apa yang ingin Anda capai dengan menggunakan statis dan setidaknya menyadari konsekuensi dari melakukan hal itu maka sangat baik untuk menerapkan metode tersebut. Topik-topik bagus seputar masalah ini di Stack Overflow
Adam
Ini membuat saya benar-benar berpikir. Jadi mengapa menggunakan Kelas lalu dan tidak hanya kembali ke fungsi awalan sederhana. Apakah kita melakukan ini hanya untuk memiliki nama fungsi / metode yang lebih bersih? Maksud saya menyuruh mereka bersarang dengan "statis" b4 mereka, apakah itu jauh lebih mudah dibaca? Kemungkinan memiliki konflik nama hampir sama dengan nama kelas tunggal jika Anda menggunakan awalan yang tepat atau apakah saya kehilangan sesuatu?
James Mitch
1
@ JamesMitch ya, metode semua-statis sebagian besar hanya berfungsi dengan namespace palsu seperti yang digunakan dalam WP. Namun kelas memang memiliki beberapa keunggulan dibandingkan fungsi murni bahkan dalam kasus ini, seperti autoload dan inheritance. Akhir-akhir ini saya telah bergerak dari metode statis dan menuju objek instantiated nyata yang diselenggarakan oleh wadah injeksi ketergantungan.
Jarang
3

Itu semua tergantung pada fungsionalitas.

Saya pernah membuat plugin yang mendaftarkan skrip ketika konstruktor dipanggil jadi saya harus mengaitkannya di wp_enqueue_scriptshook.

Jika Anda ingin menyebutnya ketika functions.phpfile Anda dimuat, Anda mungkin juga membuat instance sendiri $class_instance = new ClassName();seperti yang Anda sebutkan.

Anda mungkin ingin mempertimbangkan kecepatan dan penggunaan memori. Saya tidak mengetahui adanya, tetapi saya bisa membayangkan ada kait tidak beralasan dalam beberapa kasus. Dengan membuat instance Anda di kait itu Anda dapat menghemat beberapa sumber daya server.

Tim S.
sumber
Terima kasih keren untuk itu, saya kira ada dua poin untuk pertanyaan di atas juga. Yang lain adalah apakah __construct cocok atau apakah init () adalah cara yang lebih baik untuk menginisialisasi kelas.
kalpaitch
1
Yah aku akan pergi untuk init()metode statis sehingga instance kelas dipanggil dalam ruang lingkup kelas 'daripada ruang lingkup lain di mana Anda mungkin bisa menimpa variabel yang ada.
Tim S.
0

Saya tahu ini berumur beberapa tahun, tetapi sementara itu php 5.3 mendukung metode anonim , jadi saya datang dengan ini:

add_action( 'plugins_loaded', function() { new My_Plugin(); } );

dan entah bagaimana aku paling menyukainya. Saya dapat menggunakan konstruktor biasa dan tidak perlu mendefinisikan metode "init" atau "on_load" yang mengacaukan struktur OOP saya.

Basti
sumber