วิธีการตั้งค่าและใช้ตัวแปรทั่วโลก? หรือทำไมไม่ใช้มันเลย


27

อัปเดต:คำถามเดิมของฉันได้รับการแก้ไขแล้ว แต่นี่กลายเป็นการอภิปรายที่ถูกต้องเกี่ยวกับสาเหตุที่ไม่ใช้ตัวแปรทั่วโลกดังนั้นฉันจึงอัปเดตคำถามเพื่อให้สะท้อนถึงสิ่งนั้น วิธีแก้ไขคือ<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>ตามที่ @TomJNowell แนะนำ

ปรับปรุง 2:ตอนนี้ฉันได้ทำสิ่งที่ฉันต้องการ แต่ฉันยังคงใช้ขอบเขตทั่วโลกและยินดีที่จะหาวิธีที่ดีกว่า

ฉันกำลังพยายามตั้งค่าตัวแปรส่วนกลางจำนวนมากเพื่อให้ลิงก์ไปยังหมวดหมู่ถูกใช้ในสถานที่ต่าง ๆ ในธีมของฉัน เหตุผลหลักสำหรับสิ่งนี้คือเพื่อใช้ในการนำทางหลักเช่นเดียวกับในชุดการนำทางย่อยที่เลือกตามประเภทของโพสต์ปัจจุบันที่มีอยู่นี่ไม่ใช่ชุดรูปแบบที่ฉันจะปล่อยให้ผู้อื่นใช้ แต่ถูกสร้างขึ้นเพื่อวัตถุประสงค์เฉพาะอย่างหนึ่งอย่างยิ่ง

นี่คือวิธีที่ฉันกำลังสร้างพวกเขาในขณะนี้ (ฉันวางเพียงบางตัวแปร)

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' );

ตอนนี้ฉันสามารถทำ<?php global $prop; echo $prop; ?>int เขา 4 ที่ที่จะไปและกลับลิงค์ทั้งหมดสำหรับรหัส เมื่อมีการเปลี่ยนแปลงฉันต้องเปลี่ยนมันในที่เดียว ฉันเปิดให้ทางเลือกที่ไม่เกี่ยวข้องกับขอบเขตทั่วโลก


1
คำสั่งนี้ใช้ลิงก์ใด echo esc_url ($ category_link_prop); แสดงหรือไม่ ลิงค์ที่คาดหวังของคุณคืออะไร?
Vinod Dalvi

1
ทำไมคุณไม่เพียงแค่ใช้ 'get_cat_ID (****)' ในที่ที่คุณเคยวางแผนที่จะใช้ตัวแปรโกลบอล ฉันสงสัยว่าจะมีข้อได้เปรียบความเร็วใด ๆ ในแบบของคุณ จากมุมมองที่สามารถอ่านได้ 'get_cat_ID (****)' จะชนะด้วยมือ
Chris Strutton

1
คุณสามารถใส่ข้อความซ้ำได้ไหม ฉันอ่านคำถามของคุณแล้วและฉันยังไม่แน่ใจในสิ่งที่คุณต้องการทำและทำไมคุณถึงอยากทำ คำแนะนำทั่วไปของฉันคือการไม่ใช้ตัวแปรทั่วโลกและจะไม่สร้างความเสียหายให้กับขอบเขตทั่วโลก
Tom J Nowell

1
นี้จะทำให้เกิดเสียงบิตเช่นX / Y ปัญหา บางทีคุณควรสำรองข้อมูลและอธิบายอย่างชัดเจนว่าผลลัพธ์ที่คุณต้องการคืออะไร ฉันมั่นใจว่ามีวิธีแก้ปัญหาที่สง่างามกว่าการตั้งค่า vars ทั่วโลกให้เป็นเพียงแค่การอ้างอิง hardcode กับพวกเขาใน nav ที่อื่น
Milo

2
สร้างฟังก์ชั่นที่แสดงผลเมนูของคุณตามบริบทที่คุณส่งผ่านไปเพื่อให้คุณสามารถรักษาตรรกะของเมนูและ vars ที่เกี่ยวข้องทั้งหมดไว้ในที่เดียว
Milo

คำตอบ:


21

ในขณะที่ฉันแนะนำอย่างยิ่งต่อสิ่งนี้และมันจะไม่เพิ่มความเร็วการใช้งานของคุณไม่ถูกต้อง

เมื่อคุณพยายามที่จะใช้ทั่วโลกคุณต้องระบุคำหลักทั่วโลกก่อน คุณได้ระบุไว้ที่นี่เมื่อกำหนดค่าของมัน แต่อยู่นอกขอบเขตนั้นจะต้องมีการประกาศใหม่เป็นตัวแปรขอบเขตโกลบอล

เช่นใน functions.php:

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

ใน single.php สิ่งนี้จะไม่ทำงาน:

echo $hello;

เนื่องจาก $ hello ไม่ได้ถูกกำหนด อย่างไรก็ตามสิ่งนี้จะใช้ได้:

global $hello;
echo $hello;

แน่นอนคุณไม่ควรทำ WordPress พยายามแคชสิ่งเหล่านี้ในแคชวัตถุแล้ว คุณจะไม่เห็นความเร็วเพิ่มขึ้นจากการทำเช่นนี้ (คุณอาจเห็นความเร็วลดลงเล็กน้อย) สิ่งที่คุณจะได้รับคือความซับซ้อนที่เพิ่มขึ้นและความจำเป็นในการพิมพ์การประกาศทั่วโลกจำนวนมากที่ไม่จำเป็น

คุณควรใช้ข้อมูลที่มีโครงสร้างเช่นวัตถุหรือการฉีดพึ่งพาหรือในกรณีของคุณชุดของฟังก์ชัน

ตัวอย่างเช่นนี่คือวิธีการทำสิ่งที่คล้ายกันผ่านตัวแปรคงที่ (ยังไม่ดีสำหรับเหตุผลเดียวกัน แต่เพียงเล็กน้อยน้อยกว่าและพิมพ์ง่ายกว่า) เช่น

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

หากคุณต้องการประหยัดเวลาด้วยการเก็บข้อมูลไว้ที่อื่นเพื่อนำกลับมาใช้ใหม่ให้พิจารณาใช้WP_Cacheระบบกับwp_cache_getฯลฯ


ฉันรู้ว่ามันเป็นถั่วเล็ก ๆ น้อย ๆ ที่จะใช้ขอบเขตทั่วโลก แต่ส่วนใหญ่หากไม่ใช้ตัวแปรเหล่านี้ทั้งหมดในทุกหน้า ฉันเปิดรับแนวคิดที่ดีกว่า ฉันจะแก้ไขคำถามเพื่อให้เจตนาของฉันชัดเจนขึ้นเล็กน้อย BTW มันทำงานได้อย่างสมบูรณ์แบบเมื่อฉันทำ<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>ตามคำแนะนำของคุณ ขอบคุณ!
JPollock

2
อ่าถ้าวิธีการแก้ปัญหาของฉันทำงานได้คุณสามารถทำเครื่องหมายว่ายอมรับหรือไม่? ตัวแปรทั่วโลกของคุณนั้นเร็วเท่ากับการโทรดั้งเดิมคุณอาจต้องการลองใช้ฟังก์ชั่นแทนดังนั้นคุณไม่จำเป็นต้องพิมพ์ 2 บรรทัดดีกว่า แต่เป็นซิงเกิลดีกว่ายังสร้างไดนามิกทั้งหมดและใน ส่วนเทมเพลตรวมอยู่ใน get_template_part
Tom J Nowell

ทำเครื่องหมายว่าได้รับการยอมรับว่าเป็นสิ่งที่ฉันทำอยู่ตอนนี้แม้ว่าฉันจะใช้กลยุทธ์อย่างใดอย่างหนึ่ง @MarkKaplun แนะนำด้านล่าง ใช้ get_template_part () เป็นความคิดที่น่าสนใจ แต่ฉันไม่แน่ใจว่าฉันต้องการมี dir ที่เต็มไปด้วยไฟล์สั้น ๆ แบบนั้น ...
JPollock

oooh ไม่ไม่คุณไม่ต้องการไฟล์สำหรับแต่ละหมวดหมู่คุณต้องการเพียงไฟล์ที่คว้าชื่อหมวดหมู่ปัจจุบันและใช้มัน คุณไม่ควรต้องใส่รหัสอะไรลองจินตนาการถึงความยุ่งยากในการเข้ารหัสทั้งหมด
Tom J Nowell

ฉันใส่รหัสลงใน child-Functions.php ที่ใช้งานอยู่ แต่ฉันไม่สามารถเข้าถึงตัวแปรในไฟล์ php-include ที่ฉันเรียกจากโพสต์ที่สร้างจากฐานข้อมูล "ปกติ" โปรดแนะนำฉันฉันจะทำอะไรผิด (ฉันกำหนดให้เป็นโลกแน่นอน)
ycc_swe

19

อย่าใช้ตัวแปรโกลบอลอย่างง่ายๆ

ทำไมไม่ใช้ globals

เนื่องจากการใช้กลมทำให้การบำรุงรักษาซอฟต์แวร์ในระยะยาวทำได้ยากขึ้น

  • ทั่วโลกสามารถประกาศได้ทุกที่ในรหัสหรือไม่มีเลยเพราะไม่มีที่ที่คุณสามารถดูความคิดเห็นเกี่ยวกับสิ่งที่โลกใช้สำหรับ
  • ในขณะที่อ่านรหัสคุณมักจะคิดว่าตัวแปรเป็นแบบท้องถิ่นของฟังก์ชันและไม่เข้าใจว่าการเปลี่ยนค่าในฟังก์ชันอาจมีการเปลี่ยนแปลงทั้งระบบ
  • หากไม่จัดการอินพุตฟังก์ชันควรส่งคืนค่า / เอาต์พุตเดียวกันเมื่อถูกเรียกด้วยพารามิเตอร์เดียวกัน การใช้ globals ในฟังก์ชันจะแนะนำพารามิเตอร์เพิ่มเติมซึ่งไม่ใช่เอกสารในการประกาศฟังก์ชัน
  • globals ไม่มีโครงสร้างการเริ่มต้นที่เฉพาะเจาะจงและคุณไม่สามารถมั่นใจได้เมื่อคุณสามารถเข้าถึงคุณค่าของโลกและคุณจะไม่ได้รับข้อผิดพลาดใด ๆ เมื่อพยายามเข้าถึงโลกก่อนที่จะเริ่มต้น
  • บางคนอาจมีปลั๊กอินที่ใช้ชื่อเดียวกันทำลายรหัสของคุณหรือคุณอาจทำการทำลายโดยขึ้นอยู่กับลำดับการเริ่มต้น

WordPress core มีวิธีการใช้งานเยอะมาก ในขณะที่พยายามเข้าใจว่าฟังก์ชั่นพื้นฐานทำงานอย่างไรthe_contentทันใดนั้นคุณก็ตระหนักว่า$moreตัวแปรนั้นไม่ใช่แบบโลคอล แต่เป็นระดับโลกและต้องการค้นหาไฟล์หลักทั้งหมดเพื่อทำความเข้าใจว่าเมื่อใดที่มันเป็นจริง

ดังนั้นสิ่งที่สามารถทำได้เมื่อพยายามหยุดการคัดลอก & วางโค้ดหลายบรรทัดแทนที่จะเก็บผลลัพธ์การรันครั้งแรกในโกลบอล? มีหลายวิธีการทำงานและ OOP

ฟังก์ชั่นสารให้ความหวาน มันเป็นเพียงเสื้อคลุม / แมโครสำหรับการบันทึกคัดลอก / วาง

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

ประโยชน์ที่ได้รับคือตอนนี้มีเอกสารสำหรับสิ่งที่อดีตทั่วโลกทำและคุณมีจุดที่ชัดเจนสำหรับการดีบักเมื่อค่าที่ส่งคืนไม่ใช่สิ่งที่คุณคาดหวัง

เมื่อคุณมีสารให้ความหวานมันเป็นเรื่องง่ายที่จะแคชผลถ้าจำเป็น (ทำเฉพาะในกรณีที่คุณค้นพบว่าฟังก์ชั่นนี้ใช้เวลานานในการดำเนินการ)

function notaglobal($id) {
  static $cache;

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

สิ่งนี้จะช่วยให้คุณมีพฤติกรรมเหมือนกันทั่วโลก แต่ด้วยความได้เปรียบของการเริ่มต้นมั่นใจทุกครั้งที่คุณเข้าถึง

คุณสามารถมีรูปแบบที่คล้ายกันกับ OOP ฉันพบว่า OOP มักจะไม่เพิ่มค่าใด ๆ ในปลั๊กอินและธีม แต่นี่เป็นการอภิปรายที่แตกต่าง

class notaglobal {
   var latestfoo2;

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

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

นี่คือรหัส clumsier แต่ถ้าคุณมีหลายค่าที่คุณต้องการ precompute เพราะพวกมันถูกใช้อยู่ตลอดเวลานี่อาจเป็นวิธีที่จะไป โดยทั่วไปนี่เป็นวัตถุที่บรรจุรูปดาวทั้งหมดของคุณในรูปแบบที่เป็นระเบียบ เพื่อหลีกเลี่ยงการสร้างอินสแตนซ์ของวัตถุนี้ให้เป็นโกลบอล (คุณต้องการอินสแตนซ์หนึ่งตัวหรือคุณจะคำนวณค่าใหม่) คุณอาจต้องการใช้รูปแบบซิงเกิล (บางคนแย้งว่าเป็นแนวคิดที่ไม่ดี YMMV)

ฉันไม่ชอบที่จะเข้าถึงคุณลักษณะของวัตถุโดยตรงดังนั้นในรหัสของฉันมันจะทำให้บิดได้มากกว่านี้

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
กรุณาอย่าตะโกน รังเกียจที่จะอธิบายว่าทำไมและให้การอ้างอิงบางอย่าง?
brasofilo

ฉันคิดว่าคุณเข้าใจผิดคำตอบ หากเขาไม่ได้พยายามเพิ่มประสิทธิภาพ แต่เนิ่น ๆ โดยการเก็บค่าไว้ในตัวแปรทั่วโลกโค้ดของเขาจะใช้ได้ การตะโกนนั้นเป็นเพราะการปฏิบัติตามหลักการพัฒนาซอฟต์แวร์ขั้นพื้นฐานเป็นสิ่งที่ไม่สามารถเน้นได้เพียงพอ ผู้ที่ไม่เข้าใจหลักการพื้นฐานเหล่านั้น (มีให้ที่ google ในพื้นที่ของคุณ) ไม่ควรแพร่กระจายรหัสผ่านเน็ต
Mark Kaplun

1
IMO นี่เป็นคำตอบคนที่มาที่นี่ในรูปแบบ google ควรเห็นว่าเป็นความคิดที่ไม่ดีแม้แต่คิดเกี่ยวกับการใช้ globals ทันที
Mark Kaplun

6
ยังไม่พอที่จะบอกว่าอย่าทำ X คุณต้องอธิบายว่าทำไมหรือดูเหมือนว่าคุณกำลังพูดด้วยความตั้งใจ
Tom J Nowell

1
@ TomJNow ฉันคิดว่ามันตลกมากที่ฉันเป็นคนเดียวในการลบล้างคำถามเพราะเห็นได้ชัดว่าอยู่นอกขอบเขตของ WASE ฉันไม่เห็นคุณค่าของการขยายในเรื่องที่ไม่ควรเริ่มต้นที่นี่เลย
Mark Kaplun

8

คำถามของคุณเกี่ยวข้องกับการทำงานของ php

รับ$ wpdbเป็นตัวอย่าง

$ wpdbเป็นตัวแปรทั่วโลกที่รู้จักกันดี

คุณรู้หรือไม่ว่าจะมีการประกาศและกำหนดค่าเมื่อใด

ทุกหน้าโหลดใช่ทุกครั้งที่คุณเยี่ยมชมเว็บไซต์ wordpress ของคุณ

ในทำนองเดียวกันคุณต้องตรวจสอบให้แน่ใจว่าตัวแปรที่คุณต้องการให้เป็นโลกาภิวัตน์จะถูกประกาศและกำหนดค่าที่เกี่ยวข้องทุกหน้าที่โหลด

แม้ว่าฉันไม่ใช่นักออกแบบธีม แต่ฉันสามารถบอกได้ว่า after_setup_theme เป็นเบ็ดเพียงครั้งเดียว มันจะถูกเรียกเมื่อเปิดใช้งานชุดรูปแบบ

ถ้าฉันเป็นคุณฉันจะใช้ init หรือ hooks อื่น ๆ ไม่ถ้าฉันเป็นคุณฉันจะไม่ใช้ตัวแปรโกลบอลเลย ...

ฉันไม่สามารถอธิบายสิ่งต่าง ๆ ได้ดีนัก ดังนั้นคุณควรเลือกหนังสือถ้าคุณต้องการเจาะลึก PHP


2

คุณสามารถใช้รูปแบบซิงเกิลผ่านทางตัวรับแบบคงที่

<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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.