add_action başvuru sınıfı


38

'Add_action' içindeki bir işlev yerine bir sınıfa başvurmak mümkün müdür? Bunu çözmek gibi görünmüyor. İşte söz konusu işlevin basit bir örneği.

add_action( 'admin_init', 'MyClass' );
class MyClass {
     function __construct() {
          .. This is where stuff gets done ..
     }
}

Yani evet, bu işe yaramaz. Ben de denedim:

$var = new MyClass();
add_action( 'admin_init', array( &$var ) );

Ve:

$var = new MyClass();
add_action( 'admin_init', array( &$var, '__construct' ) );

Ve ayrıca:

add_action( 'admin_init', 'MyClass::__construct' );

Yine de, sınıfı yükleyen ayrı bir işlev oluşturmak zorunda kalmadan bunu yapabilir miyim? Sadece sınıf yapıcısını add_action üzerinden çalıştırabilmek istiyorum. Topun yuvarlanabilmesi için yüklenmesi gereken tek şey bu.

Yanıtlar:


69

Hayır, sınıfı doğrudan değil bir kanca ile 'başlatamazsınız' veya başlatamazsınız. Bazı ek kodlar her zaman gereklidir (ve kendiniz için bir solucan kutusu açarken bunu yapabilmek için arzu edilen bir şey değildir.

İşte bunu yapmanın daha iyi bir yolu:

class MyClass {
     function __construct() {
          add_action( 'admin_init',array( $this, 'getStuffDone' ) );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();

Tabii ki, genel durum için daha da basitleştirmek için bir arayüz sınıfı oluşturabiliriz:

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( 'admin_init',array( $this, 'getStuffDone' ) );
    }
    public abstract function getStuffDone();
}

Arabirim olarak, doğrudan bu türde bir nesne oluşturamayacağınızı, ancak şunu söyleyebilmenizi sağlayan bir alt sınıf oluşturabileceğinizi unutmayın:

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();

Hangisi otomatik olarak tüm kancaları ekleyecektir, sadece bir alt sınıfta tam olarak ne yapıldığını tanımlamanız ve onu yaratmanız yeterlidir!

İnşaatçılar Üzerine

Bir yapıcıyı bir kanca işlevi olarak eklemem, kötü bir uygulama ve pek çok olağandışı olaya yol açabilir. Ayrıca çoğu dilde bir yapıcı başlatılmakta olan nesneyi döndürür, böylece kancanız bir filtrede olduğu gibi bir şey döndürmek zorunda kalırsa, istediğiniz gibi süzülmüş değişkeni döndürmez, ancak bunun yerine sınıf nesnesini döndürür.

Yapıcı veya yıkıcı olarak adlandırmak, hangi dilde olursanız olun, asla yapılmamalı , çok, çok, çok kötü bir programlama pratiğidir .

Yapıcılar, fiili çalışmalar için değil, kullanıma hazır hale getirilmeleri için nesneler inşa etmelidir. Nesne tarafından yapılacak iş ayrı bir fonksiyonda olmalıdır.

Statik sınıf yöntemleri ve başlatılması / başlatılması gerekmiyor

Sınıf yönteminiz statik bir sınıf yöntemse, sınıfın adını $thisaşağıda gösterildiği yerine tırnak işaretleri içinde iletebilirsiniz :

class MyClass {
     public static function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
add_action( 'admin_init', array('MyClass','getStuffDone' ) );

Kapanışlar ve PHP 5.3

Ne yazık ki yeni sınıfı oluşturan çizgiden kaçınamazsınız. Bunu atlamanın diğer tek çözümü, hala bu çizgiye sahip olan kazan plakası kodunu içerecek ve PHP 5.3+ gerektiren, örneğin:

add_action('admin_init',function(){
    $var = new MyClass();
    $var->getStuffDone();
});

Hangi noktada sınıfı geçebilir ve sadece bir işlev kullanabilirsiniz:

add_action('admin_init',function(){
    // do stuff
});

Ancak, adsız fonksiyonların hayaletini tanıttığınızı unutmayın. Yukarıdaki eylemi kullanarak kaldırmanın bir yolu yoktur remove_actionve bu, diğer halkların yasalarıyla çalışmak zorunda olan geliştiriciler için büyük acı ve acı yaratır.

Üzerinde Ve İşaretleri

Bunun gibi kullanılan eylemleri görebilirsiniz:

array( &$this, 'getStuffDone' );

Bu kötü . &nesneler referans olarak değil, değerler olarak iletildiğinde PHP 4'te geri eklendi. PHP 4, on yıldan daha eskidir ve WordPress tarafından uzun süredir desteklenmemektedir.

Orada hiçbir sebep kullanmak &thiskancalar ve filtreler ekleyerek ve hiçbir sorunlara neden olacaktır başvuru kaldırma ve hatta PHP gelecekteki sürümlerinde uyumluluğu iyileştirebilir zaman

Bunun yerine bunu kullanın:

array( $this, 'getStuffDone' );

Tamam. Tüm bunlardan teşekkür ederim; gerçekten biraz öğrendim. Şimdi sadece sınıf tabanlı PHP'de rahat edeceğim. Yaptığım şey buydu ve işe yarıyor, ancak herhangi bir şekilde yanlış bir uygulama / yanlış olup olmadığını söyler misiniz? Sınıfı, sınıfın içinde statik bir işlev içinde başlattım. Sonra add_action içindeki statik fonksiyona başvurdu. Bu bağlantıya bakınız: pastebin.com/0idyPwwY
Matthew Ruddy

evet, bu şekilde yapabilirsiniz $class, değişken isminiz olarak kullanmaktan kaçınabildiğim halde , bu kelimeler saklı tutulma eğilimindedir. $x = new Y();Global kapsamdakine benzer bir şey söylemekten kaçınmak için yolunuzun dışına çıkıyorsunuz ve hiçbirinin gerekli olmadığı durumlarda karmaşıklık ekliyorsunuz. Yazılan kod miktarını azaltma girişiminiz daha fazla kod yazmayı içermiştir!
Tom J Nowell

Yukarıdaki durumların hepsine dikkat çekerdim, sınıf yerine bir işlev kullanmak daha iyi olurdu, çünkü o sınıf yine de atılacak ve aynı amaca hizmet edecek. Bu bir kaynak israfı. Unutma, bir nesneyi yaratmanın ve imha etmenin bir bedeli vardır, az sayıda nesne istersiniz ve onların uzun ömürlü olmasını istersiniz
Tom J Nowell

İyi bir nokta. Baktığım gibi değişti. Bunun yerine küresel kodda arayacağım ve fazladan koddan kaçınacağımı düşünüyorum.
Matthew Ruddy

1
Eğer sınıfınızı bir isim alanına koyduysanız, bunu da eklemek zorunda kalacağınızı ya da add_action () / add_filter () 'un bulamayacağına şunu eklemek isterim - böyle:add_action( 'admin_init', array('MyNamespace\MyClass','getStuffDone' ) );
jschrab

10

Örnek sınıf

Notlar:

  • Sadece bir kez sınıfa gir
    • Öncelik 0'ı ara, böylece daha sonra varsayılan önceliğe sahip aynı kancayı kullanabilirsin.
    • ! class_existsİki kez çağırmaktan kaçınmak için bir kutuya sarın ve arayanın içini arayana yerleştirin.
  • Make initfonksiyon ve sınıf Varstatic
  • Sınıfı çağırırken yapıcıyı init içinden çağır new self.

İşte bir örnek

if ( ! class_exists( 'WPSESampleClass' ) )
{
    // Init the class on priority 0 to avoid adding priority inside the class as default = 10
    add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 );

class WPSESampleClass
{
    /**
     * The Class Object
     */
    static private $class = null;

    public static function init()
    {
        if ( null === self::$class ) 
            self :: $class = new self;

        return self :: $class;
    }

    public function __construct()
    {
        // do stuff like add action calls:
        add_action( 'init', array( $this, 'cb_fn_name' ) );
    }

    public function cb_fn_name()
    {
        // do stuff 
    }
} // END Class WPSESampleClass

} // endif;

Php 5+

Lütfen& dışarıda bırak . Biz zaten php4'ün ötesindeyiz. :)


2
if (!class_exists("AllInOneWoo")){
    class AllInOneWoo {
        function __construct(){
            add_action('admin_menu', array($this, 'all_in_one_woo') );
        }
        function all_in_one_woo(){
            $page_title = 'All In One Woo';
            $menu_title = 'All In One Woo';
            $capability = 'manage_options';
            $menu_slug  = 'all-in-one-woo-menu';
            $function   = array($this, 'all_in_one_woo_menu');
            $icon_url   = 'dashicons-media-code';
            $position   = 59;

            add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
        }
        function all_in_one_woo_menu(){?>
            <div class="wrap">
                <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1>
            </div>
        <?php }
    }// end class
}// end if

if (class_exists("AllInOneWoo")){       
    $all_in_one_woo = new AllInOneWoo();
}

Lütfen cevabınızı düzenleyin ve bir açıklama ekleyin: bu neden sorunu çözdü?
fuxia

0

Başlangıçta yüklemenize gerek kalmadan sınıfınızdaki olayları tetikleyebilirsiniz . Tam sınıfı önden yüklemek istemiyorsanız, ancak WordPress filtrelerine ve işlemlerine erişmeniz gerekiyorsa bu kullanışlıdır.

İşte çok basit bir örnek

<?php
class MyClass
{
    public static function init()
    {
        add_filter( 'the_content', array('MyClass', 'myMethod') );
    }

    public static function myMethod($content)
    {
        $content = $content . 'Working without loading the object';
    }
}

MyClass::init();

Bu, Kaiser'in cevabının çok basitleştirilmiş bir versiyonudur, ancak basit terimlerle davranışı gösterir. Bu stile ilk kez bakanlar için kullanışlı olabilir.

Diğer yöntemler gerekirse nesneyi yine de başlatabilir. Eklentimin isteğe bağlı bölümlerinin komut dosyalarını kodlamasını sağlamak için kişisel olarak kullanıyorum, ancak yalnızca bir AJAX isteğinde nesneyi tetikliyorum.


0

Bu benim için çalışıyor:

class foo
{
    public static function bar()
    {
        echo 'it works!';
    }
}

add_action('foo_bar', array('foo', 'bar'));

0

Genel olarak konuşursak, bir kancaya bütün bir sınıfı eklemezsiniz . add_action()/ add_filter()Kanca geri arama bekliyoruz fonksiyonları , olabilir başvurulan bir sınıf içinde .

Diyelim ki init()sınıfınızda, WordPress initkancasına bağlanmak istediğiniz bir işleviniz var .

Senin koyun add_action()çağrı içine şöyle geri arama tanımlamak ardından sınıfı ve:

add_action( 'init', array( $this, 'init' ) );

(Not: Sınıfınızın düzgün bir şekilde isimlendirildiğini farz ediyorum; aksi halde geri çağırma işlevlerinizi adlandırdığınızdan emin olun.)


Peki ya mevcut sınıf henüz başlatılmamışsa? Gerçekten başlatmak için add_action kullanmaya çalışıyordum, bu yüzden $ var = new MyClass (); önceden başka yerde.
Matthew Ruddy

Sadece sınıfınızı başlatmak için init(veya ihtiyaç duyduğunuz her yerde) bir geri arama yazmak mümkün değil mi?
Chip Bennett

0

Başlatılan nesne yerine sınıf adını ileterek bunu yapabilmeniz gerekir:

add_action( 'init', array( 'MyClass', '__construct' ) );

(Teoride, diğer çözümünüz de işe yaramalı

$var = new MyClass();
add_action( 'admin_init', array( $var, '__construct' ) );

Kafanın neden olmadığından emin değilim. Belki referans ile aramazsanız?)


Birincisi çalışmıyor. Sadece sayfanın boş kalmasını sağlar. İkinci işler, ancak sınıfın ilk satırda başlatılmasından dolayı. Sınıf zaten başlatılmış olduğundan, bu eylemi ekleme amacını geçersiz kılar. Ama yapmaya çalıştığım şeyi yapmıyor, bu da dersi eylem yoluyla başlatıyor. Üzerinde çalışmakta olduğum fiili kodda, eylem 'admin_init' değil, başka bir sınıf içinde özel bir işlemdir. Diğer sınıftaki eylem orada değilse, 'Sınıfım' işlevinin başlatılmasını istemiyorum. Bir şey kaçırdığımda üzgünüm; gittiğim gibi öğrenme
Matthew Ruddy

Evet yanılmışım. Bu sadece statik bir inityöntem çağırıyorsanız işe yarar . Bkz wordpress.stackexchange.com/a/48093/14052
Boone Gorges
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.