it-swarm.com.ru

Как установить и использовать глобальные переменные? Или почему бы не использовать их вообще

ОБНОВЛЕНИЕ: Мой первоначальный вопрос был решен, но это превращается в полноценную дискуссию о том, почему бы не использовать глобальные переменные, поэтому я обновляю вопрос, чтобы отразить это. Решение было <?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; ?> в четырех местах и ​​получить всю ссылку на код. Когда это изменится, мне нужно только изменить его в одном месте. Я открыт для альтернатив, которые не связаны с глобальным охватом.

27
JPollock

Хотя я настоятельно советую против этого, и это не ускорит процесс, ваше использование некорректно.

Когда вы пытаетесь использовать глобальный, вы должны сначала указать ключевое слово global. Вы указали его здесь при определении его значения, но за пределами этой области его необходимо повторно объявить как глобальную переменную области.

например в 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 и т.д.

21
Tom J Nowell

Не используйте глобальные переменные , все так просто.

Почему бы не использовать глобалы

Потому что использование глобалов затрудняет поддержание программного обеспечения в долгосрочной перспективе.

  • Глобальный объект может быть объявлен в любом месте кода или вообще нигде, поэтому нет места, в котором вы можете инстинктивно взглянуть, чтобы найти какой-то комментарий о том, для чего используется глобал.
  • При чтении кода вы обычно предполагаете, что переменные являются локальными для функции, и не понимаете, что изменение их значения в функции может привести к общесистемным изменениям.
  • Если они не обрабатывают ввод, функции должны возвращать одинаковое значение/вывод при вызове с одинаковыми параметрами. Использование глобальных переменных в функции вводит дополнительные параметры, которые не задокументированы в объявлении функции.
  • глобальные переменные не имеют какой-либо конкретной конструкции инициализации, и поэтому вы никогда не можете быть уверены, когда сможете получить доступ к значению глобальной переменной, и вы не получите никакой ошибки при попытке доступа к глобальной переменной перед инициализацией.
  • Кто-то другой (возможно, плагин) может использовать глобалы с тем же именем, разрушая ваш код, или вы разрушаете его в зависимости от порядка инициализации.

Ядро WordPress имеет много общего с глобальным использованием. Пытаясь понять, как работают основные функции, такие как the_content, вы внезапно понимаете, что переменная $more не локальная, а глобальная, и вам нужно искать все основные файлы, чтобы понять, когда для нее установлено значение true.

Итак, что можно сделать, пытаясь остановить копирование и вставку нескольких строк кода вместо сохранения результата первого запуска в глобальном формате? Существует несколько подходов, функциональных и ООП.

Функция подсластителя. Это просто оболочка/макрос для сохранения копии/вставки

// 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 обычно не добавляет никакой ценности в плагины и темы, но это другое обсуждение

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);
19
Mark Kaplun

Ваш вопрос связан с тем, как работает PHP.

Возьмите $ wpdb в качестве примера

$ wpdb - известная глобальная переменная.

Вы знаете, когда он будет объявлен и назначен со значениями?

Каждая страница загружена , да, каждый раз, когда вы посещаете ваш WordPress сайт.

Точно так же вы должны убедиться, что те переменные, которые вы хотите глобализировать, будут объявлены и назначены с соответствующими значениями на каждой загруженной странице.

Хотя я не дизайнер тем, я могу сказать, что after_setup_theme - одноразовый хук. он будет срабатывать только при активации темы.

Если бы я был тобой, я бы использовал init или другие хуки. Нет, на вашем месте я вообще не буду использовать глобальные переменные ...

Я действительно не очень хорошо объясняю вещи. Итак, вы должны взять книгу, если вы хотите углубиться в PHP.

6
Jesse

Вы всегда можете использовать шаблон синглтона через статические геттеры.

<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
2
jgraup