WP eklentisinde bir sınıfı başlatmak için en iyi yol?


89

Bir eklenti oluşturdum ve tabii ki ben olmakla birlikte, güzel bir OO yaklaşımı ile gitmek istedim. Şimdi yapmakta olduğum şey bu sınıfı yaratmak ve hemen altında da bu sınıfın bir örneğini oluşturmak:

class ClassName {

    public function __construct(){

    }
}

$class_instance = new ClassName();  

Bu sınıfın başlatılması için daha fazla WP yolu olduğunu farz ediyorum ve daha sonra bir init()taneden daha çok bir işlevi tercih ettiklerini söyleyerek insanlarla karşılaştım __construct(). Benzer şekilde, birkaç kişiyi aşağıdaki kancayı kullanarak buldum:

class ClassName {

    public function init(){

    }
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );

Genel olarak yük altında bir WP sınıfı örneği oluşturmanın ve bunu küresel olarak erişilebilir bir değişken olarak görmenin en iyi yolu olarak kabul edilen nedir?

NOT: İlginç bir yan nokta register_activation_hook()olarak, içinden __constructçağrılabilirken init(), ikinci örneği kullanarak aranamayacağını fark ettim . Belki birileri beni bu konuda aydınlatabilir.

Düzenleme: Tüm cevaplar için teşekkürler, sınıfın kendi içinde başlatmanın nasıl yapılacağına dair oldukça tartışmalı bir konu var, ancak genel olarak bunu başlatmak add_action( 'plugins_loaded', ...);için en iyi yol olan oldukça iyi bir fikir birliği olduğunu düşünüyorum ...

Düzenleme: Meseleleri karıştırmak için, bunun da kullanıldığını gördüm (bu yöntemi kendim kullanmamama rağmen, iyi bir OO sınıfını bir işleve dönüştürmek, onun amacını bozmuş gibi görünüyor):

// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
    global $class_name;
    $class_name = new ClassName();
}

1
Son düzenlemeyle ilgili olarak, eğer sınıfla aynı eklenti dosyasında bulunuyorsa, bu biraz işe yaramaz hale gelir. Sınıfı, tarif ettiğim yönteme göre başlatabilirsiniz. Ayrı bir dosyada olsa bile, hala biraz anlamsız. Görebildiğim tek kullanım, eklenti dosyalarınızın dışında, temaların içinde vb. Bir sınıfı başlatmanıza olanak sağlayan bir sarmalayıcı işlevi oluşturmak isteyip istemediğinizdir. Öyle olsa bile, hangi mantığın arkasında durduğunu sormam gerekiyor, çünkü koşulların ve kancaların doğru kullanımı, bunun yerine eklentiyi kullanmaya odaklanmanıza olanak tanıyan somutlaştırma üzerinde ince tanecik kontrolüne izin vermelidir.
Adam

Buna katılıyorum ama birkaç WP eklentisinde bulduğumda kullanmaya değeceğini düşündüm.
kalpaitch

Yanıtlar:


60

Güzel soru, birkaç yaklaşım var ve bu ne elde etmek istediğinize bağlı.

Sık sık yaparım;

add_action( 'plugins_loaded', array( 'someClassy', 'init' ));

class someClassy {

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
           //construct what you see fit here...
    }

    //etc...
}

WPSE üyesi toscho'nun bu özünde , sohbet odasındaki bu konuyla ilgili bazı son tartışmaların sonucu olarak ortaya çıkan daha derin bir örnek görülebilir .

Boş yapıcı yaklaşımı.

Boş inşaatçı yaklaşımını bütünüyle örnekleyen yukarıdaki boşluktan alınan avantajların / dezavantajların bir kısmı.

  • Avantajları:

    • Ünite testleri, herhangi bir kancayı otomatik olarak etkinleştirmeden yeni örnekler oluşturabilir. Singleton yok.

    • Global değişken gerekli değil.

    • Eklenti örneği ile çalışmak isteyen herkes T5_Plugin_Class_Demo :: get_instance () yöntemini çağırabilir.

    • Devre dışı bırakmak kolaydır.

    • Hala gerçek OOP: çalışma yöntemleri statik değildir.

  • dezavantajı:

    • Belki de okumak daha zor?

Bence dezavantajı zayıf olanı, bu yüzden tercih ettiğim yaklaşım bu olsa gerek, benim kullandığım tek şey değil. Aslında, birkaç diğer ağır ağırlık, kısa sürede konuyla ilgilenmeleri konusunda bu konuda şüphe duymayacaktır, çünkü bu konuyu çevreleyen, seslendirilmesi gereken bazı iyi fikirler vardır.


not: toscho'dan , her birinin lehte ve aleyhlerinde bakılan bir sınıfın nasıl başlatılacağına ilişkin bir sınıfın nasıl başlatılacağına dair 3 veya 4 karşılaştırmaya dayanan gist örneğini bulmam gerekiyor; diğer örnekler bu konuyla iyi bir kontrast sağlar. Umarım toscho hala bu dosyada vardır.

Not: WPSE Cevap ilgili örnekler ve karşılaştırmalar ile bu konuya. Ayrıca en iyi çözüm örneğin WordPress'te bir sınıf.

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
class My_Plugin {

    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance() {

        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo() {

        return $this->var; // never echo or print in a shortcode!
    }
}

add_action ('plugins_loaded', ...) arasındaki fark ne olurdu? ve add_action ('load-plugins.php', ...);
Aldığım

1
Anladığım kadarıyla load-plugins.php, çalışmasına rağmen, çekirdek update.phpdosyayla ilişkili ve başlatma sırasında ortaya çıkan olayların sıralamasıyla ilgili olarak güvenilmesi gereken varsayılan varsayılan işlemlerin bir parçası değil ve bu nedenle tercih ediyorum Bu durumda geçerli olan kancaları kullanmak plugins_loaded. Bu, Action Reference olduğunda olanların hızlı bir anlık görüntüsü olarak adlandırdığım şeydir . Açıklamam bütünüyle tamamlanmadı.
Adam

4
Bu singleton benzeri yaklaşımı seviyorum. Ancak, başlangıç ​​eylem kancanız olarak plugins_loaded öğesini sorguluyorum. Bu kanca tüm eklentiler yüklendikten sonra çalıştırılmak içindir . Ardından kancayı asarak, o kancayı bir tür ele geçiriyorsunuz ve plugins_loaded'a bağlanan diğer eklentilerle veya temalarla ilgili çatışmalar veya başlangıç ​​sırası sorunları ile eğlenebilirsiniz. Başlatma yönteminizi çalıştırmak için hiçbir eylemde bulunmam. Eklenti mimarisi, bir eylemde değil satır içi çalışmak üzere tasarlanmıştır.
Tom Auger

2
Kullanırsanız register_activation_hook(), plugins_loadedeylem tetiklenmeden önce bu işlevi çağırmanız gerektiğini unutmayın .
Geert

1
Ek bilgi olarak, bu yazıya @mikeschinkel ve yorumlardaki tartışmalara bakın. hardcorewp.com/2012/…
bueltge

78

Özgün soru sorulduktan tam olarak 2 yıl sonra buraya gelindiğinde, belirtmek istediğim birkaç şey var . (Benden bir çok şeyi işaret etmemi istemeyin ).

Uygun kanca

Bir eklenti sınıfını başlatmak için uygun kanca kullanılmalıdır. Bunun için genel bir kural yoktur, çünkü sınıfın ne yaptığına bağlıdır.

Çok erken bir kancanın kullanılması "plugins_loaded"çoğu zaman anlamsızdır, çünkü böyle bir kanca admin, frontend ve AJAX'ın talepleri için ateşlenir, ancak çoğu zaman, daha sonraki bir kanca çok daha iyidir, çünkü sadece gerektiğinde eklenti sınıflarını başlatmayı sağlar.

Örneğin, şablonlar için bir şeyler yapan bir sınıftan başlatılabilir "template_redirect".

Genel olarak konuşursak, bir sınıfın "wp_loaded"ateşlenmeden önce başlatılması gerektiğine çok nadir rastlanır .

Tanrı Sınıfı Yok

Eski cevaplarda örnek olarak kullanılan tüm sınıfların çoğu, "Prefix_Example_Plugin"ya da "My_Plugin"... adında bir sınıf kullanır . Bu, muhtemelen eklenti için bir ana sınıf olduğunu gösterir .

Peki, bir eklenti tek bir sınıf tarafından yapılmadıkça (bu durumda eklenti adından sonra isimlendirmek kesinlikle mantıklı), bütün eklentiyi yöneten bir sınıf oluşturmak için (örneğin, bir eklentinin ihtiyaç duyduğu tüm kancaları eklemek veya diğer tüm eklenti sınıflarını başlatmak) ) bir tanrı nesnesine örnek olarak kötü bir uygulama olarak kabul edilebilir .

Nesneye yönelik programlama kodunda , "S" nin "Tek sorumluluk ilkesi" anlamına geldiği yerde, SOLID olma eğiliminde olmalıdır .

Her sınıfın tek bir şey yapması gerektiği anlamına gelir. WordPress eklenti geliştirmesinde, geliştiricilerin bir ana eklenti sınıfını başlatmak için tek bir kanca kullanmaktan kaçınmaları gerektiği , ancak sınıf sorumluluğuna göre farklı sınıfları başlatmak için farklı kancalar kullanılması gerektiği anlamına gelir.

Yapıcıdaki kancalardan kaçının

Bu argüman burada diğer cevaplarda da açıklanmıştır, ancak bu kavramı vurgulamak ve bu diğer cevabı , ünite testi amacıyla oldukça geniş bir şekilde açıklandığı yere bağlamak istiyorum .

Neredeyse 2015: PHP 5.2 zombiler içindir

14 Ağustos 2014'ten beri PHP 5.3 kullanım ömrü sona erdi . Kesinlikle öldü. PHP 5.4 tüm 2015 için desteklenecek, yazdığım şu anda bir yıl daha demek oluyor.

Ancak, WordPress hala PHP 5.2'yi desteklemektedir, ancak hiç kimse, özellikle de OOP ise, o sürümü destekleyen tek bir kod satırı yazmamalıdır.

Farklı sebepler var:

  • PHP 5.2 uzun zaman önce ölmüş, bunun için hiçbir güvenlik düzeltmesi yapılmamıştır, bu güvenli olmadığı anlamına gelir.
  • PHP 5.3, PHP'ye birçok özellik ekledi, adsız işlevler ve ad alanları über alles
  • PHP'nin yeni sürümleri çok daha hızlı . PHP ücretsizdir. Güncellemek ücretsizdir. Neden daha hızlı, daha güvenli bir sürümünü ücretsiz olarak kullanabiliyorsanız, neden daha yavaş ve güvensiz bir sürüm kullanıyorsunuz?

PHP 5.4+ kodunu kullanmak istemiyorsanız, en az 5.3+ kullanın

Örnek

Bu noktada, şu ana kadar söylediklerime dayanarak eski cevapları gözden geçirme zamanı.

Artık 5.2 ile ilgilenmek zorunda değilsek, isim alanları kullanabiliriz ve kullanmalıyız.

Daha iyi açıklamak tek bir sorumluluk ilkesinin aşkına, örnek 3 sınıfları, does birini kullanacak şey önyüzü üzerinde, arka uçta bir tane ve her iki durumda da kullanılan üçüncü.

Yönetici sınıfı:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Ön sınıf:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Araçlar arayüzü:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

Ve diğer ikisi tarafından kullanılan bir Araçlar sınıfı:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

Bu dersleri alarak uygun kancalar kullanarak onları başlatabilirim. Gibi bir şey:

require_once plugin_dir_path( __FILE__ ) . 'src/ToolsInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'src/Tools.php';

add_action( 'admin_init', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/AdminStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $admin_stuff; // this is not ideal, reason is explained below
   $admin_stuff = new GM\WPSE\Example\AdminStuff( $tools ); 
} );

add_action( 'template_redirect', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/FrontStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $front_stuff; // this is not ideal, reason is explained below
   $front_stuff = new GM\WPSE\Example\FrontStuff( $tools );    
} );

Bağımlılık İnversiyonu ve Bağımlılık Enjeksiyonu

Yukarıdaki örnekte, yukarıda belirtilenleri uygulayarak farklı kancalarda farklı sınıfları başlatmak için ad alanları ve adsız işlevler kullandım.

Ad alanlarının herhangi bir önek olmadan adlandırılmış sınıflar oluşturmasına nasıl izin verdiğine dikkat edin.

Yukarıda dolaylı olarak belirtilen başka bir konsept uyguladım: Bağımlılık Enjeksiyonu , Bağımlılık İnversiyon Prensibi olan “D” olan SOLID kısaltmasında uygulamak için bir yöntem .

ToolsOnlar örneklenen zaman sınıf bu yolla o sorumluluğu ayırmak mümkündür, böylece diğer iki sınıfta "enjekte" dır.

Ek olarak AdminStuffve FrontStuffsınıflar , uygulayan bir sınıfa ihtiyaç duyduklarını bildirmek için tür ipucunu kullanır ToolsInterface.

Bu şekilde kodumuzu kullanan kendimiz veya kullanıcılarımız aynı arabirimin farklı uygulamalarını kullanabilir, kodumuzu somut bir sınıfa değil bir soyutlamaya bağlarlar: tam olarak Bağımlılık İnversiyon Prensibi'nin konusu budur.

Bununla birlikte, yukarıdaki örnek daha da iyileştirilebilir. Bakalım nasıl.

Otomatik Yükleyici

Daha iyi okunabilir cepten kod yazmak için iyi bir yol değildir karıştırmak diğer koduyla türleri (Arayüzler, Sınıflar) tanımını ve kendi dosyasındaki her tür koymak.

Bu kural aynı zamanda PSR-1 kodlama standartlarından biridir 1 .

Bununla birlikte, bunu yaparken, bir sınıfı kullanmadan önce onu içeren dosyayı zorunlu kılmak gerekir.

Bu çok zor olabilir, ancak PHP , gerektiğinde sınıfı otomatik olarak yüklemek için kendi adına göre bir dosyayı yükleyen bir geri çağırma kullanarak yardımcı işlevler sağlar .

Ad alanlarını kullanmak çok kolaydır, çünkü şimdi klasör yapısını ad alanı yapısıyla eşleştirmek mümkündür.

Bu sadece mümkün değil, aynı zamanda başka bir PSR standardıdır (veya daha iyi 2: PSR-0 şimdi kullanımdan kaldırılmış ve PSR-4 ).

Bu standartlara uyarak, özel bir otomatik yükleyiciyi kodlamak zorunda kalmadan, otomatik yükü işleyen farklı araçlardan yararlanmak mümkündür.

WordPress kodlama standartlarının dosyaları adlandırmak için farklı kuralları olduğunu söylemeliyim .

Yani WordPress çekirdek için kod yazarken, geliştiriciler WP kurallarına uymak zorunda, ama özel kod yazarken bir geliştirici bir seçimdir, ama PSR standart kullanılarak zaten yazılı araçları kullanmak daha kolaydır 2 .

Global Erişim, Kayıt ve Servis Belirleme Kalıpları.

WordPress'te eklenti sınıflarını başlatırken en büyük sorunlardan biri, kodun çeşitli bölümlerinden bunlara nasıl erişileceğidir.

WordPress'in kendisi global yaklaşımı kullanır : değişkenler global kapsamda saklanır ve bu da her yerde erişilebilir olmasını sağlar. Her WP geliştiricisi sözcüğü globalkariyerine binlerce kez yazar.

Bu aynı zamanda yukarıdaki örnek için kullandığım yaklaşım, ama kötülük .

Bu cevap zaten nedenini daha fazla açıklamama izin vermek için çok uzun, ancak SERP'teki "küresel değişkenler kötülük" için ilk sonuçları okumak iyi bir başlangıç ​​noktası.

Ancak küresel değişkenlerden kaçınmak nasıl mümkün olabilir?

Farklı yollar var.

Buradaki eski cevapların bazıları statik örnek yaklaşımını kullanır .

public static function instance() {

  if ( is_null( self::$instance ) ) {
    self::$instance = new self;
  }

  return self::$instance;
}

Kolay ve oldukça iyi, ancak erişmek istediğimiz her sınıf için modeli uygulamaya zorluyor.

Üstelik, çoğu zaman bu yaklaşım tanrı sınıfı meselesine girmenin yolunu ortaya koyar, çünkü geliştiriciler bu yöntemi kullanarak bir ana sınıfa erişilebilir hale getirir ve ardından diğer tüm derslere erişmek için onu kullanır.

Bir tanrı sınıfının ne kadar kötü olduğunu zaten açıkladım, bu yüzden statik örnek yaklaşımı bir eklentinin yalnızca bir veya iki sınıfı erişilebilir hale getirmesi gerektiğinde gitmek için iyi bir yoldur.

Bu, sadece birkaç sınıfa sahip eklentiler için kullanılabileceği anlamına gelmez, aslında, bağımlılık enjeksiyon prensibi düzgün kullanıldığında, küresel olarak erişilebilir bir sayıya ihtiyaç duymadan, oldukça karmaşık uygulamalar oluşturmak mümkündür. Nesnelerin

Bununla birlikte, bazen eklentilerin bazı sınıfları erişilebilir kılmaları gerekir ve bu durumda statik örnek yaklaşımı ezicidir.

Bir başka olası yaklaşım kayıt düzenini kullanmaktır .

Bu onun çok basit bir uygulamasıdır:

namespace GM\WPSE\Example;

class Registry {

   private $storage = array();

   function add( $id, $class ) {
     $this->storage[$id] = $class;
   }

   function get( $id ) {
      return array_key_exists( $id, $this->storage ) ? $this->storage[$id] : NULL;
   }

}

Bu sınıfı kullanarak, nesneleri bir kayıt defteri nesnesinde bir kimliğiyle depolamak mümkündür, böylece bir kayıt defterine erişebilmek, tüm nesnelere erişebilmek mümkündür. Elbette bir nesne ilk defa yaratıldığında, kayıt defterine eklenmesi gerekir.

Örnek:

global $registry;

if ( is_null( $registry->get( 'tools' ) ) ) {
  $tools = new GM\WPSE\Example\Tools;
  $registry->add( 'tools', $tools );
}

if ( is_null( $registry->get( 'front' ) ) ) {
  $front_stuff = new GM\WPSE\Example\FrontStuff( $registry->get( 'tools' ) );    
  $registry->add( 'front', front_stuff );
}

add_action( 'wp', array( $registry->get( 'front' ), 'wp' ) );

Yukarıdaki örnek, kullanışlı olmanın kayıt defterinin küresel olarak erişilebilir olması gerektiğini açıkça ortaya koymaktadır. Tek kayıt defteri için genel bir değişken çok kötü değildir , ancak genel olmayan saflaştırıcılar için bir kayıt defteri için statik örnek yaklaşımını veya belki de statik değişkenli bir işlevi uygulamak mümkündür:

function gm_wpse_example_registry() {
  static $registry = NULL;
  if ( is_null( $registry ) ) {
    $registry = new GM\WPSE\Example\Registry;
  }
  return $registry;
}

Fonksiyon ilk çağrıldığında kayıt defterini başlatır, daha sonraki çağrılar için onu döndürür.

Bir sınıfı genel olarak erişilebilir kılmak için başka bir WordPress'e özgü yöntem, bir nesne örneğini bir filtreden döndürmektir. Bunun gibi bir şey:

$registry = new GM\WPSE\Example\Registry;

add_filter( 'gm_wpse_example_registry', function() use( $registry ) {
  return $registry;
} );

Bundan sonra her yerde kayıt defteri gereklidir:

$registry = apply_filters( 'gm_wpse_example_registry', NULL );

Kullanılabilecek bir başka model, servis bulma modelidir . Kayıt düzenine benzer, ancak hizmet konumlayıcılar bağımlılık enjeksiyonunu kullanarak çeşitli sınıflara geçirilir.

Bu kalıpla ilgili ana sorun, kodun korunmasını ve okunmasını zorlaştıran sınıf bağımlılıklarının gizlenmesidir.

DI Konteynerler

Kayıt veya servis bulucuyu global olarak erişilebilir kılmak için kullanılan yöntem ne olursa olsun, nesnelerin orada depolanması gerekir ve saklanmadan önce bunların başlatılması gerekir.

Oldukça fazla sınıfın olduğu ve çoğunun birkaç bağımlılığı olduğu karmaşık uygulamalarda, sınıflandırma yapmak için çok fazla kod gerekir, bu nedenle hata olasılığı artar: Var olmayan kodda hata olmaz.

Son yıllarda, PHP geliştiricilerinin nesnelerin örneklerini kolayca başlatmasına ve saklamasına , bağımlılıklarını otomatik olarak çözmesine yardımcı olan bazı PHP kütüphaneleri ortaya çıktı .

Bu kütüphaneler Bağımlılık Enjeksiyon Konteynerleri olarak bilinir, çünkü bağımlılıkları çözen sınıfları somutlaştırabilirler ve ayrıca bir kayıt defteri nesnesine benzer şekilde hareket ederek nesneleri depolayabilir ve gerektiğinde geri getirebilirler.

Genellikle, DI kapları kullanırken, geliştiriciler uygulamanın her sınıfı için bağımlılıkları ayarlamak zorunda kalırlar ve daha sonra kodda bir sınıfa ilk defa ihtiyaç duyulduklarında uygun bağımlılıklar ile başlatılırlar ve aynı örnek sonraki taleplerde tekrar tekrar geri gönderilir. .

Bazı DI kapları ayrıca bağımlılıkları konfigürasyon olmadan otomatik olarak keşfedebilirler ancak PHP yansıması kullanırlar .

Bazı iyi bilinen DI Konteynerleri:

Ve bircok digerleri.

Sadece birkaç sınıf ve sınıf içeren basit eklentiler için pek fazla bağımlılığın bulunmadığını, DI kapsayıcılarını kullanmaya değmeyeceğini belirtmek istiyorum: statik örnek yöntemi veya genel erişilebilir bir kayıt defteri iyi çözümlerdir, ancak karmaşık eklentiler için bir DI konteynerinin yararı belirginleşir.

Tabii ki, DI konteyner nesnelerinin bile uygulamada kullanılmak için erişilebilir olması gerekir ve bu amaçla yukarıda görülen yöntemlerden birini, genel değişken, statik örnek değişkeni, nesneyi filtre yoluyla geri döndürmek vb. Kullanmak mümkündür.

Besteci

DI konteynerini kullanmak genellikle üçüncü taraf kodunu kullanmak anlamına gelir. Günümüzde PHP'de harici bir lib kullanmamız gerektiğinde (sadece DI konteynerlerini değil, uygulamanın parçası olmayan herhangi bir kodu), basitçe indirerek ve uygulama klasörümüze koymak iyi bir uygulama olarak kabul edilmez. Başka bir kod parçasının yazarı olsak bile.

Bir uygulama kodunun dış bağımlılıklardan ayrılması, daha iyi bir organizasyonun, daha iyi güvenilirliğin ve kodun daha iyi akıl sağlığının işaretidir .

Besteci , PHP bağımlılığını yönetmek için PHP topluluğunda fiili bir standarttır. WP topluluğunda da ana akım olmaktan çok uzak , her PHP ve WordPress geliştiricisinin kullanmıyorsa en azından bilmesi gereken bir araçtır.

Bu cevap daha fazla tartışmaya izin vermek için zaten kitap boyutundadır ve ayrıca Composer'ı burada tartışmak muhtemelen konu dışıdır, sadece tamamlanma adına söz edilmiştir.

Daha fazla bilgi için Besteci sitesini ziyaret edin ve ayrıca @Rarst tarafından önerilen bu minisite bir okumaya değer .


1 PSR, PHP Framework Birlikte Çalışma Grubu tarafından yayımlanan PHP standart kurallarıdır.

2 Besteci (bu cevapta bahsedilecek bir kütüphane) diğer şeylerin yanı sıra bir otomatik yükleyici yardımcı programı da içerir.


1
Ek bir not, PHP 5.3'ün de ömrünün sonu olduğunu. Sorumlu bir ana bilgisayar, varsayılan değilse en az 5,4 seçenek olarak sunar
Tom J Nowell

2
"14 Ağustos 2014'ten beri PHP 5.3 kullanım ömrü sona erdi. Kesinlikle öldü." "PHP 5.2 zombiler içindir" altındaki ilk satır mı @TomJNowell
gmazzap

3
Sadece merak ediyorum, "birçok şeyi" neye benzetmek istersiniz? ;-)
MikeSchinkel

Global değişkenlerden kaçınmaya çabalarken, işlevsellik ve statik değişkenli Kayıt defteri modeli fikrini seviyorum. Fonksiyon ilk çağrıldığında kayıt defterini başlatır, sonraki çağrılarda onu döndürür.
Michael Ecklund

10

Aşağıdaki yapıyı kullanıyorum:

Prefix_Example_Plugin::on_load();

/**
 * Example of initial class-based plugin load.
 */
class Prefix_Example_Plugin {

    /**
     * Hooks init (nothing else) and calls things that need to run right away.
     */
    static function on_load() {

        // if needed kill switch goes here (if disable constant defined then return)

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    /**
     * Further hooks setup, loading files, etc.
     *
     * Note that for hooked methods name equals hook (when possible).
     */
    static function init(  ) {


    }
}

Notlar:

  • hemen çalışması gereken şeyler için yer tanımladı
  • tweaks için devre dışı bırakma / geçersiz kılma kolaydır (bir inityöntemden kurtulun )
  • Eklenti sınıfının hiç kullanılmadığını / ihtiyaç duyduğumu sanmıyorum - takip etmeyi gerektirir, vb; Bu gerçekten OOP değil, amaç olarak sahte ad alanıdır (çoğu zaman)

Feragat Birim testlerini henüz kullanmıyorum ( plaka üzerinde pek çok şey var ) ve statiklerin kendileri için daha az tercih edilebileceğini duyuyorum. Bunu test etmek için birime ihtiyacınız varsa, bununla ilgili araştırma yapın.


3
Birim testinde büyük olan kişilerin statik / singleton çözümlerinden hoşlanmadıklarını biliyorum. Bence statik kullanarak neyi başarmaya çalıştığınızı tam olarak anlıyorsanız ve en azından bunu yapmanın etkilerinin farkındaysanız, o zaman bu tür yöntemleri uygulamak için gayet iyi. Stack Overflow'ta
Adam

Bu beni gerçekten düşündürdü. Öyleyse neden bir Sınıf kullanıyorsunuz ve sadece basit ön ekli fonksiyonlara geri dönmüyorsunuz. Bunu sadece temizleyici işlev / yöntem adlarına sahip olmak için mi yapıyoruz? Demek istediğim, onları "statik" bir yuva ile iç içe geçirme b4 onları daha fazla okunabilir mi? Ad çatışması yapma şansı, propper önekleri kullanıyorsanız veya bir şeyleri özlüyorsam, tek bir sınıf adıyla aynıdır.
James Mitch,

1
@JamesMitch evet, tamamen statik yöntemler çoğunlukla WP'de kullanıldığı gibi sadece sahte ad alanıyla işlev görür. Bununla birlikte, sınıflar, bu durumda bile, otomatik yükleme ve kalıtım gibi saf fonksiyonlara göre bazı avantajlara sahiptir. Son zamanlarda, bağımlılık enjeksiyon kabı tarafından düzenlenen statik yöntemlerden ve gerçek somutlaştırılmış nesnelere doğru ilerliyorum.
Rarst,

3

Her şey işlevselliğe bağlıdır.

Bir zamanlar yapıcı çağrıldığında senaryoları kaydeden bir eklenti yaptım, bu yüzden onu kancaya bağlamak zorunda kaldım wp_enqueue_scripts.

functions.phpDosyanız yüklendiğinde onu çağırmak $class_instance = new ClassName();istiyorsanız, belirttiğiniz bir örnek oluşturabilirsiniz .

Hız ve hafıza kullanımını göz önünde bulundurmak isteyebilirsiniz. Farkında değilim, ancak bazı durumlarda çağrılmayan kancalar olduğunu hayal edebiliyorum. Örneğini bu kancada oluşturarak, bazı sunucu kaynaklarını koruyabilirsiniz.


Bunun için teşekkürler, sanırım yukarıdaki soruda iki nokta var. Diğeri __construct'ın uygun olup olmadığı veya init () 'in sınıfı başlatmanın daha iyi bir yolu olup olmadığı.
kalpaitch

1
Statik bir init()metoda gidiyorum, bu yüzden sınıf örneğini var olan değişkenlerin üzerine yazabileceğiniz başka bir kapsam yerine sınıfın kapsamı olarak adlandırıyordum.
Tim S.

0

Bunun birkaç yaşında olduğunu biliyorum, ancak bu arada php 5.3 adsız yöntemleri destekliyor , bu yüzden şunu buldum:

add_action( 'plugins_loaded', function() { new My_Plugin(); } );

ve bir şekilde en çok hoşuma gitti. Düzenli yapıcılar kullanabilirim ve OOP yapılarını bozan herhangi bir "init" veya "on_load" yöntemi tanımlamam gerekmiyor.

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.