Posts 2.変数
Post
Cancel

2.変数

PHP基本

基本のき

まずは、PHPというものを勉強すると言っても、プログラムの言葉ってほとんど外国語みたいなもので、詳細は後で勉強すると言っても多少は知っていないと話がちんぷんかんぷんになってしまいそうなので、ちょっぴりさわりを勉強しておきましょう、本格的に勉強する前に。

基本用語

業界的にはよく使っているのだけれど、たいていの方には何のことやらわからない、というようなことはどこの世界でもあります。ここでは、少しばかりその辺の用語をピックアップして、簡単な説明をします(極簡単にですw)。

  1. ターミナル ターミナルとかシェルとか言いますが、Windowsだったら「コマンドプロンプト」です。これらに共通しているのは、黒っぽい(カスタマイズできるものもあるので色が違うものもあります)画面にプロンプトがあって、プログラム名を入力して改行コードを打つと、そのプログラムが実行される、というものです。今から25年以上前はWindows3.1がまだ発売されていない頃は、むしろその黒い画面がメジャーでした。次の図はWindowsのコマンドプロンプトです。 コマンドプロンプト
    また、下はLinux(Ubuntu)のターミナルです。 Ubuntuのターミナル
    また、下はMacのターミナルです。 Macのターミナル この画面でPHPのプログラムを実行させることができるので、ちょっと確認したいときには便利です。
  2. 標準出力 そもそもで言うと、OSのUnixで動くプログラムは標準出力への書き込みを要求して、それがディスプレイ上に実行結果として表示していました(ターミナルしかない時代です!)。 ただ、もう少し簡単に言ってしまえば、1のターミナル上でPHPのプログラムを実行して、その中で「echoとかprint」で出力した文字列はターミナル上に現れて、これを標準出力って言う、という感じで覚えていればOKでしょう。 ただ、httpdサーバーであるApache上で動いているPHPのプログラムを実行して、標準出力すると、ブラウザーに文字列として送られてきて、それが表示され、これも標準出力です。
  3. Apache 「ブラウザでURLを叩いてページを閲覧する」という作業はHTTPプロトコルというルールに則って、通信しています。そして、閲覧側(ブラウザー側)と通信しているのが、サーバー側にあるHTTPDというプログラムで(HTTPサーバーとかHTTPデーモンとかいろんな言い方をします)、具体的なそのプログラムの名前がApache(アパッチ)です。HTTPサーバーには他にも色々あるのですが、このApacheが一番有名なものですし、だいぶ昔から活躍しているものです。
  4. データベース データベースは、様々な情報を保存したり、保存されている情報を検索したりするソフトウェアを、たいていは、指します。Oracle、MySQL、PostgreSQL等が有名なデータベースのアプリケーション(いずれもリレーショナルデータベース)で、最近はMemcahceやCassandora等、MongoDB、Redisのような「NoSQL」という種類のデータベースも利用されるようになってきている。
  5. 文字化け 以前のように「プログラミングの何分の1かは文字化けとの戦い」ということはなくなりつつありますが、それでも皆無になったわけじゃありません。これはWindowsがShift_JISという文字コードでLinuxが以前はEUC、最近はUTF-8というように、文字コードが違っているのが1点。それから、アルファベット(アルファベットだけだと文字コードは関係がない)しかない国の人が開発したプログラムを利用しようとすると、作者が文字コードについて無頓着な場合どうしても文字化けが起こってしまうというのが2点目です。日本語を扱う(普通はそうですがw)ようなプログラムを書いたり、データベースに日本語が混ざっている文字を登録する際は文字コード(単にエンコードと言ったりもする)は意識する必要がありそうです。
  6. SSH 以前セキュリティ等をほとんど気にしていなかった時代はtelnetというものを利用して、遠隔にある(リモートの)サーバーにログインしていましたが、昨今、その時のデータを盗み見されたり、改竄されたりする危険があるので、通信データを暗号化して作業ができるようにしたりする「ネットワークを介して別のコンピュータにログインして操作するためのソフトウェアの一つ」です(セキュアシェルの略)。
  7. TCP/IP インターネットで標準的に用いられる通信プロトコル(通信手順)で、TCPとIPを組み合わせたもので、インターネット標準のプロトコル群全体の総称を表すこともあるつまり、インターネットにおいてデータをやりとりをしている時の仕組みのことです。
  8. IPアドレス前項の仕組みの中で、インターネットにアクセスしているコンピュータ(ユーザー側の)やアクセスしている対象のコンピュータ(例えばGoogleが管理しているコンピューター群)の住所です。現在はIPv4という前から使われているものとIPv6が同時運用している感じですが(IPアドレスが枯渇するという懸念から新しいIPv6が生み出されました)、まだまだ身近なのは全社のIPv4です。 これは0~255までの数字を4つに句切って表します。例えば「192.168.0.1」のような感じです。

変数

変数とはなにかしらのを入れておく入れ物です。PHPでは型宣言をする必要がありません。つまり、JavaやC言語等のように整数を入れるものは「整数を入れる変数だよ」と宣言する必要があるのですが、PHPでは何でも宣言なしに値を入れられます。ただ変数には$(ドルマーク)を最初に付ける必要があるというルールがあります。

>
1
2
3
$i = 1;
$i = "a"
$i = 0.01;

こんな風に後から種類の違うものを入れることができます。

ただ、このような使い方はしない方が無難です。

ビルトイン関数、言語構造、関数定義

プログラム言語には「関数」とか「メソッド」とかいうものがあって、微妙に区別するのですが、そのためにはオブジェクト指向やクラスというものを知らないとわからないので、ここではほぼ同じものとしておきましょう(違いに大きな意味もないので)。

関数とは【function】 - 意味/解説/説明/定義 : IT用語辞典

1
引数と呼ばれるデータを受け取り、定められた通りの処理を実行して結果を返す一連の命令群。多くのプログラミング言語では、関数がプログラムを構成する要素となっている。多くの言語や処理系では、開発者の負担を軽減するため、よく使う機能が関数としてあらかじめ用意されている。

具体的に見てみましょう。上記の引用の「よく使う機能が関数としてあらかじめ用意されている」というのがPHPではビルトイン関数(組み込み関数とか言う場合も)にあたります。次の例は、あるテキストを受けとった関数がHTMLエンコーディングしたもの(htmlspecialchars)、文字の最初と最後のスペースを取り除いたもの(trim)、文字列の一部を取り出したもの(substr)を返します。

>
1
2
3
echo htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES) , PHP_EOL;
echo trim("     Chiku    is an old man!     ") . PHP_EOL;
echo substr('abcdef', 1, 3) . PHP_EOL;

実行すると以下のように出力されます。

>F:\PhpstormProjects\test_php>php variable04.php &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt; Chiku is an old man! bcd

少し補足します(関数名のリンクはPHPのマニュアルの内容を表示させます)。

  1. 1行目のhtmlspecialcharsという関数は、文字列を引数にして、htmlとして意味を持つものをエスケープしてその文字が表示されるようにするものです。例えば、htmlのファイル内に「$i < 10」と書き込み、そのように表示させたいとしても、このままではブラウザーはそのようには表示してはくれません。何故なら「<」がタグの始まりを意味するものですからです。そこで「<」は「&lt;」と書き込まなければならないのですが、この関数はそういう変換をしてくれるものです。PHPはWEBアプリとしてよく利用されているので、お目にかかる機会も多いでしょう。
  2. 2行目のtrimという関数は、文字列の最初と最後のスペースやタブを取り除いてくれるものです(途中の空白は取り除きません)。
  3. 3行目のsubstrという関数は文字列から、一部の文字列を取り出すのに利用されます。これは第1引数の文字列、「第2引数の数字に1を足した数」番目から「第3引数の数」文だけの文字を取り出します。

さて、標準出力させるechoも、同様の関数のようですが、実は違います。PHPのマニュアルでも、関数の一覧の中にしっかりechoがありますが、そのマニュアルに

1
echo は実際には関数ではありません (言語構造です)。このため、使用する際に括弧は必要ありません。 (いくつかの他の言語構造と異なり) echo は関数のように動作しません。そのため、 関数のコンテキスト中では常に使用することができません。 加えて、複数のパラメータを指定して echo をコールしたい場合、括弧の中にパラメータを記述してはいけません。

とあり、echoは言語構造だそうです。ただ、関数のように「括弧()」がいらないという以外は当面あまり関係がないので、それだけでも覚えておきましょう。このecho以外に次のようなものが言語構造です。

返り値の型名前機能
なしecho文字列を出力
intprint文字列を出力
arrayarray配列を生成
arraylist配列の形式で、変数に値を代入
mixedeval文字列をPHPコードとして評価
なしunset変数を破棄する
boolisset変数がセットされているか調べる
boolempty変数が空かどうか調べる
なしexitスクリプトの実行を終了
なしdieexitと同等
mixedincludeファイルを読み込む
mixedrequireファイルを読み込む(読み込めないと停止)

次に、このようなビルトイン関数だけじゃなく、自分でも関数を定義できます。例えば次のようなものです。

>
1
2
3
4
5
6
7
8
9
10
11
<?php
function tasizan($num)
{
    $ans = 0;
    for ($i = 1; $i <= $num; $i++) {
        $ans += $i;
    }
    return $ans;
}

echo bikkuri(10), PHP_EOL;

上のコードの2行目から9行目までがfunc関数の定義になります。詳細はいずれということになりますが、functionという文字列で始めて、括弧の中に引数(仮引数)を書き、その引数を「うんたら」して、値を返しています。実際には1~10まで足した答えを返し、echoで出力しています。

関数定義の例

簡単に説明します。

  1. 11行目のechoを実行しようするのですが、その引数がtasizanなので、PHPは定義してあるtasizan関数を実行します。
  2. bikkuri関数の実引数は10が与えらています(11行目)
  3. bikkuri関数の仮引数で10を受けとります(2行目)
  4. $ansに0を代入します
  5. for文(ループ)が始まり
  6. for文の{}の間を繰り返します
  7. $iに最初1を入れる
  8. $ansに$iの値の1を加える($ansは1) ※($ans += 1$ans = $ans + 1と同じ)
  9. $iに1を加え($iは2)
  10. $iが仮引数の$num(実際には10)以下の場合繰り返します
  11. 8と9と10を繰り返す
  12. $iが11になったら、for文を抜けて、$ansの値が返されます

プログラムの実行順

プログラムには同期非同期という考え方があります。PHPの場合多くがこの同期です。いずれ非同期も学習する必要があるでしょうが、ここでは同期について触れます。

同期とは、プログラムは上から順番にプログラムを実行していくというもので、非常に単純です。

PHPの実行順序

変数

変数の基本

PHPの変数にはドルマーク($)を先頭に必ず付ける必要があります。これはPerlと似たような仕様ですが、他の言語ではあまり見られない仕様かもしれません。大文字と小文字は別の変数となります。またそのドルマークの次の単語は数字ではダメです($2_var等)。

>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
$var = 1;
$Var = "string";
$var2 = 2.1;
$var_3 = null;
$var_4;
// $5varはダメ

echo $var . PHP_EOL;
echo $Var . PHP_EOL;
echo $var2 . PHP_EOL;
echo $var_3 . PHP_EOL;
echo $var_4 , PHP_EOL;

echo "=====ここからvar_dump\n";

var_dump($var);
var_dump($Var);
var_dump($var2);
var_dump($var_3);
var_dump($var_4);

echo "====isset\n";

echo var_dump(isset($var2));
echo var_dump(isset($var_3));
echo var_dump(isset($var_4));

出力は以下のようです。

>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
php variable01.php
1
string
2.1


Notice: Undefined variable: var_4 in F:\PhpstormProjects\test_php\variable01.php on line 13

=====ここからvar_dump
int(1)
string(6) "string"
float(2.1)
NULL

Notice: Undefined variable: var_4 in F:\PhpstormProjects\test_php\variable01.php on line 21
NULL
====isset
bool(true)  // (isset($var2)→2.1
bool(false) // isset($var_3)→NULLを代入
bool(false) // isset($var_4)→初期化していない

若干コードの補足をします。

  1. PHPは1行の最後に「;(セミコロン)」が必要です。
  2. 「echo」関数は、標準出力するものです。
  3. 9行目の「$var . PHP_EOL」の「.(ピリオド)」は、文字列と文字列を連結するものです。ここでは変数の中身とPHP_EOL(改行コード)を連結しています。
  4. 13行目の「echo $var_4, PHP_EOL;」の「,(コンマ)」は前項のピリオドと違い文字列を連結しているのではなく、echoがコンマで句切られてた複数の引数を取ることができ、それでそれら2つが出力されるので、結局2と同じ結果になります(3の方が若干時間がかかる—といっても極めて短い差ですが—数が多いと問題になる場合も)。
  5. 「PHP_EOL」は実行しているOSにおける改行コードで、標準出力内のその「PHP_EOL」のところでで改行されます。
    Windowsでは改行コードが「**\r\n**」、Macでは以前は「**\r**」で最近のOSXは「**\n**」、Linuxでは「**\n**」です。
  6. 「var_dump」は、1の「echo」と同様標準出力しますが、型などの付加情報も出力します。 例:「string(6) “string”」→変数の中身がstring(文字)が6つの「string」という意味
  7. issetは「その変数に値がセットされているかどうかを判定する」もので、値が代入されていると(NULL以外)falseを返し、そうでないとtrueを返します。
  8. 「$var = null;」のように、とりあえず最初に初期値を代入することを「初期化」と言うことがあります。


これらから、次のようなことがわかります。

  1. PHPの変数は「型(文字や整数等)」にかかわらず代入することができます。
  2. echoで出力したものは、基本、文字列なのですが、数字なども自動で文字列に変換されています。
  3. 代入していない変数を出力させようとしている出力されたものの7行目、15行目でNoticeをPHPが出力していますが、これは「注意!」というニュアンスのもので、「値も入っていない奴を出力するのはダメじゃない?」とPHPがダメ出しをしている感じです。ただ、そのすぐあとにNULLが出力されています。これは詳しくはhttp://www.cpa-lab.com/tech/097あたりを読んでもらうとして、簡単に言うと、PHPは一度も代入が行われていないものを変数として認識しておらず(シンボルテーブルに登録されていない)、とりあえずNULLとして取り扱うよ、ということらしく「わかってる?注意してね」と警告しているのです。
  4. そもそもNULLとは「値がない」という値で、ちょっと矛盾した表現になっています、「値がないという値がある」わけなので。だから明示的に「$var_3 = null;」のように代入することができ、明示的にNULLを代入しているものに関してはNoticeをPHPは出していません(上でも述べたように変数を初期化することにより、シンボルテープルに登録されるからです)。
  5. 18行目だけは2.1という値を代入しているのでtrueになっており、NULLを代入したものも、何も代入していないものも、「Noticeが出る・出ないの違い」はあるものの、issetの判定ではどちらも「false」が返ってきます。

変数のスコープ

変数のスコープとは、その変数を参照できる範囲みたいなものです(逆に言えば、どんな変数でもどこからでも参照できるものじゃない、ということになります)。

PHPには、ローカルスコープとグローバルスコープしかありません。ブロックスコープがあるJavaなんかとは違い、実に単純です。

基本はfunctionやClassの中のローカル環境では、通常、その外側から参照したりすることができません(関数やクラスの話はいずれw)。

下のソースを見てください。ここにはfuncという関数がありますが、それ以外はグローバルスコープです。言い換えれば、関数内は特別で、この関数の中の変数は外から参照できないし、外へ影響を与えることができません(厳密に言えば、できますが、とりあえずそれはおいておきましょう)。

>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
// 関数
function func(){
  // ローカル内の変数$var
  $var = "Miyazaki Hayao";
  //  ローカル内で初期化していない$var2を出力(Noticeで警告---1回目)
  echo $var2.PHP_EOL;
}

// グローバルの$var
$var = "Chiku Kazuro";

// グローバルの$varを参照していて、$varには「Chiku Kazuro」が入っているのでif内に
if($var == "Chiku Kazuro"){
  // 2回目の出力
  echo $var.PHP_EOL;
  // グローバルの$var2を初期化
  $var2 = "Denpoya Chiyoharu";
}

// $var2が出力される(出力3回目)
echo  $var2.PHP_EOL;

// 最後に関数funcを実行。
func();
echo $var, PHP_EOL;

これをコマンドラインで実行しますと、次のような出力があります。

>
1
2
3
4
5
6
7
c:\work>php var02.php
Chiku Kazuro
Denpoya Chiyoharu

Notice: Undefined variable: var2 in F:\work\variable03.php on line 7

Chiku Kazuro

これで2回目登場の「Notice: Undefined variable: var2」が出力されています。

これは、上のソースの関数funcは最後の25行目で実行され、7行目の「 echo $var2.PHP_EOL;」が実行されます。そして、その前のif文の中で一度$var2に値が代入されているのですが、関数の中の「$var2」は先の関数の外側の$var2とは別物なので、PHPが「そんな変数知らないよ」というNoticeが出力されたと言うことになります。

下の図のように、function内とグローバル内で、変数的には独立して扱われる、という感じです。

グローバルスコープとローカルスコープ

さて、逆から言えば、グローバルスコープ内ならどこからでも参照できることになりますが、これはこれで結構危ういものなんです。

上記のような短いプログラムでは大丈夫でしょうが、1万行を超えるような(1つのファイルということじゃなく、いずれ触れるincludeやrequire_onceというようなものを使ったものも含めて)ソースだと、その中にどんな変数が使われているか全て頭に入れながらプログラムしていくのは厳しいと思います。

そうなってくると、予期せず、あとから変数を上書きしてしまう、という危険性をはらんでいるということです。

例えば、次のような(極端な)コードで、読み込んでいるfile03.phpで$filenameという変数を使っていて、12行目でその変数の値を書き換えて、さらに、file04でもそれを利用しているとしたら、上書きしたことによって何が起こるか予想が付きません。つまり、何も起きないかもしれませんが、変なことがあるかもしれません。

これは少し極端で、そもそもこんなコードを書くこと自体がダメじゃん、と言うこともできますが、いずれにしろ、なかなか何が悪いのかつかみづらいバグが入り込む可能性があり少なくともグローバルスコープの変数や関数名の命名は常に気をつけた方が良い、ということは言えるでしょう

><?php require_once "file01.php"; // ←1000行の関数群 require_once "file02.php"; // ←2000行の関数群 include "file03.php"; // ←3000行の実行ファイル // ・・・・ここに2000行ほどある for(j = 0; j < 20; j++) { // ........ for(k = 0; k < 1000; k++) { // ........ $filename = "file_" + k; // ........ } } include "file04.php"; // ←1000行の実行ファイル

globalキーワード

globalキーワードとはローカルスコープでも、グローバルスコープの変数を参照することができるようにするものです。

下のコードを見てください。

>
1
2
3
4
5
6
7
8
9
10
11
12
<?php
function func()
{
    echo $var1;
    global $var1;
    echo $var1;
    echo $var2;
}

$var1 = 1;
$var2 = 100;
func();

出力は次のようです。

>
1
2
3
4
F:\PhpstormProjects\test_php>php variable02.php
Notice: Undefined variable: var1 in F:\work\variable02.php on line 4
1
Notice: Undefined variable: var2 in F:\work\variable02.php on line 7

簡単に説明します。

  1. echoした際にNoticeが出ていないのは、唯一6行目のものだけで、1が出力されています。 これは5行目でglobal $var1とし、「$var1はグローバルのを指すことにするよ」とPHPに言っていて、グローバルでは10行目で$var1に1を代入しているので、Noticeが出ずに、1が出力されているわけです。
  2. 4行目と7行目でNoticeが出ているのは、4行目はglobal宣言する前なので$var1が初期化されていない(1度も値が代入されていない)状態だからで、7行目はglobal宣言自体されておらず、関数内でも初期化がされていないからです。

スーパーグローバル変数

PHPには、あらゆるスコープからも参照できるスーパーグローバル変数というものがあります。

スーパーグローバル変数には次のようなものがあります。これらは全て連想配列として定義されており、PHPが自動で設定してくれるもので、特に$_POST$_GETは、今後よくお目にかかることになろうかと思います。

変数名意味
$GLOBALS(グローバル変数)グローバルスコープで使用可能なすべての変数への参照
$_SERVER(サーバー変数)サーバ情報および実行時の環境情報
$_GET(ゲット変数)HTTP GET 変数
$_POST(ポスト変数)HTTP POST 変数
$_FILES(ファイル変数)HTTP ファイルアップロード変数
$_REQUEST(リクエスト変数)HTTP リクエスト変数
$_SESSION(セッション変数)セッション変数
$_ENV(環境変数)環境変数
$_COOKIE(クッキー変数)HTTP クッキー
シェア
#内容発言者

1. LAMPのインストール

roo - Excelファイルの読み込み