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();
}
sumber
Jawaban:
Pertanyaan bagus, ada sejumlah pendekatan dan itu tergantung pada apa yang ingin Anda capai.
Saya sering melakukannya;
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.
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.
sumber
update.php
file 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 iniplugins_loaded
. Inilah yang sering saya sebut sebagai gambaran singkat tentang apa yang terjadi ketika Referensi Tindakan . Penjelasan saya tidak lengkap secara keseluruhan.register_activation_hook()
Anda harus memanggil fungsi itu sebelumplugins_loaded
tindakan telah dipicu.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:
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:
Kelas frontend:
Antarmuka alat:
Dan kelas Tools, digunakan oleh dua lainnya:
Dengan kelas ini, saya bisa instantiate mereka menggunakan kait yang tepat. Sesuatu seperti:
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
Tools
kelas "disuntikkan" di dua kelas lainnya ketika mereka dipakai, sehingga dengan cara ini adalah mungkin untuk memisahkan tanggung jawab.Selain itu,
AdminStuff
danFrontStuff
kelas menggunakan tipe petunjuk untuk menyatakan mereka membutuhkan kelas yang mengimplementasikanToolsInterface
.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
global
ribuan 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 .
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:
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:
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:
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:
Setelah itu di mana-mana registri diperlukan:
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.
sumber
Saya menggunakan struktur berikut:
Catatan:
init
metode)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.
sumber
Itu semua tergantung pada fungsionalitas.
Saya pernah membuat plugin yang mendaftarkan skrip ketika konstruktor dipanggil jadi saya harus mengaitkannya di
wp_enqueue_scripts
hook.Jika Anda ingin menyebutnya ketika
functions.php
file 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.
sumber
init()
metode statis sehingga instance kelas dipanggil dalam ruang lingkup kelas 'daripada ruang lingkup lain di mana Anda mungkin bisa menimpa variabel yang ada.Saya tahu ini berumur beberapa tahun, tetapi sementara itu php 5.3 mendukung metode anonim , jadi saya datang dengan ini:
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.
sumber