Global değişkenler nasıl ayarlanır ve kullanılır? Ya da neden onları hiç kullanmamaya


27

GÜNCELLEME: Asıl sorum çözüldü, ancak bu neden küresel değişkenleri kullanmama konusunda geçerli bir tartışmaya dönüşüyor, bu yüzden soruyu güncellemek için güncelleme yapıyorum. Çözüm <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>@ TomJNowell'in önerdiği gibi oldu .

GÜNCELLEME 2: Şimdi tam olarak istediğim şeyi yapıyor. Ama hala küresel kapsamı kullanıyorum ve daha iyi bir yol bulmaktan mutluluk duyacağım.

Permalinklerin temalarımın çeşitli yerlerinde kullanılacak kategoriler için bir sürü küresel değişken oluşturmaya çalışıyorum. Bunun ana nedeni, hem ana navigasyonda hem de mevcut gönderinin hangi kategorideki olduğuna göre seçilen bir dizi alt navigasyonda kullanım içindir. Bu, başkaları tarafından kullanmak üzere bırakacağım bir tema değil . ama çok özel bir amaç için üretildi.

Bu, şu anda onları nasıl oluşturduğumla ilgili (değişkenlerin sadece birkaçını yapıştırdım).

function set_global_nav_var()
{
    //proposal
    global $prop;
    // Get the ID of a given category
    $category_id_prop = get_cat_ID( 'proposal' );
    // Get the URL of this category
    $category_link_prop = get_category_link( $category_id_prop );
    $prop = '<a href="' .esc_url( $category_link_prop ). '" title="Proposal">Proposal</a>';

    //Calvinball
    global $cb;
    // Get the ID of a given category
    $category_id_cb = get_cat_ID( 'calvinball' );
    // Get the URL of this category
    $category_link_cb = get_category_link( $category_id_cb );
    $cb = '<a href="' .esc_url( $category_link_cb). '" title="Calvinball">Calvinball</a>';
}
add_action( 'init', 'set_global_nav_var' );

Şimdi <?php global $prop; echo $prop; ?>gidip kodun bütün linkini geri alan 4 yer bulabilirim. Bu değiştiğinde, sadece bir yerde değiştirmem gerekiyor. Global kapsamı içermeyen alternatiflere açığım.


1
Bu ifade hangi bağlantıyı yapar echo esc_url ($ category_link_prop); görüntüler? Beklediğiniz bağlantı nedir?
Vinod Dalvi

1
Neden genel değişkeni kullanmayı planladığınız sadece 'get_cat_ID (****)' yi kullanmıyorsunuz? Yaptığınız şekilde herhangi bir hız avantajı olacağından şüpheliyim. Okunabilirlik açısından 'get_cat_ID (****)' elleri kazanır.
Chris Strutton

1
Tekrar cevap verir misin? Sorunuzu okudum ve hala ne yapmak istediğinizden ve neden yapmak istediğinizden emin değilim. Genel tavsiyem küresel değişkenleri kullanmamak ve küresel kapsamı kirletmemek olacaktı
Tom J Nowell

1
bu biraz X / Y Sorunu gibi geliyor . Belki de istediğiniz sonucun ne olduğunu tam olarak açıklamalısınız. Eminim başka yerlerde bir denizcilikte onlara sadece sabit kod referansları koymak için çok sayıda küresel değişken ayarlamaktan çok daha zarif bir çözüm vardır
Milo

2
Menünüze aktardığınız içeriğe göre çıkan bir fonksiyon yaratın, böylece tüm menü mantığını ve ilişkili vars'leri tek bir yerde kapatabilirsiniz.
Milo

Yanıtlar:


21

Buna şiddetle karşı tavsiyede bulunmama rağmen işleri hızlandırmaz, kullanımınız yanlış.

Genel kullanmaya çalıştığınızda, önce genel anahtar sözcüğü belirtmelisiniz. Değeri tanımlarken burada belirtmiştiniz, ancak bu kapsamın dışında global bir kapsam değişkeni olarak yeniden belirtilmesi gerekiyor.

örneğin, fonksiyonlar.php:

function test() {
    global $hello;
    $hello = 'hello world';
}
add_action( 'after_theme_setup', 'test' );

Single.php'de bu işe yaramaz:

echo $hello;

Çünkü $ merhaba tanımsızdır. Ancak bu işe yarayacak:

global $hello;
echo $hello;

Tabii ki ikisini de yapmamalısın. WordPress zaten bu şeyleri nesne önbelleğinde önbelleğe almaya çalışır. Bunu yapmaktan hız artışı görmeyeceksiniz (ufak bir hız azalması görebilirsiniz), elde edeceğiniz tek şey ek bir karmaşıklık ve gerekli olmayan bir çok küresel bildirimde bulunma gereğidir.

Nesneler veya bağımlılık enjeksiyonu gibi yapısal verileri veya sizin durumunuzda bir dizi işlevi kullanmaktan daha iyi olursunuz.

Örneğin, burada statik değişkenlerle benzer bir şey yapmanın bir yolu var (aynı nedenlerle hala kötü, ama sadece biraz daha az ve yazması daha kolay);

function awful_function( $new_hello='' ) {
    static $hello;
    if ( !empty( $new_hello ) ) {
        $hello = $new_hello;
    }
    return $hello;
}

awful_function( 'telephone' );
echo awful_function(); // prints telephone
awful_function( 'banana');
echo awful_function(); // prints banana

Yeniden kullanmak üzere bir yerde veri depolayarak zamandan tasarruf etmek istiyorsanız, WP_Cachesistemi wp_cache_getvb. Kullanarak kullanmayı düşünün.


Global kapsamı kullanmanın biraz zor olduğunu biliyorum, ancak çoğu, bu değişkenlerin tümü her sayfada kullanılmayacaksa. Daha iyi fikirlere açığım. Niyetimizi biraz daha net hale getirmek için soruyu düzenleyeceğim. BTW <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>, önerinize göre yaptığımda mükemmel çalışıyor . Teşekkürler!
JPollock

2
Benim çözümüm işe yararsa, kabul edildi olarak işaretler misiniz? Global değişkenleriniz orijinal çağrıyı yapmak kadar hızlıdır, bunun yerine işlevleri kullanarak denemek isteyebilirsiniz, bu nedenle 2 satır yazmanıza gerek kalmaz, daha iyisi, bir singleton, daha iyisi, hepsini dinamik hale getirin. şablon bölümü get_template_part aracılığıyla dahil edildi
Tom J Nowell

@MarkKaplun'un önerdiği stratejilerden biriyle devam etmeme rağmen, şu anda yaptığım iş olarak kabul edildi. Get_template_part () kullanmak ilginç bir fikir, ancak bunun gibi kısa dosyalarla dolu bir dir elde etmek istediğimden emin değilim ...
JPollock

oooh hayır hayır, her kategori için bir dosya istemezsiniz, sadece geçerli kategori adını alan ve bunu kullananları istersiniz. Hiçbir şeyi kodlamamanız, hepsini kodlamanın zorluğunu hayal etmemeniz gerekir
Tom J Nowell

Kodu, etkin olan child-functions.php dosyasına koydum. Ancak değişkene "normal" veritabanı tarafından oluşturulan bir gönderiden çağırdığım php-include dosyasındaki erişemiyorum. Lütfen bana bildir, ne yanlış yaparım? (Elbette global olarak tanımlarım.)
ycc_swe

19

Global değişkenleri kullanmayın , bu kadar basit.

Neden globals kullanmamak

Çünkü küresel kullanım, yazılımı uzun vadede korumayı zorlaştırır.

  • Bir global kodun herhangi bir yerinde veya hiç bir yerde ilan edilemez, bunun için içgüdüsel olarak globalin ne için kullanıldığı hakkında bir yorum bulabileceğiniz bir yer yoktur.
  • Kod okurken, genellikle değişkenlerin işlevin yerel olduğunu ve işlevin değerini değiştirmenin sistem genelinde bir değişikliğe sahip olabileceğini kabul edemezsiniz.
  • Girdiyi işlemezlerse, işlevler aynı parametrelerle çağrıldığında aynı değeri / çıkışı döndürmelidir. Bir fonksiyonda küresellerin kullanılması, fonksiyon bildiriminde belgelenmeyen ilave parametreler ortaya çıkarır.
  • globals özel bir başlatma yapısına sahip değildir ve bunun için global değerine ne zaman erişebildiğinizden asla emin olamazsınız ve globalleştirmeden önce global erişmeye çalışırken hiçbir hata alamazsınız.
  • Bir başkası (belki bir eklenti), aynı ada sahip global kodlar kullanabilir, kodunuzu mahvedebilir veya ilkleme sırasına bağlı olarak mahvedebilirsiniz.

WordPress çekirdeği, dünyayı çok fazla kullanmanın bir yoludur. Temel işlevlerin nasıl çalıştığını anlamaya çalışırken the_content, aniden $moredeğişkenin yerel değil, global olduğunu ve ne zaman doğru olduğunu belirlemek için tüm çekirdek dosyaları aramanız gerektiğini fark edersiniz .

Peki, ilk çalıştırma sonucunu global olarak saklamak yerine birkaç satır kod kopyalayıp yapıştırmayı durdurmaya çalışırken ne yapılabilir? İşlevsel ve OOP olmak üzere birkaç yaklaşım vardır.

Tatlandırıcı işlevi. Bu sadece kopyala / yapıştır kaydetmek için bir sarıcı / makro

// input: $id - the category id
// returns: the foo2 value of the category
function notaglobal($id) {
  $a = foo1($id);
  $b = foo2($a);
  return $b;
}

Avantajları şimdi eski globalin yaptıklarına dair bir dokümantasyonun olması ve iade edilen değer beklediğiniz değilken hata ayıklama konusunda bariz bir noktanız var.

Bir tatlandırıcınız olduğunda, gerekirse sonucu önbelleğe almak kolaydır (yalnızca bu işlevin yürütülmesi uzun zaman alırsa bunu yapın)

function notaglobal($id) {
  static $cache;

  if (!isset($cache)) {
    $a = foo1($id);
    $b = foo2($a);
    $cache = $b;
  } 
  return $cache;
} 

Bu size global olarak aynı davranışı verir, ancak her erişiminizde güvenli bir şekilde ilk kullanıma sahip olmanın avantajıyla.

OOP ile benzer kalıplara sahip olabilirsiniz. OOP'un genellikle eklentiler ve temalara değer katmadığını biliyorum, ancak bu farklı bir tartışma.

class notaglobal {
   var latestfoo2;

   __constructor($id) {
     $a = foo1($id);
     $this->latestfoo2 = foo2($a)
   }
}

$v = new notaglobal($cat_id);
echo $v->latestfoo2;

Bu bir clumsier kodudur, ancak her zaman kullanıldıkları için önceden hesaplamak istediğiniz birkaç değeriniz varsa, bu bir yol olabilir. Temel olarak bu, tüm globlarınızı organize bir şekilde içeren bir nesnedir. Bu nesnenin bir örneğini global yapmaktan kaçınmak için (bir örneği görmek isterseniz aksi halde değerleri yeniden hesaplayın) bir singleton deseni kullanmak isteyebilirsiniz (bazı kişiler bunun kötü bir fikir olduğunu iddia eder, YMMV)

Bir nesne özelliğine doğrudan erişmek istemiyorum, bu yüzden kodumda biraz daha çarpıtılacak

class notaglobal {
   var latestfoo2;

   __constructor() {}

   foo2($id) {  
     if (!isset($this->latestfoo2)) {    
       $a = foo1($id);
       $b = foo2($a);
       $this->latestfoo2= $b;
     } 
     return $this->latestfoo2;
   }
}

$v = new notaglobal();
echo $v->foo2($cat_id);

7
Lütfen bağırma . Nedenini açıklamak ve bir tür atıfta bulunmak ister misiniz?
brasofilo

Bence cevabı yanlış anladın. Global değişkenlerde değerleri depolayarak erken optimizasyon yapmaya çalışmadıysa kodu işe yarayacaktı. Bağırmak, temel oluşturulmuş yazılım geliştirme ilkelerini takip etmek, yeterince vurgulanamayan bir şeydir. Bu temel prensibi anlamayan kişiler (yerel google’da mevcut), ağı ağ üzerinden yaymamalıdır.
Mark Kaplun

1
IMO bu bir cevap, buraya google'dan gelen insanlar, hemen globals kullanmayı düşünmenin kötü bir fikir olduğunu görmelidir.
Mark Kaplun

6
X'i yapma demek yeterli değil, nedenini açıklamak zorundasın ya da bir hevesle söylediğini söylemelisin
Tom J Nowell

1
@TomJNowell, açıkça WASE'in kapsamı dışında olduğu için sorunun kendisinden aşağı inen tek kişi olduğumu komik buluyorum. Burada başlatılmaması gereken bir konuda genişlemenin değerini görmedim.
Mark Kaplun

8

Sorunuz php'ın nasıl çalıştığı ile ilgilidir.

$ Wpdb'yi örnek olarak alın

$ wpdb bilinen bir global değişkendir.

Ne zaman ilan edileceğini ve değerlerle atanacağını biliyor musunuz?

Her sayfa yüklendi , evet, wordpress sitenizi her ziyaretinizde.

Benzer şekilde, küreselleşmek istediğiniz değişkenlerin ilan edildiğinden ve yüklenen her sayfaya karşılık gelen değerlerle atandığından emin olmanız gerekir.

Bir tema tasarımcısı olmasam da, after_setup_theme 'in bir seferlik kanca olduğunu söyleyebilirim. sadece tema aktif olduğunda tetiklenir.

Yerinde olsam init ya da başka kancalar kullanırım. Hayır, senin yerinde olsam, küresel değişkenler kullanmayacağım.

Bir şeyleri açıklamakta gerçekten iyi değilim. Öyleyse, PHP'ye dalmak istiyorsanız bir kitap almalısınız.


2

Statik alıcılar aracılığıyla her zaman bir singleton desenini kullanabilirsiniz.

<ul>
    <li><?php echo MyGlobals::get_nav_prop( 'proposal' )[ 'html' ]; ?></li>
    <li><?php echo MyGlobals::get_nav_prop( 'calvinball', 'html' ); ?></li>
</ul>


<?php

if ( ! class_exists('MyGlobals') ):

class MyGlobals {

    public $props;

    public function __construct(){
      $this->props = array (
        'proposal' => array( 'title' => 'Proposal', 'text' => 'Proposal' ),
        'calvinball' => array( 'title' => 'Calvinball', 'text' => 'Calvinball' ),
      );
    }

    public function get_nav_prop ( $term, $prop = false )
    {
      $o = self::instance();
      if ( ! isset( $o->props[$term] ) ) {  return falst; }
      if ( ! isset( $o->props[$term][ 'html' ] ) ) {
          $id = get_cat_ID( $term );
          $link = esc_url ( get_category_link( $id ) );
          $title = $o->props[$term]['title'];
          $text = $o->props[$term]['text'];
          $o->props[$term]['html'] = '<a href="'.$link.'" title="'.$title.'">'.$text.'</a>';
          $o->props[$term]['link'] = $link;
          $o->props[$term]['id'] = $id;
      }

      if($prop){ return isset($o->props[$term][$prop]) ? $o->props[$term][$prop] : null; }

      return $o->props[$term];
    }

    // -------------------------------------

    private static $_instance;

    public static function instance(){

      if(!isset(self::$_instance)) {
        self::$_instance = new MyGlobals();
      }
      return self::$_instance;
    }

}

endif; // end MyGlobals
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.