전역 변수를 설정하고 사용하는 방법? 아니면 전혀 사용하지 않는 이유 given category

업데이트 : 내 원래의 질문이 해결되었지만 전역 변수를 사용하지 않는 이유에 대한 유효한 토론으로 바뀌고 있으므로 반영하기 위해 질문을 업데이트하고 있습니다. 해결책은 <?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; ?>그가가는 4 곳에서 코드의 전체 링크를 다시 얻을 수있다. 그 변화가있을 때 나는 한 곳에서만 변경해야합니다. 나는 세계적인 범위를 포함하지 않는 대안에 열려 있습니다.



답변

나는 이것에 대해 강력히 권고하지만 속도가 빨라지지는 않지만 사용법이 잘못되었습니다.

글로벌을 사용하려고 할 때 먼저 글로벌 키워드를 지정해야합니다. 값을 정의 할 때 여기에 지정했지만 해당 범위를 벗어나면 전역 범위 변수로 다시 선언해야합니다.

예를 들어 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

재사용 할 수 있도록 데이터를 저장하여 시간을 절약하려면 etc WP_Cache와 함께 시스템 사용을 고려하십시오.wp_cache_get


답변

전역 변수 를 그렇게 간단하게 사용하지 마십시오 .

글로벌을 사용하지 않는 이유

전역을 사용하면 소프트웨어를 장기적으로 유지 관리하기가 어렵습니다.

  • 전역은 코드의 어느 곳에서나 선언 될 수 있으며, 그 어느 곳에서도 전역이 어디에 사용되는지에 대해 본능적으로 주석을 찾을 수있는 곳이 없습니다.
  • 코드를 읽는 동안 일반적으로 변수가 함수의 로컬 변수라고 가정하고 함수에서 값을 변경하면 시스템 전체가 변경 될 수 있음을 이해하지 못합니다.
  • 입력을 처리하지 않으면 함수는 동일한 매개 변수로 호출 될 때 동일한 값 / 출력을 반환해야합니다. 함수에서 전역을 사용하면 함수 선언에 문서화되지 않은 추가 매개 변수가 도입됩니다.
  • 전역에는 특정 초기화 구성이 없으므로 전역 값에 언제 액세스 할 수 있는지 확신 할 수 없으므로 초기화 전에 전역에 액세스하려고 할 때 오류가 발생하지 않습니다.
  • 다른 사람 (플러그인)은 같은 이름의 전역을 사용하여 코드를 망치거나 초기화 순서에 따라 망치를 사용할 수 있습니다.

워드 프레스 코어는 전 세계를 많이 사용합니다. 작동과 같은 기본 기능을 이해하려고 시도하는 동안 변수는 로컬이 아니라 전역 변수이며 언제 true로 설정 되었는지 이해 하기 위해 전체 코어 파일을 검색해야 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;

이것은 더 성가신 코드이지만 항상 사용되므로 미리 계산하려는 여러 값이있는 경우이 방법이 될 수 있습니다. 기본적으로 이것은 모든 글로벌을 체계적으로 포함하는 객체입니다. 이 객체의 인스턴스를 전역으로 만들지 않으려면 (하나의 인스턴스를 원하지 않으면 값을 다시 계산해야 함) 단일 패턴 을 사용할 수 있습니다 (일부 사람들은 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);

답변

귀하의 질문은 PHP의 작동 방식과 관련이 있습니다.

가지고 $ wpdb 예 등을

$ wpdb 는 잘 알려진 전역 변수입니다.

언제 선언되고 값이 할당되는지 알고 있습니까?

워드 프레스 사이트를 방문 할 때마다 모든 페이지가로드 됩니다.

마찬가지로, 전역 화하려는 변수가로드되고 페이지가로드 될 때마다 해당 값이 지정되고 지정되는지 확인해야합니다.

테마 디자이너는 아니지만 after_setup_theme이 한 번의 후크라고 말할 수 있습니다. 테마가 활성화 된 경우에만 트리거됩니다.

내가 너라면 init이나 다른 고리를 사용할 것이다. 아니요, 내가 당신이라면 전역 변수를 전혀 사용하지 않을 것입니다 …

나는 일을 잘 설명하지 못한다. 따라서 PHP에 대해 자세히 알아 보려면 책을 선택해야합니다.


답변

정적 게터를 통해 항상 싱글 톤 패턴을 사용할 수 있습니다.

<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