mirror of
https://github.com/php/doc-ja.git
synced 2026-03-23 22:52:11 +01:00
Closes #310 Co-authored-by: KentarouTakeda <4785040+KentarouTakeda@users.noreply.github.com>
1212 lines
38 KiB
XML
1212 lines
38 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<!-- EN-Revision: 22583751fbfdaa3eaa41aeb6470d1343f5cb2c78 Maintainer: takagi Status: ready -->
|
|
<!-- CREDITS: hirokawa,mumumu -->
|
|
<chapter xml:id="language.variables" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>変数</title>
|
|
|
|
<sect1 xml:id="language.variables.basics">
|
|
<title>基本的な事</title>
|
|
|
|
<simpara>
|
|
PHP の変数はドル記号の後に変数名が続く形式で表されます。
|
|
変数名は大文字小文字を区別します。
|
|
</simpara>
|
|
|
|
<para>
|
|
変数名は、文字
|
|
(<literal>A-Z</literal>, <literal>a-z</literal>,
|
|
128から255 までのバイト) で始まり、
|
|
任意の数の文字、
|
|
数字、アンダースコアが続きます。正規表現を使うと、これは次の
|
|
ように表現することができます。
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
PHP は Unicode の変数名はサポートしていませんが、
|
|
(UTF-8のような)文字エンコーディングによっては、
|
|
マルチバイト文字の全てのバイトを可能な範囲にまでエンコードする場合があり、
|
|
その結果正しい変数名になる場合があります。
|
|
</simpara>
|
|
</note>
|
|
|
|
<note>
|
|
<simpara>
|
|
<literal>$this</literal> は特別な変数であり、ここに代入することはできません。
|
|
PHP 7.1.0 より前のバージョンでは、
|
|
(<link linkend="language.variables.variable">可変変数</link> を使った)
|
|
間接的な代入 が可能でした。
|
|
</simpara>
|
|
</note>
|
|
|
|
&tip.userlandnaming;
|
|
|
|
<example>
|
|
<title>有効な変数名</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$var = 'Bob';
|
|
$Var = 'Joe';
|
|
echo "$var, $Var"; // outputs "Bob, Joe"
|
|
|
|
$_4site = 'not yet'; // valid; starts with an underscore
|
|
$täyte = 'mansikka'; // valid; 'ä' is (Extended) ASCII 228.
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>無効な変数名</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$4site = 'not yet'; // invalid; starts with a number
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<simpara>
|
|
PHP は、任意のバイトの連続を変数名として受け入れます。
|
|
既に述べたルールに従わない変数名は、実行時にのみ動的にアクセスできます。
|
|
アクセスする方法については
|
|
<link linkend="language.variables.variable">可変変数</link>
|
|
を参照ください。
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>曖昧な変数名にアクセスする</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
${'invalid-name'} = 'bar';
|
|
$name = 'invalid-name';
|
|
echo ${'invalid-name'}, " ", $$name;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
bar bar
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
デフォルトでは、変数に代入されるのは常にその値です。
|
|
これは、つまり、ある変数にある式を代入する際、元の式の
|
|
値全体がコピーされる側の変数にコピーされるということです。
|
|
これは、例えば、ある変数の値を他の変数に代入した後で、
|
|
これらの変数の1つを変更しても他の変数には影響を与えないという
|
|
ことを意味します。この種の代入に関するより詳細な情報については、
|
|
<link linkend="language.expressions">式</link> を参照ください。
|
|
</para>
|
|
<para>
|
|
PHP には、変数に値の代入を行う別の方法も存在します。それは、
|
|
<emphasis>参照による代入</emphasis> です。
|
|
この場合、新規の変数は元の変数を参照するだけです。
|
|
(言いかえると、元の変数の"エイリアスを作る"または元の変数を"指す")
|
|
新規の変数への代入は、元の変数に影響し、その逆も同様となります。
|
|
</para>
|
|
<para>
|
|
参照により代入を行うには、代入する変数(ソース変数)の先頭に
|
|
アンパサンドを加えます。たとえば、次の簡単なコードは
|
|
'<literal>My name is Bob</literal>'を二度出力します。
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$foo = 'Bob'; // 値'Bob'を$fooに代入する。
|
|
$bar = &$foo; // $fooを$barにより参照
|
|
$bar = "My name is $bar"; // $barを変更...
|
|
echo $bar;
|
|
echo $foo; // $fooも変更される。
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
|
|
<para>
|
|
注意すべき重要な点として、変数のみが参照により代入できる
|
|
ということがあります。
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$foo = 25;
|
|
$bar = &$foo; // これは有効な代入です。
|
|
$bar = &(24 * 7); // 無効です。名前のない式を参照しています。
|
|
|
|
function test() {
|
|
return 25;
|
|
}
|
|
|
|
$bar = &test(); // 無効。なぜなら、リファレンスで値を返していないからです。
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
|
|
<para>
|
|
PHP では変数を初期化する必要はありませんが、
|
|
そうするのはとてもよいことです。
|
|
初期化されていない場合、
|
|
<constant>E_WARNING</constant>
|
|
(PHP 8.0.0 より前のバージョンでは <constant>E_NOTICE</constant>)
|
|
が発生します。
|
|
未定義の変数は、デフォルト値 &null; を持ちます。
|
|
変数が既に初期化済みかどうかを検知するには、
|
|
言語構造 <function>isset</function> が使えます。
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>未初期化の変数のデフォルト値</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Unset AND unreferenced (no use context) variable.
|
|
var_dump($unset_var);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Warning: Undefined variable $unset_var in ...
|
|
NULL
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
PHP は、未定義の変数からの配列の autovivification
|
|
(新しい配列の自動生成) を許可しています。
|
|
未定義の変数に要素を追加する操作は、
|
|
新しい配列を生成し、警告は発生しません。
|
|
</simpara>
|
|
<example>
|
|
<title>未定義の変数から配列を自動生成する</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$unset_array[] = 'value'; // 警告は発生しません
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<warning>
|
|
<simpara>
|
|
初期化されていない変数のデフォルト値に依存すると、そのファイルを
|
|
include している別のファイルで同名の変数が使用されていた場合に問題を起こします。
|
|
</simpara>
|
|
</warning>
|
|
|
|
<simpara>
|
|
変数は、言語構造
|
|
<function>unset</function>
|
|
を使って破棄できます。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
変数に関連した関数については、
|
|
<link linkend="ref.var">関数リファレンス</link>
|
|
を参照ください。
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.variables.predefined">
|
|
<title>定義済みの変数</title>
|
|
|
|
<para>
|
|
PHPは、多くの
|
|
<link linkend="reserved.variables">定義済みの変数</link> を提供します。
|
|
PHP には、(使用する場合)Webサーバー、環境変数、
|
|
ユーザー入力からの変数を値とする定義済みの配列が追加されています。
|
|
これらの配列は、自動的に全ての
|
|
スコープで利用可能です。このため、これらは
|
|
"スーパーグローバル" といわれることもあります。
|
|
(PHPには、ユーザー定義のスーパーグローバルという機構はありません。)
|
|
<link
|
|
linkend="language.variables.superglobals">スーパーグローバルの一覧</link> も参照ください。
|
|
</para>
|
|
|
|
<note>
|
|
<title>可変変数</title>
|
|
<para>
|
|
<link linkend="language.variables.variable">可変変数</link>として
|
|
スーパーグローバルを使うことはできません。
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
<link linkend="ini.variables-order">variables_order</link>に
|
|
ある変数が設定されていない場合、これらに対応するPHPの定義済み
|
|
変数も空のままとなります。
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.variables.scope">
|
|
<title>変数のスコープ</title>
|
|
|
|
<simpara>
|
|
変数のスコープは、その変数が定義されたコンテキストです。
|
|
PHP には関数スコープとグローバルスコープがあります。
|
|
関数の外部で定義されたあらゆる変数は、グローバルスコープになります。
|
|
ファイルが include された場合、
|
|
そのファイルに含まれるコードは、
|
|
include が行われた行の変数のスコープを引き継ぎます。
|
|
</simpara>
|
|
<example>
|
|
<title>グローバル変数のスコープの例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 1;
|
|
|
|
include 'b.inc'; // 変数 $a は b.inc で利用できます。
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<simpara>
|
|
名前付きの関数や
|
|
<link linkend="functions.anonymous">無名関数</link>
|
|
の内部で作られた変数は、関数の内部のスコープでのみ使えます。
|
|
しかし、<link linkend="functions.arrow">アロー関数</link>
|
|
は親のスコープの変数を内部で利用できるようにするために、
|
|
変数をバインドします。
|
|
ファイルの include が呼び出し側のファイルで発生した場合、
|
|
呼び出されたファイルに含まれる変数は、
|
|
関数を呼び出す内部で定義されたかのように利用できます。
|
|
</simpara>
|
|
<example>
|
|
<title>ローカル変数のスコープ</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 1; // グローバルスコープ
|
|
|
|
function test()
|
|
{
|
|
echo $a; // $a は、ローカルスコープの $a を参照しているので未定義です
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<simpara>
|
|
このスクリプトは、未定義の変数があるという <constant>E_WARNING</constant>
|
|
(PHP 8.0.0 より前のバージョンでは <constant>E_NOTICE</constant>)
|
|
を生成します。
|
|
これは、echo 命令がローカル版の
|
|
<varname>$a</varname> 変数を参照しているにもかかわらず、こ
|
|
のスコープでは値が代入されていないからです。この動作は、特にローカ
|
|
ルな定義で上書きしない限りグローバル変数が自動的に関数で使用可能で
|
|
ある C 言語と少々異なっていると気がつかれるかもしれません。C言語の
|
|
ような場合、グローバル変数を不注意で変更してしまうという問題を生じ
|
|
る可能性があります。PHP では、グローバル変数は、関数の内部で使用す
|
|
る場合、関数の内部でグローバルとして宣言する必要があります。
|
|
</simpara>
|
|
|
|
<sect2 xml:id="language.variables.scope.global">
|
|
<title><literal>global</literal> キーワード</title>
|
|
<simpara>
|
|
<literal>global</literal> キーワードは
|
|
グローバルスコープの変数をローカルスコープにバインドするために使います。
|
|
このキーワードは変数のリストや、単一の変数を指定できます。
|
|
グローバル変数と同じ名前の変数を参照するローカル変数が作られます。
|
|
グローバル変数が存在しない場合、グローバルスコープの変数が作られ、
|
|
&null; が代入されます。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title><literal>global</literal> の使用</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 1;
|
|
$b = 2;
|
|
|
|
function Sum()
|
|
{
|
|
global $a, $b;
|
|
|
|
$b = $a + $b;
|
|
}
|
|
|
|
Sum();
|
|
echo $b;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
関数の内部で
|
|
<varname>$a</varname>、<varname>$b</varname>
|
|
をグローバル宣言を行うことにより、両変数への参照は、グローバル変数
|
|
の方を参照することになります。ある関数により操作できるグローバル変
|
|
数の数は無制限です。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
グローバルスコープから変数をアクセスする2番目の方法は、PHPが定義す
|
|
る配列<varname>$GLOBALS</varname>を使用することです。先の例は、次
|
|
のように書き換えることができます。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>globalのかわりに<varname>$GLOBALS</varname>を使用する</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 1;
|
|
$b = 2;
|
|
|
|
function Sum()
|
|
{
|
|
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
|
|
}
|
|
|
|
Sum();
|
|
echo $b;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
配列<varname>$GLOBALS</varname>は連想配列であり、グローバル変数の
|
|
名前がキー、その変数の内容が配列要素の値となっています。
|
|
<varname>$GLOBALS</varname> は <link
|
|
linkend="language.variables.superglobals">スーパーグローバル</link>
|
|
であるため、<varname>$GLOBALS</varname>は全てのスコープに存在します。
|
|
以下にスーパーグローバルの効果を示す例を示します。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>スーパーグローバルとスコープの例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test_superglobal()
|
|
{
|
|
echo $_POST['name'];
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
<literal>global</literal> キーワードを関数の外部で使ってもエラーにはなりません。
|
|
そのファイルが関数の内部からインクルードされたときに使うことができます。
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.scope.static">
|
|
<title>static 変数の使用</title>
|
|
<simpara>
|
|
変数のスコープに関する別の重要な機能は、<emphasis>static (静的)</emphasis>
|
|
変数です。static 変数はローカル関数スコープのみに
|
|
存在しますが、プログラム実行がこのスコープの外で行われるようになっ
|
|
てもその値を失いません。次の例を見てください。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>static 変数が必要な場面の例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test()
|
|
{
|
|
$a = 0;
|
|
echo $a;
|
|
$a++;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
この関数は、コールされる度に<varname>$a</varname>を
|
|
<literal>0</literal>にセットし、<literal>0</literal> を出力するのでほとん
|
|
ど役にたちません。変数を1増やす $a++ は、関数から外に出ると変数
|
|
<varname>$a</varname>が消えてしまうために目的を達成しません。現在
|
|
のカウントの追跡ができるようにカウント関数を使用できるようにするた
|
|
めには、変数<varname>$a</varname>を static として宣言します。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>static 変数の使用例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test()
|
|
{
|
|
static $a = 0;
|
|
echo $a;
|
|
$a++;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
こうすると、<varname>$a</varname> は関数が最初にコールされたときにのみ初期化され、
|
|
<literal>test()</literal> 関数がコールされるたびに <varname>$a</varname>
|
|
の値を出力してその値を増加させます。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
static 変数は、再帰関数を実現する1つの手段としても使用されます。
|
|
次の簡単な関数は、中止す
|
|
るタイミングを知るためにstatic変数<varname>$count</varname>を用いて、
|
|
10 回まで再帰を行います。
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>再帰関数でのstatic変数の使用</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test()
|
|
{
|
|
static $count = 0;
|
|
|
|
$count++;
|
|
echo $count;
|
|
if ($count < 10) {
|
|
test();
|
|
}
|
|
$count--;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
PHP 8.3.0 より前のバージョンでは、
|
|
static 変数には、定数式でのみ初期化できていました。
|
|
PHP 8.3.0 以降では、動的な式(例: 関数呼び出し) での初期化も許可されています。
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>static 変数の宣言</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(){
|
|
static $int = 0; // 正しい
|
|
static $int = 1+2; // 正しい
|
|
static $int = sqrt(121); // PHP 8.3.0 以降は正しい
|
|
|
|
$int++;
|
|
echo $int;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
無名関数の内部にある static 変数は、
|
|
その特定の関数のインスタンス内でのみ生き残ります。
|
|
コールされるたびに無名関数が再作成される場合、
|
|
static 変数は再初期化されます。
|
|
</simpara>
|
|
<example>
|
|
<title>無名関数の内部にある static 変数</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function exampleFunction($input) {
|
|
$result = (static function () use ($input) {
|
|
static $counter = 0;
|
|
$counter++;
|
|
return "Input: $input, Counter: $counter\n";
|
|
});
|
|
|
|
return $result();
|
|
}
|
|
|
|
// Calls to exampleFunction will recreate the anonymous function, so the static
|
|
// variable does not retain its value.
|
|
echo exampleFunction('A'); // Outputs: Input: A, Counter: 1
|
|
echo exampleFunction('B'); // Outputs: Input: B, Counter: 1
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
(オーバーライドされていない場合)
|
|
内部でstatic 変数を使ったメソッドも継承されます。
|
|
PHP 8.1.0 以降は、継承されたメソッドは、
|
|
親クラスのメソッドとstatic 変数を共有するようになりました。
|
|
つまり、メソッド内でのstatic 変数も、
|
|
static プロパティと同じ振る舞いになったということです。
|
|
</para>
|
|
|
|
<simpara>
|
|
PHP 8.3.0 以降では、static 変数は任意の式で初期化できるようになりました。
|
|
これはたとえば、メソッドをコールすることでも、
|
|
static 変数を初期化できるようになったということです。
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>継承されたメソッドのstatic 変数を使う</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo {
|
|
public static function counter() {
|
|
static $counter = 0;
|
|
$counter++;
|
|
return $counter;
|
|
}
|
|
}
|
|
class Bar extends Foo {}
|
|
var_dump(Foo::counter()); // int(1)
|
|
var_dump(Foo::counter()); // int(2)
|
|
var_dump(Bar::counter()); // int(3), PHP 8.1.0 より前のバージョンでは int(1)
|
|
var_dump(Bar::counter()); // int(4), PHP 8.1.0 より前のバージョンでは int(2)
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.scope.references">
|
|
<title>グローバル変数とstatic 変数のリファレンス</title>
|
|
<simpara>
|
|
PHP は、
|
|
<link linkend="language.references">リファレンス</link>
|
|
変数の修正子として
|
|
<link linkend="language.variables.scope.static">static</link> および
|
|
<link linkend="language.variables.scope.global">global</link>
|
|
を実装しています。
|
|
例えば、関数スコープ内に<literal>global</literal>
|
|
命令により実際にインポートされた真のグローバル変数は、
|
|
実際にグローバル変数へのリファレンスを作成します。
|
|
これにより、以下の例が示すように予測できない動作を引き起こす可能性
|
|
があります。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function test_global_ref() {
|
|
global $obj;
|
|
$new = new stdClass;
|
|
$obj = &$new;
|
|
}
|
|
|
|
function test_global_noref() {
|
|
global $obj;
|
|
$new = new stdClass;
|
|
$obj = $new;
|
|
}
|
|
|
|
test_global_ref();
|
|
var_dump($obj);
|
|
test_global_noref();
|
|
var_dump($obj);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
&example.outputs;
|
|
|
|
<screen>
|
|
<![CDATA[
|
|
NULL
|
|
object(stdClass)#1 (0) {
|
|
}
|
|
]]>
|
|
</screen>
|
|
|
|
<simpara>
|
|
類似の動作が<literal>static</literal>命令にも適用されます。
|
|
リファレンスはstaitc 変数に保存することができません。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &get_instance_ref() {
|
|
static $obj;
|
|
|
|
echo 'Static object: ';
|
|
var_dump($obj);
|
|
if (!isset($obj)) {
|
|
$new = new stdClass;
|
|
// Assign a reference to the static variable
|
|
$obj = &$new;
|
|
}
|
|
if (!isset($obj->property)) {
|
|
$obj->property = 1;
|
|
} else {
|
|
$obj->property++;
|
|
}
|
|
return $obj;
|
|
}
|
|
|
|
function &get_instance_noref() {
|
|
static $obj;
|
|
|
|
echo 'Static object: ';
|
|
var_dump($obj);
|
|
if (!isset($obj)) {
|
|
$new = new stdClass;
|
|
// Assign the object to the static variable
|
|
$obj = $new;
|
|
}
|
|
if (!isset($obj->property)) {
|
|
$obj->property = 1;
|
|
} else {
|
|
$obj->property++;
|
|
}
|
|
return $obj;
|
|
}
|
|
|
|
$obj1 = get_instance_ref();
|
|
$still_obj1 = get_instance_ref();
|
|
echo "\n";
|
|
$obj2 = get_instance_noref();
|
|
$still_obj2 = get_instance_noref();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
この例を実行すると以下の出力となります。
|
|
</simpara>
|
|
|
|
<screen>
|
|
<![CDATA[
|
|
Static object: NULL
|
|
Static object: NULL
|
|
|
|
Static object: NULL
|
|
Static object: object(stdClass)#3 (1) {
|
|
["property"]=>
|
|
int(1)
|
|
}
|
|
+]]>
|
|
</screen>
|
|
|
|
<simpara>
|
|
この例は、static変数にリファレンスを代入した時に
|
|
<literal>&get_instance_ref()</literal>関数を2回目に
|
|
コールした際に保持されていないことを示しています。
|
|
</simpara>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.variables.variable">
|
|
<title>可変変数</title>
|
|
|
|
<simpara>
|
|
変数名を可変にできると便利なことが時々あります。可変変数では、変数
|
|
名を動的にセットし使用できます。通常の変数は、次のような命令でセッ
|
|
トします。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 'hello';
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
可変変数は、変数の値をとり、変数の名前として扱います。上の例では、
|
|
<emphasis>hello</emphasis> は、ドル記号を二つ使用することにより、
|
|
変数の名前として使用することができます。つまり、
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$$a = 'world';
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
ここまでで、二つの変数が定義され、PHP シンボルツリーに定義されてい
|
|
ます。これらは、"hello" を値とする<varname>$a</varname>と "world"
|
|
を値とする<varname>$hello</varname>です。そこで、次の命令
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo "$a {$$a}";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
の出力は、次の命令と全く同じとなります。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo "$a $hello";
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
すなわち、両方共、<computeroutput>hello world</computeroutput>を出
|
|
力します。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
可変変数を配列で使用する際には、曖昧さの問題を解決する必要がありま
|
|
す。つまり、<varname>$$a[1]</varname>と書いた場合、
|
|
<varname>$a[1]</varname>を変数として使用したいのか、
|
|
<varname>$$a</varname>を変数とし [1] を変数の添え字としたいのかを、
|
|
パーサーが知る必要があるのです。この曖昧さを解決するには、前者では
|
|
<varname>${$a[1]}</varname>とし、後者では
|
|
<varname>${$a}[1]</varname>とする構文を用います。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
クラスのプロパティには、可変プロパティ名でアクセスすることができます。
|
|
可変プロパティ名の解決は、呼び出し元のスコープで行われます。
|
|
たとえば <varname>$foo->$bar</varname> のようにするとローカルスコープで
|
|
<varname>$bar</varname> を調べ、その値を
|
|
<varname>$foo</varname> のプロパティ名として使います。
|
|
<varname>$bar</varname> が配列へのアクセスであっても同じです。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
波括弧を使って、プロパティ名の区切りを明確にすることもできます。
|
|
これが特に有用なのは、配列が格納されているプロパティにアクセスするときや
|
|
プロパティ名が複数のパーツからなる場合、
|
|
あるいはプロパティ名として無効な文字を含む場合
|
|
(たとえば <function>json_decode</function>
|
|
や <link linkend="book.simplexml">SimpleXML</link> に由来するプロパティ)
|
|
などです。
|
|
</simpara>
|
|
|
|
<para>
|
|
<example>
|
|
<title>可変プロパティの例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo {
|
|
public $bar = 'I am bar.';
|
|
public $arr = ['I am A.', 'I am B.', 'I am C.'];
|
|
public $r = 'I am r.';
|
|
}
|
|
|
|
$foo = new Foo();
|
|
$bar = 'bar';
|
|
$baz = ['foo', 'bar', 'baz', 'quux'];
|
|
echo $foo->$bar . "\n";
|
|
echo $foo->{$baz[1]} . "\n";
|
|
|
|
$start = 'b';
|
|
$end = 'ar';
|
|
echo $foo->{$start . $end} . "\n";
|
|
|
|
$arr = 'arr';
|
|
echo $foo->{$arr}[1] . "\n";
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
I am bar.
|
|
I am bar.
|
|
I am bar.
|
|
I am r.
|
|
I am B.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<warning>
|
|
<simpara>
|
|
関数やクラスメソッドの内部で、可変変数と PHP の
|
|
<link linkend="language.variables.superglobals">
|
|
スーパーグローバル配列</link> とを組み合わせては使用できないということに注意してください。
|
|
<literal>$this</literal> も特別な変数であり、
|
|
動的に参照することはできません。
|
|
</simpara>
|
|
</warning>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.variables.external">
|
|
<title>外部から来る変数</title>
|
|
|
|
<sect2 xml:id="language.variables.external.form">
|
|
<title>HTML フォーム (GET と POST)</title>
|
|
|
|
<simpara>
|
|
フォームが PHP スクリプトに投稿された時、フォームから渡された全て
|
|
の変数は PHP により自動的にスクリプトから使用可能となります。
|
|
この情報にアクセスする手段は複数あります。例を以下に示します。
|
|
</simpara>
|
|
|
|
<para>
|
|
<example>
|
|
<title>簡単なHTMLフォーム</title>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<form action="foo.php" method="post">
|
|
Name: <input type="text" name="username" /><br />
|
|
Email: <input type="text" name="email" /><br />
|
|
<input type="submit" name="submit" value="Submit me!" />
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
HTML フォームからデータにアクセスする方法は二種類だけしかありません。
|
|
現在使える方法を、以下にまとめます。
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>簡単なPOST HTMLフォームからのデータにアクセスする</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo $_POST['username'];
|
|
echo $_REQUEST['username'];
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
GETフォームを使用した場合も同じですが、かわりに適当な定義済みの
|
|
GET変数を使用するところが異なります。
|
|
GETは、<literal>QUERY_STRING</literal> (URLの'?'の後の情報)にも代入されます。
|
|
例えば、
|
|
<literal>http://www.example.com/test.php?id=3</literal>には、
|
|
<varname>$_GET['id']</varname>によりアクセス可能なGETデータ
|
|
が含まれます。
|
|
<varname>$_REQUEST</varname> も参照ください。
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
変数名のドットやスペースはアンダースコアに変換されます。
|
|
たとえば <literal><input name="a.b" /></literal> は
|
|
<literal>$_REQUEST["a_b"]</literal> となります。
|
|
</para>
|
|
</note>
|
|
|
|
<simpara>
|
|
PHPではフォーム変数のコンテキスト内で配列が使用可能です(<link
|
|
linkend="faq.html">FAQの関連箇所</link>も参照ください)。
|
|
例えば、関連する変数をグループ化したり、select inputで複数の値を
|
|
取得するといったことが可能です。フォームを同じスクリプトに投稿し、
|
|
投稿したデータを表示する例を示します。
|
|
</simpara>
|
|
|
|
<para>
|
|
<example>
|
|
<title>より複雑なフォーム変数</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
if ($_POST) {
|
|
echo '<pre>';
|
|
echo htmlspecialchars(print_r($_POST, true));
|
|
echo '</pre>';
|
|
}
|
|
?>
|
|
<form action="" method="post">
|
|
Name: <input type="text" name="personal[name]" /><br />
|
|
Email: <input type="text" name="personal[email]" /><br />
|
|
Beer: <br />
|
|
<select multiple name="beer[]">
|
|
<option value="warthog">Warthog</option>
|
|
<option value="guinness">Guinness</option>
|
|
<option value="stuttgarter">Stuttgarter Schwabenbrau</option>
|
|
</select><br />
|
|
<input type="submit" value="submit me!" />
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
外部の変数の名前が、正しい配列の文法で始まっていた場合、
|
|
後に続く文字は黙って無視されます。
|
|
たとえば、<literal><input name="foo[bar]baz"></literal>
|
|
は <literal>$_REQUEST['foo']['bar']</literal> になります。
|
|
</simpara>
|
|
</note>
|
|
|
|
<sect3 xml:id="language.variables.external.form.submit">
|
|
<title>IMAGE SUBMIT 変数名</title>
|
|
|
|
<simpara>
|
|
フォームを投稿する際、次のタグのように標準の投稿ボタンの代わりに
|
|
画像を使用することができます。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<input type="image" src="image.gif" name="sub" />
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
画像のどこかがクリックされた場合、二つの変数 <varname>sub_x</varname> および <varname>sub_y</varname>
|
|
が付け加えられてこのフォームはサーバーに転送されます。これらの変
|
|
数は、ユーザーがこの画像をクリックした座標を示しています。経験の
|
|
ある人は、ブラウザにより送られた変数の名前においてアンダースコア
|
|
がピリオドになってしまっていることを心配するかもしれません。
|
|
しかし、PHP はピリオドをアンダースコアに自動的に変換します。
|
|
</simpara>
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.external.cookies">
|
|
<title>HTTP Cookie</title>
|
|
|
|
<simpara>
|
|
PHP は、<link xlink:href="&url.rfc;6265">RFC 6265</link>
|
|
に定義されたHTTP Cookieを完全にサポートします。Cookieは、リモート
|
|
ブラウザにデータを保持し、再訪するユーザーを追跡し、特定する機構
|
|
です。<function>setcookie</function> 関数によりCookieをセットす
|
|
ることができます。Cookieは、HTTP ヘッダの一部なので、SetCookie
|
|
関数をブラウザに何かを出力する前にコールする必要があります。
|
|
この制約は、<function>header</function> 関数のものと同じです。
|
|
Cookieのデータは、<varname>$_COOKIE</varname> のような適当なCookieデータ
|
|
配列で参照可能です。また、 <varname>$_REQUEST</varname>でも
|
|
参照可能です。詳細および例については、
|
|
<function>setcookie</function>のマニュアルページを参照ください。
|
|
</simpara>
|
|
|
|
<note>
|
|
<simpara>
|
|
セキュリティ上の理由により、
|
|
PHP 7.2.34, 7.3.23, 7.4.11 以降では、外部から入力される Cookie の <emphasis>名前</emphasis>
|
|
はurlデコードされなくなりました。
|
|
</simpara>
|
|
</note>
|
|
|
|
<simpara>
|
|
単一のCookieに複数の値を代入したい場合は、配列として
|
|
代入することが可能です。以下に例を示します。
|
|
</simpara>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
|
|
setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<simpara>
|
|
上記スクリプトにおいては、2つの異なるCookieを生成されますが、
|
|
この場合、スクリプトでは <varname>MyCookie</varname> という単一の配列になります。
|
|
一つのCookieに複数の値を設定したい場合、最初の値に
|
|
<function>serialize</function>または
|
|
<function>explode</function>を用いることを考えてください。
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Cookieは、パスまたはドメインが異ならない限り、
|
|
以前のクッキーをブラウザ上の同じ名前の変数に置き換えることに
|
|
注意してください。
|
|
さて、買い物かご(Shopping Cart) プログラムの場合、カウンタを保持し、
|
|
受け渡したいと思うかもしれません。
|
|
これは、次のようになります。
|
|
</simpara>
|
|
|
|
<example>
|
|
<title><function>setcookie</function>の例</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
if (isset($_COOKIE['count'])) {
|
|
$count = $_COOKIE['count'] + 1;
|
|
} else {
|
|
$count = 1;
|
|
}
|
|
setcookie('count', $count, time()+3600);
|
|
setcookie("Cart[$count]", $item, time()+3600);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.external.dot-in-names">
|
|
<title>外部変数名のドット</title>
|
|
|
|
<para>
|
|
通常、PHP はスクリプトに渡された変数の名前を変更しません。しかし、
|
|
ドット(ピリオド、終止符)はPHPの変数名で有効な文字ではないというこ
|
|
とに注意する必要があります。次の例を見てみましょう。
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$varname.ext; /* 無効な変数名 */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
ここで、パーサーは、<varname>$varname</varname>という名前の変数の後に
|
|
文字列結合演算子があり、その後に、裸の文字列(すなわち、既知のキー
|
|
または予約語にマッチしない引用符無しの文字列) 'ext' が続くとして
|
|
解釈します。この場合、明らかに意図する結果にはなりません。
|
|
</para>
|
|
|
|
<para>
|
|
重要なことを記述しておくと、このため、外部変数に含まれるドットを
|
|
PHP は自動的にアンダースコアに変換します。
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.determining-type-of">
|
|
<title>変数の型の定義</title>
|
|
|
|
<para>
|
|
PHPは、変数の型を定義し、必要に応じて変換します。このため、ある変
|
|
数の型がある時点で常に明らかであるわけではありません。PHPは、変数
|
|
の型を調べる複数の関数をサポートしています。それらは、
|
|
<function>gettype</function>, <function>is_array</function>,
|
|
<function>is_float</function>, <function>is_int</function>,
|
|
<function>is_object</function>,
|
|
<function>is_string</function> です。
|
|
<link linkend="language.types">型</link>の章も参照ください。
|
|
</para>
|
|
|
|
<para>
|
|
HTTP はテキストプロトコルなので、
|
|
<varname>$_POST</varname> および <varname>$_GET</varname>
|
|
のような
|
|
<link linkend="language.variables.superglobals">スーパーグローバル配列</link>
|
|
に入ってくる内容は、全てとは言えないまでも、ほとんどは文字列のままです。
|
|
PHP は決して値を特定の型に変換したりはしません。
|
|
以下の例では、<varname>$_GET["var1"]</varname>
|
|
は "null" という文字列を含みますし、
|
|
<varname>$_GET["var2"]</varname> は、文字列 "123" を含みます。
|
|
<programlisting>
|
|
<![CDATA[
|
|
/index.php?var1=null&var2=123
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.variables.external.changelog">
|
|
&reftitle.changelog;
|
|
|
|
<para>
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>7.2.34, 7.3.23, 7.4.11</entry>
|
|
<entry>
|
|
セキュリティ上の理由により、外部から入力される Cookie の
|
|
<emphasis>名前</emphasis> はurlデコードされなくなりました。
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|