グローバル変数を設定して使用する方法は?または、それらをまったく使用しないのはなぜですか

更新:元の質問は解決されましたが、これはグローバル変数を使用しない理由についての有効な議論になりつつあるため、それを反映するように質問を更新しています。 @TomJNowellが提案したように、解決策は<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>でした。

更新2:これで、やりたいことを正確に実行できます。しかし、私はまだグローバルスコープを使用しており、より良い方法を見つけたいと思っています。

カテゴリへのパーマリンク用に、さまざまな場所で使用されるグローバル変数をすべて設定しようとしています。テーマ。これの主な理由は、メインナビゲーションと、現在の投稿がどのカテゴリにあるかに基づいて選択される一連のサブナビゲーションの両方で使用するためです。これはテーマではありません。他の人が使用できるようにリリースしますが、1つの非常に特定の目的のために構築されています。

これが現在作成している方法です(いくつかの変数にのみ貼り付けました)。

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

これで、4つの場所で<?php global $prop; echo $prop; ?>を実行して、コードのリンク全体を取得できます。それが変わるとき、私はそれを一箇所で変える必要があるだけです。私は、グローバルスコープを含まない代替案を受け入れています。

コメント

  • このステートメントを実行するリンクはどれですか。echoesc_url($ category_link_prop); displays。 ?予想されるリンクは何ですか?
  • ‘ get_cat_ID(****)’グローバル変数を使用する予定の場所。これを使用する方法で速度の利点があるとは思えません。読みやすさの観点から、’ get_cat_ID(****)’が勝ちます。
  • 言い換えてもらえますか?質問を読みましたが、’まだ何がわからないのですか私の一般的なアドバイスは、グローバル変数を使用せず、グローバルスコープを汚染しないことです
  • これは X / Yの問題。おそらく、バックアップして、希望する結果が何であるかを正確に説明する必要があります。’確かにここ’は、グローバル変数の束を設定して、他の場所のナビゲーションでそれらへの参照をハードコードするよりもはるかに洗練されたソリューションです
  • メニューを出力する関数を作成します渡したコンテキストに基づいて、すべてのメニューロジックと関連する変数を1か所にカプセル化しておくことができます。

回答

これには強くお勧めしますが、 速度は上がりませんが、使用法は不正解です。

WordPressはすでにこれらのものをオブジェクトキャッシュにキャッシュしています。結果を保存して再利用する必要はありません。WPはすでにそれを行っています

このマイクロ最適化の結果、コードの実行速度が速くなるのではなく、遅くなる可能性が非常に高くなります。

グローバルの使用方法

グローバルを使用する場合は、最初にglobalキーワードを指定する必要があります。値を定義するときにここで指定しましたが、そのスコープ外では、グローバルスコープ変数として再宣言する必要があります。

例: functions.php

  function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );  

single.phpでは、これは機能しません:

  echo $hello;  

$helloが定義されていないため。ただし、これはで機能します

  global $hello; echo $hello;  

もちろん、どちらも実行しないでください。 WordPressはすでにこれらのものをオブジェクトキャッシュにキャッシュしようとしています

グローバル変数のデメリットと危険性

これを行っても速度は向上しません(速度がわずかに低下する場合があります)。複雑さが増し、不要なグローバル宣言を多数入力する必要があります。

他の問題も発生します。

  • テストを記述できないコード
  • 実行するたびに動作が異なるコード
  • li>

  • 共有ネームスペースからの変数名の衝突
  • global
  • の完全な欠如の宣言を忘れた場合の偶発的なバグコードデータストレージの構造
  • その他多数

代わりに何を使用する必要がありますか?

次のような構造化データを使用する方がよいでしょう。オブジェクトまたは依存関係の挿入として、またはあなたの場合は関数のセットとして。

静的変数

静的変数良くありませんが、グローバル変数のやや邪悪ないとこと考えてください。静的変数はグローバル変数に対するものであり、泥で覆われたパンはシアン化物に対するものです。

たとえば、静的変数を介して同様のことを行う方法は次のとおりです。

  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はすでにそれをしています

本当にしたいのなら再利用するデータをどこかに保存して時間を節約するには、WP_Cacheシステムとwp_cache_getなどを使用することを検討してください。例:

 $value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }  

これで、WordPressによるリクエストの有効期間中、値がキャッシュされ、デバッグツールに表示されます。オブジェクトキャッシュがある場合は、「リクエスト間で永続化されます


補足1:リクエスト間でグローバル変数のデータを永続化しようとする人がいますが、これがPHPの動作方法ではないことに気づいていません。 。 Nodeアプリケーションとは異なり、各リクエストはアプリケーションの新しいコピーをロードし、リクエストが完了すると終了します。このため、あるリクエストに設定されたグローバル変数は次のリクエストまで存続しません

補足2:更新された質問から判断すると、グローバル変数はパフォーマンスの向上をまったくもたらしません。必要なときに必要なときにHTMLを生成するだけで、同じくらい速く、おそらく少しでも速く実行されます。これはマイクロ最適化です。

コメント

  • わかっています’グローバルスコープですが、これらの変数のすべてではないにしても、ほとんどがすべてのページで使用されます。私は’より良いアイデアを受け入れています。質問を編集して、意図を少し明確にします。ところで、あなたの提案に従って<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>を実行すると、完全に正常に機能します。ありがとう!
  • 私のソリューションが機能する場合、承認済みとしてマークできますか?グローバル変数は元の呼び出しを行うのと同じくらい高速です。代わりに関数を使用してみてください。’ 2行を入力する必要はありませんが、シングルトン、さらに良いことに、すべてを動的にし、get_template_partを介して含まれるテンプレートパーツに含めます
  • @MarkKaplunが以下に提案する戦略のいずれかを使用することもできますが、現在行っていることとして受け入れ済みとしてマークされます。 get_template_part()を使用するのは興味深いアイデアですが、’そのような短いファイルでいっぱいのディレクトリが必要かどうかわかりません…
  • oooh noいいえ、’各カテゴリのファイルは必要ありません。’は、現在のカテゴリ名を取得してそれを使用するファイルだけが必要です。 。 ‘何かをハードコーディングする必要はありません。すべてをハードコーディングする煩わしさを想像してください
  • アクティブなchild-functions.phpにコードを配置します。しかし、” normal “データベースで生成された投稿から呼び出すphp-includeファイルの変数にアクセスできません。教えてください、私は何を間違えますか? (もちろん、グローバルと定義します。)

回答

グローバル変数を使用しないでくださいそのように単純です。

使用しない理由グローバルを使用する

グローバルを使用すると、ソフトウェアを長期間維持することが難しくなるためです。

  • グローバルコード内のどこにでも宣言できるか、まったく宣言できないため、グローバルが何に使用されているかについてのコメントを本能的に見ることができる場所はありません。
  • コードを読んでいる間、通常は次のように想定します。変数は関数に対してローカルであり、関数内で値を変更するとシステム全体が変更される可能性があることを理解していません。
  • 入力を処理しない場合、関数は同じ値/出力を返す必要があります。同じパラメーターで呼び出されます。関数でグローバルを使用すると、関数宣言に記載されていない追加のパラメーターが導入されます。 。
  • グローバルには特定の初期化構造がないため、グローバルの値にいつアクセスできるかわからないため、初期化前にグローバルにアクセスしようとしてもエラーは発生しません。 。
  • 他の誰か(プラグインかもしれません)が同じ名前のグローバルを使用してコードを台無しにしたり、初期化の順序に応じてコードを台無しにしたりする可能性があります。

WordPressコアにはグローバルの多くの使用への方法。 the_contentのような基本的な関数がどのように機能するかを理解しようとすると、$more変数がローカルではなくグローバルであり、全体を検索する必要があることに突然気付きます。いつtrueに設定されるかを理解するためのコアファイルの数。

では、コピーを停止しようとすると、&最初の実行結果をグローバルに保存する代わりに、数行のコードを貼り付けるとどうなるでしょうか。機能的および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; 

これは不器用なコードですが、常に使用されているため、事前に計算したい値がいくつかあります。これは、方法の1つです。基本的に、これは、すべてのグローバルを整理された方法で含むオブジェクトです。このオブジェクトのインスタンスがグローバルになるのを避けるためです。 (1つのインスタンスが必要です。それ以外の場合は値を再計算します)シングルトンパターンを使用することをお勧めします(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); 

コメント

  • お願いします。 ‘叫びません。理由を説明し、何らかの引用を提供してください。
  • あなたは答えを誤解したと思います。 ‘グローバル変数に値を格納して早期の最適化を行おうとしなかった場合、彼のコードは機能していました。叫び声は、確立された基本的なソフトウェア開発の原則に従うことは、’十分に強調できないものだからです。これらの基本原則(ローカルのグーグルで入手可能)を理解していない人は、コードをネット上に広めるべきではありません。
  • IMOこれは答えです。グーグルからここに来る人は、それが悪い考えであることを理解する必要があります。すぐにグローバルを使用することを考えることさえできます。
  • ‘ Xを実行しないと言うだけでは不十分です。理由を説明する必要があります。そうしないと、自分のように見えます’気まぐれで言っている
  • @TomJNowell、明らかに質問自体の範囲外だったので、私だけが質問自体に反対票を投じたのはおかしいと思います。 WASE。 ‘ここで始めるべきではなかったテーマを拡張することの価値がわかりませんでした。

回答

あなたの質問は、phpがどのように機能するかに関係しています。

$ wpdb を例として取り上げます

$ wpdb はよく知られているグローバル変数です。

いつ宣言され、値が割り当てられるか知っていますか?

すべてのページが読み込まれましたはい、ワードプレスサイトにアクセスするたびに。

同様に、グローバル化する変数が宣言され、ページが読み込まれるたびに対応する値が割り当てられるようにする必要があります。

私はテーマデザイナーではありませんが、after_setup_themeは1つであることがわかります。タイムフック。テーマがアクティブになったときにのみトリガーされます。

私があなたの場合は、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 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です