Hooks, Line ve Platin: WordPress' Yeni WP_Hook Sınıfı


Kanca sistemi, WordPress'in temel direğidir ve 4.7 sürümüyle birlikte, nasıl çalıştığına dair büyük bir revizyon birleştirildi. Başlangıçta kanca sistemiyle ilgili bir sorunu ortaya çıkaran Trac bileti, 6 yıldan uzun bir süre önce günlüğe kaydedildi. Birkaç denemeden sonra, güncellemeler nihayet 4.7 sürümüne ulaştı ve saygıdeğer kanca sistemi elden geçirildi. Bu yazıda, yeni WP_Hook sınıfına giren bazı teknik değişiklikleri ve kararları gözden geçirmek istiyorum. Ayrıca, WordPress çekirdek geliştirmenin daha ilginç yönlerinden bazılarını gözden geçireceğim ve WordPress çekirdeğindeki önemli bir özelliği elden geçirmek için ne gerektiğine bakacağım.

Bu yazının amaçları doğrultusunda, WordPress kanca sisteminin ne olduğunu (yani add_filter() , add_action() , apply_filters() ve do_action() ) bildiğinizi ve nasıl çalıştığı hakkında genel bir fikriniz olduğunu varsayacağım. Değişiklikleri kapsayan Make blog gönderisini okumak da iyi bir fikir olacaktır.

Neler Değişti?

WordPress 4.7'de sunulan en büyük değişikliklerden biri, yeni bir WP_Hook sınıfının olmasıdır. Bu yeni sınıf artık WordPress çekirdeğindeki tüm dahili kancaları işlemek için kullanılıyor. Önemli bir şey. 4.7 öncesi, tüm kanca işlevleri ( add_filter() vb.) ve mantık doğrudan wp-includes/plugin.php içinde işlendi. Şimdi, WP_Hook sınıfı wp-includes/plugin.php dosyasından dahil edilmiştir ve her filtre işlevi esasen sadece karşılık gelen WP_Hook yöntemini çağırır.

Örneğin, klasik add_filter() işlevi şu anda böyle görünüyor:

 function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { global $wp_filter; if ( ! isset( $wp_filter[ $tag ] ) ) { $wp_filter[ $tag ] = new WP_Hook(); } $wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args ); return true; }

Gördüğünüz gibi $wp_filter[ $tag ] global değişkenine şimdi yeni bir WP_Hook örneği atanmış ve bu örnek daha sonra karşılık gelen WP_Hook::add_filter() yöntemini çağırmıştır.

Bunu eski sürümle karşılaştırın:

 function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { global $wp_filter, $merged_filters; $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); unset( $merged_filters[ $tag ] ); return true; }

Buradaki anahtar kısım, bu işlevin 4.7 öncesi sürümlerinin, sıraya alınmış tüm filtreleri tutmak için çok boyutlu bir dizi ( $wp_filter ) oluşturmasıdır. Yeni sürümde, bu mantığın bir kısmı WP_Hook sınıfına taşındı, ancak gördüğümüz gibi, $wp_filter global artık derinlemesine yuvalanmış bir dizi değil, bir nesneler dizisi.

Geriye dönük uyumluluğu korumak ve insanların kodunu kırmamak için WP_Hook sınıfı, ArrayAccess ve Iterator arabirimlerini uygular. Basitçe, bu iki arabirim, WP_Hook sınıfının erişilebilir olmasına ve bir nesnenin tüm işlevselliğine sahipken bir dizi gibi çalışmasına izin verir.

Performans, yeni filtre işlevleri için büyük bir endişe kaynağıydı. Eski kanca sistemi, çoğu sitenin istek başına binlerce kez vurduğu son derece hızlıydı. Performansı korumak önemliydi, o halde güncellenmiş bir kanca sistemi neden daha soyutlanmış, potansiyel olarak daha yavaş, nesne tabanlı bir uygulama kullansın? Bu yanıt, dizi işaretçilerinin do-while döngüsüyle nasıl çalıştığıyla ilgilidir.

Jonathan Brinly, kanca sistemiyle ana konuyu ele alıyor (ve sonuç olarak, çözümün büyük bir bölümünü buldu). Eski add_action() uygulamasının, while yan tümcesinde next($wp_filter[$tag]) çağrısıyla birlikte bir do-while döngüsü içinde bir foreach döngüsü kullanmasıdır:

 do { foreach ( (array) current($wp_filter[$tag]) as $the_ ) if ( !is_null($the_['function']) ){ $args[1] = $value; $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } } while ( next($wp_filter[$tag]) !== false );

Trac biletindeki ilk cümle, bu mantıkla ilgili ana sorunu özetlemektedir:

Aynı kanca aracılığıyla çağrılan bir işlevden belirli bir kancayı çağırırken, ilk yinelemeden kalan kancalı işlevler atılır.

Sorun, özellikle bir geri arama aynı eyleme bağlandığında, özyineleme nedeniyle oluşur. Jonathan'ın yazısında buna güzel bir örnek var:

 function my_first_callback( $post_id, $post ) { if ( $post->post_type == 'post' ) { wp_insert_post( array( 'post_title' => 'A Post', 'post_status' => 'publish', 'post_type' => 'a_custom_post_type', ) ); } } function my_second_callback( $post_id, $post ) { // do something else } add_action('save_post', 'my_first_callback', 10, 2); //Never called add_action('save_post', 'my_second_callback', 15, 2);

wp_insert_post() işlevinin yerleşimine dikkat edin? Bu işlev çağrısı, iç içe geçmiş, özyinelemeli bir geri arama döngüsü oluşturarak başka bir save_post eylemini tetikler.

Bu iç içe wp_insert_post() çağrısı, do_action('save_post') işlevini tetikler ve do_action işlevinin $wp_filter['save_post'] dizisi içinde dolaşmasına neden olur.

Bu, while yan tümcesindeki PHP next() işlevine yapılan bir çağrı tetiklenene kadar gerçekleşir. do_action çağrılarının iç içe geçmesi nedeniyle, bu noktada dizi işaretçisi $wp_filter['save_post'] dizisinin sonuna taşınır ve döngü sona erer.

Bu senaryoda, add_action( 'save_post', 'my_second_callback', 15, 2 ) bloğu hiçbir zaman çağrılmaz. $wp_filter'ın nasıl yapılandırıldığını hatırlarsanız, bunun neden olduğunu göreceksiniz:

 $wp_filter[ $tag ][ $priority ][ $idx ] = array( 'function' => $function_to_add, 'accepted_args' => $accepted_args );

Bu durumda, içteki $wp_filter[ 'save_post' ] dizi işaretçisini dizinin sonuna taşımak next() çağrılıncaya kadar tetiklenir. Bu döngü tamamlandıktan sonra, daha sonraki bir önceliğe sahip $wp_filter dizisinin en üst düzeyinde bağlı olan gelecekteki eylemler yürütülmez. Bunun nedeni, WordPress'in $wp_filter dizisinin tamamen devre dışı bırakıldığını düşünmesidir.

 do { foreach ( (array) current( $wp_filter[ $tag ] ) as $the_ ) { if ( ! is_null( $the_['function'] ) ) { $args[1] = $value; $value = call_user_func_array( $the_['function'], array_slice( $args, 1, (int) $the_['accepted_args'] ) ); } } } while ( next( $wp_filter[ $tag ] ) !== false ); // <-- moves the array pointer to the end of the array once $wp_filter[$tag] has been looped over

Yukarıda, apply_filters() içindeki eski kodun, geri aramanın iç içe geçme düzeyi hakkında hiçbir bilgiye sahip olmadığını görebilirsiniz.

Bu sorun tartışmalı bir şekilde biraz uç bir durumdur, ancak çekirdek kanca sisteminin çok boyutlu bir diziye bağımlılığının kırılganlığını vurgular.

Çözüm

Ana düzeltme, kanca yöntemleri tetiklendiğinde mevcut yinelemeyi takip etmekti. Yeni WP_Hook sınıfının eti, bu özyineleme sorununun üstesinden gelmek için mevcut yinelemeyi takip ediyor. Ayrıca, $wp_filter global değişkenini bir dizi nesneye çevirerek, add_filter() ve ilgili işlevler artık bağlı işlevleri $callbacks sınıf özelliğinde depolar.

WP_Hook içindeki yeni add_filter() yöntemi:

 public function add_filter( $tag, $function_to_add, $priority, $accepted_args ) { $idx = _wp_filter_build_unique_id( $tag, $function_to_add, $priority ); $priority_existed = isset( $this->callbacks[ $priority ] ); $this->callbacks[ $priority ][ $idx ] = array( 'function' => $function_to_add, 'accepted_args' => $accepted_args ); // if we're adding a new priority to the list, put them back in sorted order if ( ! $priority_existed && count( $this->callbacks ) > 1 ) { ksort( $this->callbacks, SORT_NUMERIC ); } if ( $this->nesting_level > 0 ) { $this->resort_active_iterations( $priority, $priority_existed ); } }

Eski add_filter() işlevi:

 function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) { global $wp_filter, $merged_filters; $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args); unset( $merged_filters[ $tag ] ); return true; }

Yeni $this->resort_active_iterations( $priority, $priority_existed ) için yapılan yeni çağrıya dikkat edin? Bu, bir yineleme sırasında geri arama önceliklerini sıfırlamak için oluşturulmuş yeni bir yöntemdir. Bu yöntem, daha önce belirtilen yineleme önceliği sorununu gideren yöntemin bir parçasıdır. Tüm bu döngüler başınızı mı döndürüyor ?

yo ahbap

Her filtrenin yürütülmesinde de farklılıkları görebilirsiniz. WP_Hook içindeki yeni apply_filters() kodu:

 public function apply_filters( $value, $args ) { if ( ! $this->callbacks ) { return $value; } $nesting_level = $this->nesting_level++; $this->iterations[ $nesting_level ] = array_keys( $this->callbacks ); $num_args = count( $args ); do { $this->current_priority[ $nesting_level ] = $priority = current( $this->iterations[ $nesting_level ] ); foreach ( $this->callbacks[ $priority ] as $the_ ) { if( ! $this->doing_action ) { $args[ 0 ] = $value; } // Avoid the array_slice if possible. if ( $the_['accepted_args'] == 0 ) { $value = call_user_func_array( $the_['function'], array() ); } elseif ( $the_['accepted_args'] >= $num_args ) { $value = call_user_func_array( $the_['function'], $args ); } else { $value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int)$the_['accepted_args'] ) ); } } } while ( false !== next( $this->iterations[ $nesting_level ] ) ); unset( $this->iterations[ $nesting_level ] ); unset( $this->current_priority[ $nesting_level ] ); $this->nesting_level--; return $value; }

wp-includes/plugin.php içindeki eski apply_filters() kodu:

 function apply_filters( $tag, $value ) { global $wp_filter, $merged_filters, $wp_current_filter; ... do { foreach ( (array) current($wp_filter[$tag]) as $the_ ) if ( !is_null($the_['function']) ){ $args[1] = $value; $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } } while ( next($wp_filter[$tag]) !== false ); array_pop( $wp_current_filter ); return $value; }

Gördüğünüz gibi, kodun yeni sürümü, geri aramayı uygularken filtrenin geçerli yinelemesinin yanı sıra filtrenin mevcut durumunu da yönetir. apply_filters() önceki sürümü, o anda yürütülen kancanın iç içe geçme düzeyini, yinelemesini veya önceliğini hesaba katmıyordu.

Geriye Dönük Uyumluluk

Bildiğiniz gibi, WordPress çekirdek geliştirmedeki anahtar kavramlardan biri geriye dönük uyumluluktur. WordPress, eklentilerdeki ve temalardaki eski kodun hala en son sürümle çalıştığından emin olmak için harika bir iş çıkarıyor. Çoğu zaman bu, PHP'nin daha yeni özelliklerinin kullanılamayacağı anlamına gelir ve eski kodla işlerin yürümesini sağlamak için biraz yaratıcı düşünme gerekir.

WP_Hook durumunda, bu, $wp_filter doğrudan dokunan eski kod için 'dizi benzeri' işlevselliğini kullanılabilir tutmak için ArrayAccess ve Iterator arabirimlerinin kullanılması anlamına geliyordu.

Yamanın geçmişine bakıldığında, WP_Hook sınıfının ilk kodunun çoğu PHP 5.2'yi desteklemek için önemli ölçüde yeniden düzenlemeden geçmiştir.

Kabul etseniz de etmeseniz de, WordPress çekirdek geliştiricilerinin geriye dönük uyumluluğu ön planda tuttuğu ve ortamdan bağımsız olarak tüm yeni kodların (özellikle her geliştiriciyi etkileyen kodun) çalıştığından emin olduğu açıktır.

Geliştiriciler için Bu Ne Anlama Geliyor?

make.wordpress.org gönderisinin ana hatlarıyla belirttiği gibi, birçok insan için bu yeni sınıfın kodları üzerinde herhangi bir etkisi olmamalıdır. Yani, add_action() veya add_filter() kullanıyorsanız, hazırsınız demektir. Ana sorun, doğrudan $wp_filter kullanan kod için ortaya çıkar. Kodunuzun uygulanabileceği birkaç durum vardır ve bunlar gönderide özetlenmiştir. Uyumluluk mu-plugin'inde $wp_filter değiştirirken WP Migrate DB Pro eklentisinde küçük bir değişiklik yaptık.

Burada vurgulanması gereken bir diğer önemli nokta, WordPress çekirdek ekibinin kod tabanında büyük değişiklikleri nasıl planladığıdır. Proje için geriye dönük uyumluluğun ne kadar önemli olduğunu gösterir ve eski kodu desteklemek için bazı yaratıcı yaklaşımları gösterir.

WP_Hook sınıfının geliştirilmesi, WordPress çekirdeğine ne kadar büyük kod güncellemelerinin eklendiğini vurguladığı için geliştiricilerin dikkate alması gereken ilginç bir durumdur. Kullanılan yaklaşımlardan bazıları, kendi kodunuzu yeniden düzenlemenize yardımcı olabilir.

Özellikle şimdi, temel geliştirme sürecinin yenilendiği ve WordPress 4.8'de REST API'nin wp-admin'i devraldığı heyecan verici zamanlar!

İşte karşınızda, WordPress çekirdeğindeki kanca sisteminde nelerin değiştiğine dair kısa bir genel bakış. 4.7 ile birlikte gelen (REST API içerik uç noktaları dahil) birçok başka güncelleme vardı ve başka nelerin güncellendiğini görmek için alan kılavuzuna göz atmanızı tavsiye ederim.

Yeni WP_Hook sınıfı hakkında ne düşünüyorsunuz? WordPress sürüm sürecine kendiniz mi katıldınız? Geriye dönük uyumluluk hakkındaki düşünceleriniz nelerdir? Yorumlarda bize bildirin.

Copyright statement: Unless otherwise noted, this article is Collected from the Internet, please keep the source of the article when reprinting.

Check Also

Divi's Theme Builder ile Özel Global Başlık Nasıl Oluşturulur

Artık Tema Oluşturucu burada olduğuna göre, web sitenizi A'dan Z'ye kurmanıza yardımcı olacak yeni eğitimlere dalmak için sabırsızlanıyoruz. Buna Divi'nin yerleşik seçeneğini kullanarak özel başlıklar oluşturma da dahildir. Bu eğitimde Divi's Theme Builder'ı kullanarak global bir başlık oluşturmaya odaklanacağız. Bu sayfaya veya gönderiye farklı bir başlık atamadıysanız, web sitenizin her yerinde genel bir başlık görünecektir.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir