Kancalar, Hatlar ve Syker: Yeni WP_HOOK Sınıfı WordPress
Bu yazının amaçları için WordPress Hook System (yani add_filter (), add_action (), appling_filters () ve do_action ()) ne olduğunu bildiğinizi ve nasıl çalıştığına dair genel bir resme sahip olduğunuzu düşüneceğim. Bu aynı zamanda değişim içeren yayınları okumak için de iyi bir fikirdir. Ne değişti? WordPress 4.7’de tanıtılan büyük değişikliklerden biri yeni WP_HOOK sınıfıdır. Bu yeni sınıf artık WordPress’in çekirdeğindeki tüm dahili kancaları işlemek için kullanılmaktadır. Bu büyük bir problem. 4,7 öncesi, tüm kanca işlevleri (add_filter () vb.) Ve mantık doğrudan WP-Accestagees/Plugin.php’de işlenir. Şimdi, WP_HOOK sınıfı WP-IninCludes/Plugin.php’den dahildir ve her filtre işlevi temel olarak yalnızca uygun WP_HOOK yöntemini çağırır.
Örneğin, bu, mevcut klasik add_filter () işlevidir: function add_filter ($ tag, $ function_to_add, $ öncelik = 10, $ cpessed_args = 1) {global $ wp_filter; if (! isset ($ wp_filter [$ tag])) {$ wp_filter [$ tag] = yeni wp_hook (); } $ wp_filter [$ tag]-> add_filter ($ tag, $ function_to_add, $ öncelik, $ cpabired_args); Dönüş; } Gördüğünüz gibi, global değişken $ wp_filter [$ tag] artık wp_hook’dan yeni bir örnek verilir ve daha sonra uygun wp_hook :: add_filter () yöntemini çağırır. Bunu daha uzun bir sürümle karşılaştırın: function add_filter ($ tag, $ function_to_add, $ priority = 10, $ cpabired_args = 1) {global $ wp_filter, $ meged_filters; $ idx = _wp_filter_build_unique_id ($ tag, $ function_to_add, $ öncelik); $ wp_filter [$ tag] [$ öncelik] [$ idx] = array (‘function’ => $ function_to_add, ‘cpessed_args’ => $ csempleed_args); Unset ($ Merged_filters [$ etiket]); Dönüş; } Buradaki anahtar kısım, bu işlevin 4.7 sürümünden önce tüm kuyruk filtrelerini barındırmak için çok boyutlu bir dizi ($ wp_filter) yapmasıdır. Yeni sürümde, bazı mantık WP_HOOK sınıfına aktarıldı, ancak görebileceğimiz gibi, Global WP_Filter artık çok iç içe bir dizi değil, bir nesne dizisi.
Geriye dönük uyumluluğu korumak ve insanların koduna zarar vermekten kaçınmak için WP_HOOK sınıfı ArrayicCess ve Yineleyici arayüzünü uygular. Basitçe söylemek gerekirse, bu iki arayüz WP_HOOK sınıfına erişilmesine ve hala tüm nesne işlevselliğine sahipken dizi gibi çalışmasına izin verir. Performans, yeni filtre işlevi için ana endişe kaynağıdır. Eski kanca sistemi çok hızlıdır, çoğu site istek başına binlerce kez vurur. Performansı korumak önemlidir, o zaman neden güncellenmiş kanca sistemi daha fazla soyut nesne tabanlı uygulama, potansiyel olarak daha yavaş kullanıyor? Cevap, dizi işaretçisinin Loop ile nasıl çalıştığıdır. Jonathan Brinly, kanca sistemi ile ilgili ana sorunu tartışıyor (ve sonuç olarak çoğu çözümle ortaya çıkıyor). Mesele şu ki, eski add_action () uygulaması, dolandırıcılık ($ wp_filter [$ etiket]) için bir çağrı ile dolandırıcılık döngüsünde bir foreach döngüsü kullanıyor: do {forEach ((dizi) akım ($ wp_filter [$ tag]) $ the_) ise (! Is_null ($ the _ [‘işlev’]))) {$ args [1] = $ değer; $ value = call_user_func_array ($ _ [‘işlev’], array_slice ($ args, 1, (int) _ [‘circeded_args’]))); }} while (sonraki ($ wp_filter [$ tag])! == false); TRAC biletindeki ilk cümle, bu mantıkla ilgili ana sorunu açıklıyor:
Aynı kancadan çağrılan işlevden belirli bir kanca çağırırken, ilk yinelemeden kalan kanca işlevi atılır.Sorunlar özyineleme nedeniyle, özellikle arka çağrı aynı eyleme bağlandığında ortaya çıkar.Jonathan’ın yazısında buna iyi bir örneği var: işlev my_first_callback ($ post_id, $ post) {if ($ post-> post_type == ‘post’) {wp_insert_post (‘post_title’ => ‘A Post’, ‘Post_status’ => ‘yayın’, ‘post_type’ => ‘a_custom_post_type’,);}} işlev my_second_callback ($ post_id, $ post) {// başka bir şey yapın} add_ace (‘save_post’, ‘my_first_callback’, 10, 2);// Asla add_action (‘save_post’, ‘my_second_callback’, 15, 2);WP_INSERT_POST () işlevinin yerleştirilmesine dikkat ediyor musunuz?İşlevin işlevi, başka bir Save_Post eylemini tetikleyerek özyinelemeli özyinelemeli geri dönme döngüleri oluşturacaktır.
WP_INSERT_POST () Bu yuvalama DO_RACTION (‘Save_post’) tetikler ve DO_RACTION işlevinin $ wp_filter [‘save_post’] aracılığıyla tekrar etmesine neden olur. Bu, PHP’nin Next () işlevine çağrı, while maddesi tetiklenene kadar olur. Çağrı Do_ace, bu noktada dizi işaretçisi $ wp_filter [‘save_post’] ‘nın sonuna taşındı ve döngü sona erdi. Bu senaryoda, add_action (‘save_post’, ‘my_second_callback’, 15, 2) asla çağrılmadı. $ Wp_filter nasıl düzenlendiğini hatırlarsanız, bunun neden olduğunu göreceksiniz: $ wp_filter [$ tag] [$ öncelik] [$ idx] = array (‘function’ => $ function_to_add, ‘cpespeed_args’ => $ consired_args); Bu durumda, satır göstergesini dahili dizinin sonuna taşımak için bir sonraki () çağrılana kadar $ wp_filter [‘save_post’] için tetiklendi. Tekrar tamamlandıktan sonra, gelecekte bir sonraki önceliğe sahip $ WP_Filter’ın üst seviyesiyle ilgili herhangi bir işlem yapılmayacaktır. Bunun nedeni WordPress, $ wp_filter dizisini tamamen döngü olarak görüyor .do {foreach ((dizi) current ($ wp_filter [$ tag]) {if (! Is_null ($ _ [‘işlev’]) { $ args [1] = $ değer; $ value = call_user_func_array ($ _ [‘işlev’], array_slice ($ args, 1, (int) _ [‘circeded_args’]))); }}} while (sonraki ($ wp_filter [$ tag])! == false); // geri arama [$ öncelik]); $ this-> geri arama [$ öncelikli] [$ idx] = array (‘function’ => $ function_to_add, ‘cpespeed_args’ => $ cevaped_args); // Listeye yeni bir öncelik ekliyorsanız, (! $ priority_existed && count ($ this-> geri arama)> 1) {kSort ($ this-> geri arama, sort_numeric); } if ($ this-> nesting_level> 0) {$ this-> resort_active_itections ($ öncelik, $ priority_existed); }} Eski add_filter () işlevi:
Function add_filter ($ tag, $ function_to_add, $ öncelik = 10, $ cpabired_args = 1) {global $ wp_filter, $ meged_filters;$ idx = _wp_filter_build_unique_id ($ tag, $ function_to_add, $ öncelik);$ wp_filter [$ tag] [$ öncelik] [$ idx] = array (‘function’ => $ function_to_add, ‘cpessed_args’ => $ csempleed_args);Unset ($ Merged_filters [$ etiket]);Dönüş;} Yeni bir kodda $ this-> resort_active_itections ($ priority, $ priority_existed) yeni çağrısının olduğunu unutmayın?Bu, yineleme sırasında öncelik öncelikli yeniden belirleme işlemlerini işlemek için oluşturulan yeni bir yöntemdir.Bu yöntem, önceki yineleme öncelik sorunlarının geliştirilmesinin bir parçasıdır.Tüm bu tekrarlar başınızı döndürüyor mu?
Her filtrenin yürütülmesinde farkı da görebilirsiniz. Applate_filters () kodu wp_hook üzerinde yeni: public function uygulama_filters ($ value, $ args) {if (! $ This-> callbacks) {return $ değeri; } $ nesting_level = $ this-> nesting_level ++; $ this-> iterations [$ nesting_level] = array_keys ($ this-> geri arama); $ num_args = count ($ args); do {$ this-> current_priority [$ nesting_level] = $ öncelik = current ($ this-> iterations [$ nesting_level]); foreach ($ this-> geri arama [$ öncelik] $ the_) {if (! $ this-> doing_raction) {$ args [0] = $ değer; } // Mümkünse Array_Slice’den kaçının. if ($ _ [‘circeded_args’] == 0) {$ value = call_user_func_array ($ _ [‘function’], array ()); } elseif ($ _ [‘circeded_args’]> = $ num_args) {$ value = call_user_func_array ($ _ [‘işlev’], $ args); } else {$ value = call_user_func_array ($ _ [‘function’], array_slice ($ args, 0, (int) _ [‘circeded_args’])); }}} while (false! == Next ($ this-> iterations [$ nesting_level])); Unset ($ this-> iterations [$ nesting_level]); Unset ($ this-> current_priority [$ nesting_level]); $ this-> nesting_level–; $ değeri döndür; } Appling_filters () wp-accestiones/plugin.php üzerinde eski kodu uygulama_filters ($ tags, $ değer) {global $ wp_filter, $ Merged_filters, $ wp_current_filter; … do {foreach ((dizi) current ($ wp_filter [$ tag]) $ the_) olarak (! Is_null ($ the _ [‘işlev’])) {$ args [1] = $ değer; $ value = call_user_func_array ($ _ [‘işlev’], array_slice ($ args, 1, (int) _ [‘circeded_args’]))); }} while (sonraki ($ wp_filter [$ tag])! == false); array_pop ($ wp_current_filter); $ değeri döndür;
} Gördüğünüz gibi, arama uygulanırken geçerli filtre yinelemesini ve geçerli filtre durumunu işleyen kodun yeni sürümü.Önceki Applate_filters () sürümü, yürütülen kancanın yuvalama, yinelemesi veya önceliği seviyesini dikkate almadı.Ters uyumluluk Bildiğiniz gibi, WordPress Core’un geliştirilmesindeki temel kavramlardan biri geriye dönük uyumluluktur.WordPress, eklentideki eski kodu sağlamak için iyi bir iş çıkarır ve tema en son sürümle çalışmaya devam eder.Genellikle bu, daha yeni PHP özelliklerinin kullanılamayacağı ve her şeyin eski kodlarla çalışmasını sağlamak için bazı yaratıcı düşünceler gerektirdiği anlamına gelir.WP_HOOK durumunda, bu, ‘Array gibi’ işlevselliğini korumak için ArrayicCess ve Yineleyici arayüzünü kullanmak anlamına gelir.
Doğrudan $ wp_filter dokunan eski kodlar için kullanılabilir. Yamanın geçmişini gören, yeniden düzenleme yoluyla WP_HOOK sınıfı için birçok başlangıç kodu Php 5.2’yi destekleyecek kadar büyüktür. Kabul edip etmeseniz de, WordPress Core’un geliştiricisinin hala geriye dönük uyumluluğa öncelik verdiği ve ortamından bağımsız olarak tüm yeni kodları (özellikle her geliştiriciyi etkileyen kod) işlevini sağladığı açıktır. Bu geliştiriciler için ne anlama geliyor? Post.wordpress.org Post’ta açıklandığı gibi, birçok kişi için bu yeni sınıf kodlarını etkilememelidir. Yani, kodunuzda add_action () veya add_filter () kullanıyorsanız, hazırsınız. Ana sorun, doğrudan $ wp_filter kullanan bir kod için ortaya çıkar. Kodunuzun etkilenebileceği bazı örnekler vardır ve yazıda açıklanır. Global $ wp_filter’ı uyumluluk mu-plugin’de değiştirdiğimizde WP Migrate DB Pro eklentisinde küçük bir değişiklik yaptık. Burada vurgulanması gereken bir diğer önemli şey de WordPress Core ekibinin kod tabanında nasıl büyük bir değişiklik planladığıdır. Bu, proje için uyumluluğu geri çekmenin ve eski kodu desteklemek için bazı yaratıcı yaklaşımlar göstermenin ne kadar önemli olduğunu gösterir. WP_HOOK sınıfının geliştirilmesi, WordPress Core’a kod güncellemesinin ne kadar eklendiğini vurguladığı için geliştirici tarafından dikkate alınması gereken ilginç bir durumdur. Kullanılan bazı yaklaşımlar kendi kodunuzu yeniden aktarmak için yararlı olabilir. Bu, özellikle şimdi değişen bir çekirdek geliştirme süreci ile hoş bir zamandır ve yangın dinlenme WordPress 4.8’de WP-ADMIN’i devralır!