Dalam situasi di mana plugin telah merangkum metode-metodenya di dalam kelas dan kemudian mendaftarkan filter atau tindakan terhadap salah satu metode itu, bagaimana Anda menghapus aksi atau filter jika Anda tidak lagi memiliki akses ke instance kelas itu?
Misalnya, Anda memiliki plugin yang melakukan ini:
class MyClass {
function __construct() {
add_action( "plugins_loaded", array( $this, 'my_action' ) );
}
function my_action() {
// do stuff...
}
}
new MyClass();
Memperhatikan bahwa saya sekarang tidak memiliki cara untuk mengakses instance, bagaimana saya membatalkan registrasi kelas? Ini: remove_action( "plugins_loaded", array( MyClass, 'my_action' ) );
tampaknya bukan pendekatan yang tepat - setidaknya, sepertinya tidak berhasil dalam kasus saya.
Jawaban:
Hal terbaik untuk dilakukan di sini adalah menggunakan kelas statis. Kode berikut harus instruksional:
Jika Anda menjalankan kode ini dari plugin, Anda harus memperhatikan bahwa metode StaticClass dan juga fungsinya akan dihapus dari wp_footer.
sumber
remove_action
fungsi, jika tidak itu tidak akan berhasil ... itu sebabnya saya harus menulis fungsi saya sendiri untuk menangani ketika itu bukan kelas statis. Jawaban ini hanya akan menjadi yang terbaik jika pertanyaan Anda mengenai kode Anda sendiri, jika tidak, Anda akan mencoba untuk menghapus filter / tindakan lain dari basis kode orang lain dan tidak dapat mengubahnya ke statisSetiap kali plugin membuat
new MyClass();
, itu harus menetapkannya ke variabel bernama unik. Dengan begitu, instance kelas dapat diakses.Jadi jika dia melakukannya
$myclass = new MyClass();
, maka Anda bisa melakukan ini:Ini berfungsi karena plugin termasuk dalam namespace global, jadi deklarasi variabel implisit di bagian utama plugin adalah variabel global.
Jika plugin tidak menyimpan pengenal kelas baru di suatu tempat , maka secara teknis, itu bug. Salah satu prinsip umum Pemrograman Berorientasi Objek adalah bahwa objek yang tidak dirujuk oleh beberapa variabel di suatu tempat dapat dibersihkan atau dihilangkan.
Sekarang, PHP khususnya tidak melakukan ini seperti Java, karena PHP adalah implementasi OOP setengah-arsed. Variabel instance hanya string dengan nama objek unik di dalamnya, semacam itu. Mereka hanya bekerja karena cara interaksi nama fungsi variabel bekerja dengan
->
operator. Jadi melakukan sesuatunew class()
memang dapat bekerja dengan sempurna, hanya dengan bodoh. :)Jadi, intinya, jangan pernah lakukan
new class();
. Lakukan$var = new class();
dan buat agar $ var dapat diakses dengan cara tertentu untuk bit lain untuk merujuknya.Edit: bertahun-tahun kemudian
Satu hal yang saya lihat banyak plugin lakukan adalah menggunakan sesuatu yang mirip dengan pola "Singleton". Mereka membuat metode getInstance () untuk mendapatkan instance tunggal dari kelas. Ini mungkin solusi terbaik yang pernah saya lihat. Plugin contoh:
Pertama kali getInstance () dipanggil, instantiate kelas dan menyimpan pointer-nya. Anda dapat menggunakannya untuk mengaitkan tindakan.
Satu masalah dengan ini adalah Anda tidak bisa menggunakan getInstance () di dalam konstruktor jika Anda menggunakan hal seperti itu. Ini karena baru memanggil konstruktor sebelum menetapkan $ instance, jadi memanggil getInstance () dari konstruktor mengarah ke loop tak terbatas dan merusak segalanya.
Salah satu solusinya adalah tidak menggunakan konstruktor (atau, setidaknya, tidak menggunakan getInstance () di dalamnya), tetapi untuk secara eksplisit memiliki fungsi "init" di kelas untuk mengatur tindakan Anda dan semacamnya. Seperti ini:
Dengan sesuatu seperti ini, di akhir file, setelah kelas telah ditentukan dan semacamnya, instantiating plugin menjadi sesederhana ini:
Init mulai menambahkan tindakan Anda, dan dengan melakukan hal itu memanggil getInstance (), yang membuat instance kelas dan memastikan hanya satu saja yang ada. Jika Anda tidak memiliki fungsi init, Anda akan melakukan ini untuk membuat instance kelas pada awalnya sebagai gantinya:
Untuk menjawab pertanyaan awal, menghapus kait tindakan dari luar (alias, di plugin lain) kemudian dapat dilakukan seperti:
Masukkan itu ke dalam sesuatu yang dikaitkan dengan
plugins_loaded
kait tindakan dan itu akan membatalkan tindakan yang dikaitkan oleh plugin asli.sumber
wp_loaded
, bukanplugins_loaded
, yang mungkin disebut terlalu dini.plugins_loaded
akan menjadi tempat yang benar. Thewp_loaded
aksi terjadi setelahinit
tindakan, jadi jika plugin anda mengambil tindakan apapun padainit
(dan kebanyakan lakukan), maka Anda ingin menginisialisasi plugin dan mengaturnya sebelum itu. Theplugins_loaded
kait adalah tempat yang tepat untuk itu tahap konstruksi.2 fungsi PHP kecil untuk memungkinkan penghapusan filter / aksi dengan kelas "anonim": https://github.com/herewithme/wp-filters-extras/
sumber
Berikut adalah fungsi yang terdokumentasi secara luas yang saya buat untuk menghapus filter ketika Anda tidak memiliki akses ke objek kelas (berfungsi dengan WordPress 1.2+, termasuk 4.7+):
https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
sumber
Solusi di atas terlihat seperti ketinggalan zaman, harus menulis sendiri ...
sumber
Fungsi ini berdasarkan jawaban @Digerkam. Ditambahkan membandingkan jika
$def['function'][0]
adalah string dan akhirnya berhasil untuk saya.Juga menggunakan
$wp_filter[$tag]->remove_filter()
harus membuatnya lebih stabil.Contoh penggunaan:
Benar-benar cocok
Prioritas apa pun
Kelas apa pun dan prioritas apa pun
sumber
Ini bukan jawaban umum, tetapi satu khusus untuk tema Avada dan WooCommerce , yang saya pikir orang lain mungkin membantu:
sumber