PHP-log
はじめに
phpが売りの会社に入るかもしれないので、1からphpを学んでみる。
目標地点
phpの公式ドキュメントを一通りみて、基本的な仕組みと便利そうな関数とかを理解する
環境情報(適宜追加)
OS:Windows 10
PHP:version 8.2
基本的な構文
PHPタグ 開始タグと終了タグ
PHPは開始タグ<?php
と終了タグ?>
を探してこの中のコードを実行する。
<?php
...
?>
※短縮形の書き方もあるが省略(公式もできる限り<?php ... ?>
を使えといっている。
ファイルがphpコードだけで構成されている場合は開始タグ<?php
だけのほうがいいらしい。
理由は終了タグ?>
のあとに改行や空白があると出力バッファリング?というものが動いて意図せずその時点の内容を出力してしまうことがあるらしい。
// Laravelのファイルが<?php
しか書かれてなかったのはこれかあ。
HTMLからの脱出
PHPのパーサは開始タグ<?php
終了タグ?>
に囲まれていない部分は無視する。
なので、HTMLの中にPHPコードを埋め込むことができる。
<p> ここはPHPは無視。ブラウザに表示されるよ</p>
<?php echo 'ここはPHPにパースされる' ?>
<p> ここもPHPは無視。ブラウザに表示されるよ</p>
でも条件式(if)を使うとHTMLタグをスキップしたりできる。
<?php if($hoge== true) ?>
条件がtrueなら表示されるよ
<?php else: ?>
条件がfalseなら表示されるよ
<?php end if; ?>
命令の分離
PHPではステートメントの区切りにセミコロン;
が必要。でも終了タグ?>
の直前には不要。
PHPコードだけのファイルには終了タグ?>
はないこともあるので、基本的にはつけたほうがよさそう。
<?php echo "Hello!"; ?> // -> Hello!
<?="Hello!" ?> // -> Hello!
//<?=は <php echo の省略形
コメント
PHPは3種類のコメントの書き方をサポートしてる。
<?php
// 単一行コメント
/*
複数行コメント
ここもコメントにできる
*/
# これも単一行コメント
?>
複数行コメントを入れ子にしようとするとおかしくなるので注意
<?php
/*
echo 'テストです'; /* このコメントが問題を生じます */
*/
?>
型
はじめに
PHPには以下の組み込み型がある。
- null
- bool
- int
- float
- string
- array
- object
- callable
- resource
PHPは動的型付言語なので、変数の宣言時に書かなくてもいい。(もちろん書くこともできる)
型と値を調べたいときはvar_dump()
を使うと表示される。
型システム
PHPは部分型の関係を満たしつつ名前ベースで一致を調べる型システムを採用している。
//部分型?🤔
部分型はコンパイル時にチェックされる。型の検証は実行時に動的に行われる。
基本型
- 組み込み型
- ヌル(null)
- スカラー型
- 論理値(bool)
- 整数(int)
- 浮動小数点数(float)
- 文字列(string)
- 配列(array)
- オブジェクト
- リソース
- never
- void
- クラス内での関係を表す相対型:self,parent,static
- リテラル型
- false
- true
- ユーザ定義型(クラス型という)
- インターフェース
- クラス
- 列挙型(enum)
- callable
複合型
単一の型を組み合わせて、複合型を作ることができる。
交差型(intersection?)
インターフェースの型チェックに使うことができる。
たとえば、引数に* インターフェースAとインターフェースB *を実装したクラスだけ受け取りたい…という定義をするには↓みたいにかける。
<?php
interface A;
interface B;
function test(A&B $class){
…
}
union型
union型は、いずれかの型を受け入れる型を定義する。(日本語でおk)
<?php
float A;
array B;
function test(A|B $test){
...
}
この場合、test関数の引数にはfloatもarrayも渡せるようになる。
型のエイリアス
mixed という型のエイリアスがある。
これは「union 型 object|resource|array|string|float|int|bool|null 」すべてを受け入れるという型。
iterable
「Traversable|array」2つの型を受け入れる型。
Traversableとarrayについては以下参照か、別の章で出てきそう。
うーん、ここらへんの型宣言はちょっといぶし銀すぎる🤔
NULL
null(ヌル)は「なんの情報も持っていないこと」を示す。
未定義の変数や、unset()
されたものはnull
になる。
// unset()は変数の割当を解除する関数
文法
nullは大文字小文字を区別しない。
// 個人的には小文字が好き。Nullとかはどうなるんだ?
<?php
$var = null;
$var = NULL;
?>
### 関数
is_null($hoge): $hogeがnullか調べる関数
unset($hoge):$hogeの割当を解除してnullにする関数
論理型(boolean)
bool型は true , false の2つの値を持つ。必ずこのどちらかしかできない。
文法
bool型にセットするとき大文字小文字は区別しない。
<?php
$foo = true;
>
booleanへの変換
boolに明示的に変換するときはキャスト(bool)
を使う。
論理型が必要な場合は自動的にboolになるので一般的には不要らしい…。
以下の値をbool型にキャストする場合、すべてfalse
とみなされる。
- boolean の false
- integer の 0 (ゼロ)
- float の 0.0 および -0.0 (ゼロ)
- 空の文字列 ""、 および文字列の "0"
- 要素の数がゼロである 配列
- unit 型 NULL (値がセットされていない変数を含む)
- bool 型へキャストするように動作がオーバーロードされた内部オブジェクト。 例: 属性がない空要素から作 成された SimpleXML オブジェクト。
// boolへのキャストはあんまり使わないほうがよさそう。どっちかっていうと、意図せず↑になっちゃってバグになるとかのほうがありそうな…。
整数
int は、ℤ = {..., -2, -1, 0, 1, 2, ...} という集合です。
ℤ = {..., -2, -1, 0, 1, 2, ...}について
🤔:?
🤖:整数(int)とは、0を中心に左右に無限に続く数字の集まりです。マイナスの数を含めることができるので、-2、-1、0、1、2、...という数がこの集まりに含まれます。数直線で表すと、中心に0があって、右に行くほど大きな数になり、左に行くほど小さな数になります。例えば、2という数は0から2つ右に進みますし、-3という数は0から3つ左に進みます。
🤔:Zってどういう意味?
🤖:"Z"というのは、ドイツ語の "Zahlen" (数) から来ており、整数の集合を表す数学用語の一つです。整数は、自然数や負の整数を含む数の集合であり、Zはそのような数の集合を表すためによく使われます。例えば、Zの中には、-2、-1、0、1、2などが含まれます。また、Zは整数の集合を表すときに、大文字で表記されることが多いです。
文法
int型は10進数、8進数、16進数、2進数の値を格納することができる。
$a = 1234; // 10進数
$a = 0123; // 8進数
$a = 0o123; // 8進数(8.1.0以降)
$a = 0x1A; // 16進数
$a= 0b11111111; // 2進数
$a = 1_234_567; // 10進数
整数のオーバーフロー
int型の範囲外を指定すると、floatとして解釈される。
32bit OSのオーバーフロー
<?php
$large_number = 2147483647;
var_dump($large_number); // int(2147483647)
$large_number = 2147483648;
var_dump($large_number); // float(2147483648)
$million = 1000000;
$large_number = 50000 * $million;
var_dump($large_number); // float(50000000000)
?>
64bit OSのオーバーフロー
<?php
$large_number = 9223372036854775807;
var_dump($large_number); // int(9223372036854775807)
$large_number = 9223372036854775808;
var_dump($large_number); // float(9.2233720368548E+18)
$million = 1000000;
$large_number = 50000000000000 * $million;
var_dump($large_number); // float(5.0E+19)
?>
// 環境によって許容値が異なる~~!🙄
除算
整数の割り算をそのまま行うことはできない(float型になるため)
整数の割り算をするならintdiv()
を使う。
他の型からの変換
bool false -> 0、true ->1
float:小数点が丸められる。PHP8.1以降では精度が落ちると警告が表示される。
string: 文字列が数値形式の場合は対応する整数になる。そうでない場合は0になる。
null: 常に0になる
その他:未定義。現在は論理値に変換されたときに同じだが、動作が保証されないので使ってはいけない。
浮動小数点数
文法
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // PHP 7.4.0以降
floatへの変換
string:文字列が数値型文字列の場合は、対応するfloatに変換される。そうでない場合は0になる。
他の型:先にintに変換してからfloatに変換される。
floatの比較
floatの比較は色々むずかしいらしい。
ここがわかりやすかった。
とりあえずfloatの比較をするときは注意する!ってのは忘れないようにしたい。
NaN
浮動小数点演算の結果が、未定義のものや表現不可能な値になったとき、NaNと表示される。
NaNは何と比較してもfalseになる。
(NaNになった変数とNaNになった変数を比較するとさすがにtrueになる)
文字列
文字が連結されたもの。
文字は1バイトなので256種類の文字しか扱えない(?)
これはPHPはUnicodeをネイティブサポートしていないためらしい。
what?🤔
🤖:この文章は、PHPがネイティブにUnicodeをサポートしていないということを伝えています。Unicodeは、世界中の多くの言語で使用される文字の標準化された集合を表すための規格であり、それぞれの文字に対して固有の符号を割り当てることができます。ただし、PHPでは、文字を1バイトで表現するため、256個の異なる文字しかサポートしていないため、Unicodeのすべての文字を表現することができません。Unicodeをサポートするためには、UTF-8などのUnicodeエンコーディングを使用する必要があります。
文字の上限
32bit環境だと文字列の最大長は2GB(2147483647バイト)。
64bit環境かつPHP7.0以降なら制限はない。
構文
文字列は4つの方法で定義できる。
引用符(')
引用符で文字列をくくると、ほとんどのエスケープは使えなくなる。
シングルクォートを表すための\'
と バックスラッシュを表す\\
だけ使える。
$str = 'this is a pen!';
二重引用符(")
二重引用符で文字列をくくると、エスケープを解釈するようになる。
$str = "this is a pen!";
使えるエスケープは以下の通り。
記述 | 説明 |
---|---|
\n | ラインフィールド(LF) 改行(Linux) |
\r | キャリッジリターン(CR) 改行(Mac) |
\t | 水平タブ (tab文字) |
\v | 垂直タブ |
\e | エスケープ(ESC) |
\f | フォームフィールド(FF) |
\ | バックスラッシュ |
$ | ドル記号 |
" | 二重引用符 |
[0-7]{1,3} | 正規表現にマッチする文字シーケンスは、8 進数表記の 1 文字です。 1 バイトに収まらない部分は、何もメッセージを出さずにオーバーフローします (そのため、"\400" === "\000" となります)。 |
\x[0-9A-Fa-f]{1,2} | 正規表現にマッチする文字シーケンスは、16 進数表記の 1 文字です。 |
\u{[0-9A-Fa-f]+} | 正規表現にマッチする文字シーケンスは、Unicode のコードポイントです。 そのコードポイントの UTF-8 表現を文字列として出力します。 |
ヒアドキュメント
<<<{id}{改行}…{改行}{id}という形で書くと複数行の文字列の文章を作ることができる。
文章は二重引用符でくくったときと同じ動きをする。(エスケープや変数展開される)
<<<ID
ここにテキストを書ける
ID;
// PHP7.3ならこういうのも書ける
<<<ID
ここにテキストを書ける
ここにテキストを書ける
ここにテキストを書ける
ここにテキストを書ける
ID;
// こうしたらエラーになる
<<<ID
ここにテキストを書ける
ここにテキストを書ける
ここにテキストを書ける
ここにテキストを書ける
ID;
Nowdoc
<<<'{id}'{改行}…{改行}{id}という形で書くと複数行の文字列の文章を作ることができる。
文章は引用符でくくったときと同じ動きをする。(エスケープされず、変数も展開されない)
<<<'LABEL'
ここにテキストを書ける
LABEL
変数のパース
二重引用符やヒアドキュメントであれば文字列に変数を使うとパースされる。
$hoge = "hello";
echo "$hoge world"; //->hello world!
echo "{$hoge} world!"; //-> hello world!
プロパティの展開もできる。
$juices = array("red","blue","org_color" => "green");
echo "this is {$juices[0]}"; // -> this is red
echo "this is {$juices[1]}"; // -> this is blue
echo "this is {$juices[org_color]}"; // -> this is green;
class human {
public $name = "suzuki";
}
$human = new human();
echo "hi! {$human->name}!" -> hi! suzuki!
複雑な波括弧構文
複雑な式を含めて書くことができる。
$great = 'fantastic';
// 動かないパターン
echo "This is { $great}; // -> エラーになる(変数の前に空白があるため)
// 動く
echo "This is {$great}; // -> This is fantastic
// 動く(クラス内プロパティ)を表示
echo "This square is {$square->width}00 centimeters broad." ;
// 動く(キーの文字列にクォートを使うときは波括弧を使う
echo "This works: {$arr['key']}";
// 動く 配列に添字を指定
echo "This works: {$arr[4][3]}";
// 動かない (fooが変数扱いになるので未定義になる)
echo "This works: {$arr[foo][3]};
// 動く (配列arr のキーfoo の3番目の要素)
echo "This works: ".$arr['foo'][3];
// 動く (オブジェクトobjのプロパティvalueの3番目が持つname)
echo "You can even write {$obj->values[3]->name}";
// 動く ($nameが'value'の場合、{$value}と同値になる)
echo "This is the value of the var named $name: {${$name}}";
// 動く(getNameの戻り値が 'Tanaka' の場合 {$value}>{Tanaka}?
echo "This is the value of the var named by the return value of getName(): {${getName()}}";
// 動かない
echo "This is the return value of getName(): {getName()}";
// 動かない { が\によってエスケープされているため
echo "C:\folder\{$great}.txt"
// 動く
echo "C:\\folder\\{$great}.txt"
文字列内で変数を使ってプロパティにアクセスもできる。
class foo {
var $bar = 'I am bar.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo' , 'bar' , 'baz' , 'quux');
echo "{$foo->$bar}"; // ->I am bar.
echo "{$foo->{$baz[1]}}; // ->I am bar. baz[1]はbarなのでfooのbarにアクセスしてる。
class beers {
const softdrink = 'rootbeer';
public static $ale = 'ipa';
}
$rootbeer = 'A & W';
$ipa = 'Alexander Keith\'s';
// これは動作し、出力は I'd like an A & W となります
echo "I'd like an {${beers::softdrink}}\n";
//-> beers::softdrinkは rootbeer, {$rootbeer}となるので「A & W」が出力される
// これも動作し、出力は I'd like an Alexander Keith's となります
echo "I'd like an {${beers::$ale}}\n";
//-> beers->aleが「ipa」、{$ipa}となるので「Alexander Keith」が出力される
文字列の文字単位でのアクセス
文字列が定義されている変数に対して添字で指定すると任意の文字を取得することができる。
// 文字列の最初の文字を取得します
$str = 'This is a test.';
$first = $str[0]; // ->T
// 文字列の 3 番目の文字を取得します
$third = $str[2]; // ->i
// 文字列の最後の文字を取得します
$str = 'This is still a test.';
$last = $str[strlen($str)-1]; // strlenで文字数を取得、添字は0から始まるので-1して末尾の文字を指す
// 文字列の最後の文字を変更します
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';
文字列への変換
文字列へ変換するには(string)キャストや、strval()関数を使う。
echo
や print
を使うときなどは自動で文字列に変換される。
bool
trueは文字列の"1" 、falseは文字列の""(空文字)になる
//0じゃないんかーい!
数値->文字列
intやfloatはその数字が文字列となる。
浮動小数点数は指数表記になる。
配列
配列を文字列にするとArrayになる。中身を取り出したいときは$arr['foo']という形にする。
object
objectはマジック・メソッド__toString
を使う。
リソース
リソースは"Resourve id #1"という文字列になる。1
は実行中のPHPが勝手に割り振られる。
なので、この番号を前提でコードを書いてはいけない!
// てかリソースってなんや🤔
null
nullは常に空文字になる。
数値形式の文字列
PHPの文字列は int や float と解釈できるときは数値とみなす。
$hoge = 1 + "105.5"; // -> "105.5"をfloatに変換して計算してくれるので 106.5になる。
PHP8.0以降では数値に変換できないとき、エラーとなるようになった。それより前だと、0になる。
// > ver8.0
$hoge = 1 + "my 10"; // -> エラー(PHP8.0以降のみ)
// < ver7.0
$hoge = 1 + "my 10"; // -> 1 ( "my 10"が0として扱われる)
配列
PHPの配列は順番付けされマップ。値をキーに関連付けする。
array(
key => value,
key2 => value2,
key3 => value3,
...
)
構文
$array = array(
"foo" => "bar",
"bar" => "foo", //末尾にカンマはあってもなくてもOK
);
// 短縮形
$array =[
"foo" => "bar",
"bar" => "foo",
];
$array =[
// キーの"8"はintにキャストされるので$array[8]で呼び出す。$array["8"]じゃないので注意
"8" => "bar",
// キー"08"はキャストされないので$array["08"]で呼び出す。
"08" => "foo",
// "8.7"はintにキャストされ小数部分が切り捨てされる。つまり$array[8]で呼ぶ
"8.7" => "foo",
// boolもintになる。 trueは1、falseは0
true => "foo",
// null は空文字のキーになる。 $array[""]
null => "foo",
// arrayやobjectはキーとして使えない。
];
同じキーを指定するとどんどん上書きしていく。
$array = [
1 => "a",
"1" => "b",
1.5 => "c",
true => "d",
];
// 最終的には
$array[1] の中に "d"が格納されている状態になる。
文字列のキーと数値のキーを持つ配列を作ることもできる。
$array = array(
"foo" => "bar",
"bar" => "foo",
100 => -100,
-100 => 100,
);
Keyを省略することも可能。
$array = array("foo", "bar", "hello", "world");
一部だけキー指定もできる。
この指定をすると、
$array = array(
"a",
"b",
6 => "c",
"d",
);
角括弧構文による配列要素へのアクセス
配列の要素にアクセスするときは$array[key]
と書く。
$array = array(
"foo" => "bar",
42 => 24,
"multi" => array(
"dimensional" => array(
"array" => "foo"
)
)
);
$array["foo"] // -> "bar"
$array[42]; // -> 24
$array["multi"]["dimensional"]["array"]; // 配列の入れ子もできる
配列のデリファレンス
デリンファレンス(dereference) 配列や文字列の中身を取り出すこと。
// PHPではリファレンスとは関係ないらしい…えぇ。
function getArray(){
return array(1,2,3);
}
$secondElement = getArray()[1];
角括弧構文で作成/修正
既存の配列を修正することができる。
$arr[key] = 値;
$arr[] = 値; // 非推奨
$arrが未定義またはnull、falseのときは新しく配列を作ってくれる。
$arrが文字列として使われているとき、[]
がn文字目を取得する…という動きになるので注意。//なので非推奨
配列の値削除
unset($arr[5]);
配列を削除
unset($arr);
配列の分解
配列はlist()
を使って分解できる。
$source_array = ['foo', 'bar', 'baz'];
list($foo, $bar, $baz) = $source_array;
[$foo, $bar, $baz] = $source_array; // 省略形
echo $foo; // "foo" を出力します。
echo $bar; // "bar" を出力します。
echo $baz; // "baz" を出力します。
多次元配列をforeachで回しながら分解するのにも使える。
$source_array = [
[1, 'John'],
[2, 'Jane'],
];
foreach ($source_array as [$id, $name]) {
...
}
変数の値を入れ替えたいとき、分解を使うと簡単にできる。
$a = 1;
$b = 2;
[$b , $a ] = [$a, $b];
echo $a; // -> 2
echo $b; // -> 1
$foo[bar]はなぜ動かないのか
本来は$foo['bar']
という形式で記述する必要がある。
しかし$foo[bar]
も動作する。
なぜ動作するのか?
barが未定義の定数として扱われて、'bar'という文字列になるため。
これはPHP7.2.0以降では非推奨となり、E_WARNINGレベルの警告が発生する。
なので基本的には使っちゃだめ。
配列への変換
int,float,string,bool,resourceは(array)にキャストするとarray[0]に変換元の値が格納されている配列が生成される。
$myInt = 10;
$array = (array) $myInt;
pirnt_r($array)
objectの場合は…
<?php
class A {
private $B;
protected $C;
public $D;
function __construct()
{
$this->{1} = null;
}
}
var_export((array) new A());
array (
'' . "\0" . 'A' . "\0" . 'B' => NULL,
'' . "\0" . '*' . "\0" . 'C' => NULL,
'D' => NULL,
1 => NULL,
)
?🤔
配列のアンパック
配列の前に...
をつけると配列の値を展開することができる。(PHP7.4.0以降)
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; // [1,2,3]
$arr3 = [0, ...$arr1]; // [0, 1, 2, 3]
$arr4 = [...$arr1, ...$arr2, 111] // [1, 2, 3, 1,2,3, 111]
オブジェクト
オブジェクトの初期化
オブジェクトを作るときはnewを使う。
<?php
class foo{
function fo_foo(){
echo "foo を実行";
}
}
$bar = new foo;
$bar->foo;
オブジェクトへの変換
オブジェクトがオブジェクトに変換される場合はなにも修正されない。
オブジェクト以外の型をオブジェクトにするときはstdClass
というビルドインクラスのインスタンスが生成される。
<?php
$obj = (object) array('1' => 'foo');
var_dump(isset($obj->{'1'})); // PHP 7.2.0 以降は 'bool(true)' それより前は 'bool(false)'
var_dump(key($obj)); // PHP 7.2.0 以降は 'string(1) "1"' それより前は 'int(1)'
?>
列挙型/ Enum
列挙型の基礎
列挙型は、クラスやクラス定数に対して更に制限を加えたもの。
型を定義して値を限定した集合を定義する。
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
function do_stuff(Suit $s)
{
//...
}
do_stuff(Suit::Spades);
リソース(Resource)
リソースは、ファイルやデータベースなどを保持する特別な型。
色々な種類がある。//多すぎぃ!
リソースへの変換
リソースを他の型に変換することはできない。
リソースの開放
リソースがどこからも参照されなくなると自動的に削除される。
その後、ガーベジコレクタによって開放される。
持続的データベース接続はガベージコレクタによって破棄されない。
Callable
コールバックはcallable
型と呼ばれる。
call_user_func()
,usort()
などの関数は、関数を引数として渡すことができる。
受け渡し
function my_callback_function(){
echo 'hello world';
}
class MyClass{
static function myCallbackMethod(){
echo 'Hello World!';
}
}
// 単純なコールバック
call_user_func('myCallbackMethod');
// staticメソッドコール
call_user_func(array('MyClass', 'myCallbackMethod'));
// オブジェクトメソッドのコール
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));
// staticメソッドコール
call_user_func('MyClass:myCallbackMethod');
// 相対していによるstaticメソッドコール
class A {
public static function who(){
echo "A";
}
}
class B extends A {
public static function who(){
echo "B";
}
}
call_user_func(array('B', 'parent::who')); // A -> PHP8.2.0以降は非推奨
class C {
public function __invoke($name) {
echo 'Hello ', $name, "\n";
}
}
//__invokeというのはこのクラスを関数みたいに呼べるようにする定義
$c = new C();
call_user_func($c , 'PHP!'); // Hello PHP!
クロージャーを使ったコールバック
クロージャー?
🤖クロージャ(closure)とは、他の関数内で定義された無名関数(匿名関数)を指します。クロージャは、その関数の外側の変数(自由変数)にアクセスできるため、変数の値を保持したり、関数を呼び出すたびに変数を再定義する必要がない場合に便利です。
クロージャは、関数を返す高階関数として使われることが多く、PHPの場合、function() { ... }という構文で定義されます。クロージャを使用することで、より柔軟かつ効率的なコードを記述することができます。
$aisatsu = function($val){return $val;};
echo "おはよう、{$aisatsu('太郎')}さん";
// 結果:
// おはよう、太郎さん
クロージャー(無名関数)を$aisatsuに格納する。その後変数を呼ぶような形で呼び出す
Mixed
PHP8.0以降で利用可能な、object|resource|array|string|float|int|bool|nullの型を受け入れる型。
引数に色々な型を受け入れることができる関数の例
function test(mixed $data){
...
}
Void
関数の戻り値がないことを示すための型。
union型には指定することができない。
Never
never は関数が戻ってこないことを示す戻り値。
関数内でexit()
や例外発生、無限ループに入ることを表す。
クラス内での関係を示す相対型
self
self::
は自クラスを指す(newしていない)
// $this
は自インスタンス(newしたもの)を指す
parent
parent:::
は親クラスを指す。
static
static::
は実行時に最も近い定義クラスを参照するために使う。
?🤔
リテラル型
値の型だけでなく値そのものもチェックされる。
PHP8.0.0以降ではfalse型、PHP8.2.0以降ではtrue型がある。
これ以外にリテラル型は作ることができない。
Iterable
Iterableはarray,Traversable型のエイリアス。
Iterable型はforeachなどでぐるぐる回ることができる。
ジェネレータ内でyield formすることができる。
ジェネレータ?
ジェネレータは配列やコレクションの要素を順番に返すことができるオブジェクト。
yieldが呼び出されるたびに処理が停止して値を返す。
function gen_numbers($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
// ジェネレータを使って数字を順番に出力
foreach (gen_numbers(1, 10) as $number) {
echo $number . " ";
}
// 出力結果:1 2 3 4 5 6 7 8 9 10
このときyield
が呼ばれるタイミングで値を返す。
gen_number() → yield 1が返す→ echo $numberで出力→gen_number()→yield 2が返す→…という形になる。
変数
基本的なこと
PHPの変数は${任意}
という形式で記述する。数字始まりはNG。
値渡し、参照渡し
通常は値渡し(
$a = 100;
$b = $a;
$a = 150;
echo $a // -> 150
echo $b // -> 100;
参照渡しするには代入するときにアンパサンドをつける。
$a = 100;
$b = &$a;
$a = 150;
echo $a // -> 150
echo $b // -> 150;
定義済みの変数
スーパーグローバル
すべてのスコープで使用できる組み込みの変数。
以下がスーパーグローバルと呼ばれる定数。
$GLOBALS
$_SERVER
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_REQUEST
$_ENV
$GLOBALS
グローバルスコープで使用可能な変数への参照。
$GLOBALS
にはグローバルスコープの変数が格納される。
$foo = "hi foo!";
echo $GLOBALS["foo"]; // -> hi foo!
グローバル変数を使うのは極力やめたほうがよいのであまり使わないかも…。
PHP8.1.0以降では$GLOBALSを書き換えることはできなくなった。
$GLOBALS = []; //$GLOBALSを新しい配列にする…(どうなるんだこれ)
$GLOBALS += []; // $GLOBALSに新しい要素を追加する
// etc...
$_SERVER
サーバ情報および実行時の環境情報。
ヘッダ、パス、スクリプトの位置の情報を持っている配列。
この配列の中身はWebサーバが作ってくれる。
Webサーバによっては生成される内容が変化するため注意。
キーと説明
キー | 説明 |
---|---|
PHP_SELF | 現在実行しているスクリプトのファイル名をドキュメントルートから取得する。 例: http://example.com/foo/bar.php の場合は/foo/bar.php が取得できる。 |
argv | スクリプトに渡された引数の配列。 GETメソッドを通じてコールされた場合は検索引数が格納される。 |
argc | スクリプトに渡されたコマンドライン引数の数。 |
GATEWAY_INTERFACE | サーバのCGIバージョン。例:CGI/1.1
|
SERVER_SOFTWARE | レスポンスヘッダ上に書かれているサーバの認識文字列。 |
SERVER_PROTOCOL | ページがリクエストされた際のプロトコル名とバージョンです。 例. HTTP/1.0
|
REQUEST_METHOD | ページにアクセスする際に使用されたリクエストのメソッド名です。 'GET', 'HEAD', 'POST', 'PUT' など。 |
REQUEST_TIME | リクエストの開始時のタイムスタンプ。 |
REQUEST_TIME_FLOAT | リクエストの開始時のタイムスタンプ (マイクロ秒までの精度)。 |
QUERY_STRING | ページがアクセスされた際にもし検索引数があればそれが格納されます。 |
DOCUMENT_ROOT | 現在実行されているスクリプトが存在するドキュメントルート ディレクトリです。サーバーのコンフィグレーションファイルで 定義されています。 |
HTTP_ACCEPT | 現在のリクエストの Accept: ヘッダがもしあれば その内容。 |
HTTP_ACCEPT_CHARSET | 現在のリクエストの Accept-Charset: ヘッダが もしあればその内容。例: 'iso-8859-1,*,utf-8' |
HTTP_ACCEPT_ENCODING | 現在のリクエストに Accept-Encoding: ヘッダが もしあればその内容。例: 'gzip' |
HTTP_ACCEPT_LANGUAGE | 現在のリクエストに Accept-Language: ヘッダが もしあればその内容。例: 'en' |
HTTP_CONNECTION | 現在のリクエストに Connection: ヘッダが もしあればその内容。例: 'Keep-Alive' |
HTTP_HOST | 現在のリクエストに Host: ヘッダが もしあればその内容。 |
HTTP_REFERER | 現在のページに遷移する前にユーザーエージェントが参照していた ページのアドレス(もしあれば)。これはユーザーエージェントに よってセットされます。全てのユーザーエージェントが これをセットしているわけではなく、また、HTTP_REFERER を変更する機能を持つものもあります。 要するに、信頼するべきものではありません。 |
HTTP_USER_AGENT | 現在のリクエストに User-Agent: ヘッダが もしあればその内容。ページにアクセスしてきているユーザーエージェント のしるしの文字列 |
HTTPS | スクリプトが HTTPS プロトコルを通じて実行されている場合に 空でない値が設定されます。 |
REMOTE_ADDR | 現在ページをみているユーザーの IP アドレス。 |
REMOTE_HOST | 現在のページにアクセスしているホスト名。DNS の逆引き検索は ユーザーの REMOTE_ADDR に基づいています。 |
REMOTE_PORT | ユーザーのマシンから Web サーバーへの通信に使用されているポート番号 |
REMOTE_USER | 認証されたユーザー。 |
REDIRECT_REMOTE_USER | リクエストが内部でリダイレクトされた場合の認証されたユーザー。 |
SCRIPT_FILENAME | 在実行されているスクリプトの絶対パス。相対パスで呼ばれている場合は相対パスでの表記 |
SERVER_ADMIN | Web サーバーの設定ファイルの SERVER_ADMIN (Apache の場合)ディレクティブ にセットされている値。スクリプトがバーチャルホスト上で 実行されている場合、バーチャルホストに対して値が定義されます。 |
SERVER_PORT | Web サーバーの通信ポートとして使用されているポート番号。デフォルトでは '80' ですが、例えば SSL を使用している場合は セキュア HTTP ポートとして設定されている値に変わります。 |
SERVER_SIGNATURE | サーバー上で生成されたページに追加される、 サーバーのバージョン名とバーチャルホスト名の文字列。 Web サーバーの設定で有効になっていることが必要です。 |
PATH_TRANSLATED | バーチャルからリアルへのマッピングがなされた後の、 現在のスクリプトのファイルシステム上(ドキュメントルートではなく) でのパス。 |
SCRIPT_NAME | 現在のスクリプトのパス。 スクリプト自身のページを指定するのに有用です。 FILE 定数には、カレント(すなわち読み込まれた)ファイルのパスとファイル名が 含まれます。 |
REQUEST_URI | ページにアクセスするために指定された URI。例えば、 '/index.html' |
PHP_AUTH_DIGEST | HTTP ダイジェスト認証を 行っている場合、クライアントから送られた 'Authorization' ヘッダの 内容が設定されます(適切な認証処理を行うために利用します)。 |
PHP_AUTH_USER | HTTP 認証しているときにそのユーザー名がセットされます。 |
PHP_AUTH_PW | HTTP 認証しているときにそのユーザーの パスワードがセットされます。 |
AUTH_TYPE | HTTP 認証しているときにその認証形式がセットされます。 |
PATH_INFO | 実際のスクリプトファイル名とクエリ文字列の間にある、クライアントが提供するパス名情報。 たとえば、現在のスクリプトに http://www.example.com/php/path_info.php/some/stuff?foo=bar という URL でアクセスしていた場合の $_SERVER['PATH_INFO'] は /some/stuff となります。 |
ORIG_PATH_INFO | PHP で処理される前の 'PATH_INFO' の原本。 |
$_GET
HTTP GETリクエストのURLパラメータのキーと値を保持する。
URLがhttp://example.co.jp/?name=monore
のとき、```$_GET[''name]でmonore を取得できる。
$_POST
HTTP POSTリクエストで渡されたデータのキーと値を保持する。
<form method="POST" action="sample.cgi">
<p>お名前:<input type="text" name="NAME"></p>
<p>メールアドレス:<input type="text" name="email"></p>
<p><input type="submit" value="送信する"></p>
<p><input type="reset" value="取消する"></p>
</form>
$_POST['NAME']=テキストボックスに入力した名前
$_POST['email']=テキストボックスに入力したメールアドレス
$_FILES
HTTPファイルアップロード変数
アップロードされたファイルの情報を色々持つ。
キー | 説明 |
---|---|
$_FILES['userfile']['name'] | クライアントマシンの元のファイル名。 |
$_FILES['userfile']['type'] | ファイルの MIME 型。ただし、ブラウザがこの情報を提供する場合。 例えば、"image/gif" のようになります。 この MIME 型は PHP 側ではチェックされません。そのため、 この値は信用できません。 |
$_FILES['userfile']['size'] | アップロードされたファイルのサイズ(バイト単位) |
$_FILES['userfile']['tmp_name'] | アップロードされたファイルがサーバ上のどこにあるか(テンポラリファイル) |
$_FILES['userfile']['error'] | ファイルアップロードに関するエラーコード |
$_FILES['userfile']['full_path'] | ブラウザからアップロードされたファイルのフルパス。ただし、実際のディレクトリ構造を反映してるとはいえないので信用できない値。(PHP8.1.0以降) |
$_REQUEST
$_GET
,$_POST
,$_COOKIE
をまとめた連想配列。
$_SESSION
現在のスクリプトで使用できるセッション変数を含む連想配列。
そもそもセッションって…
セッションはウェブサイトやアプリケーションのユーザ側の状態を、サーバ側で保持するための仕組み。
- ユーザーがウェブサイトにアクセスすると、セッションIDがクッキーまたはURLパラメーターでユーザーのブラウザに保存されます。
- ユーザーがリクエストを送信するたびに、ブラウザはセッションIDをサーバーに送信します。
- サーバーは、受け取ったセッションIDに関連するセッションデータを検索し、必要に応じて変更します。
- セッションの最後に、サーバーはセッションデータを保存し、セッションIDをブラウザから削除します。
PHPはセッションを開始して、なんやかんやしてセッションを終了する…ということができる。
<?php
// セッション開始
session_start();
// セッションデータを保存
$_SESSION['username']='John';
//セッション終了
session_write_close();
//セッションを再開
session_start();
//セッションデータを読み取り
echo $_SESSION['username']; // -> John
//セッション終了
session_write_close();
$_ENV
環境変数としてスクリプトに渡された変数の連想配列。
実行しているシェルから渡されるものが多いので列挙できないらしい。
$_COOKIE
HTTPクッキー。
クッキーから渡された変数の連想配列。
Cookieってなんだっけ…?
CookieはWebサーバがWebブラウザに保存する小さなデータのこと。
WebサイトがユーザにCookieを送信するとブラウザはCookieを保存する。
次回ユーザが同じWebサイトにアクセスするとCookieをサーバに送ってWebサイト側でそのデータを利用する。
Cookieを消す操作やブラウザを変えるとCookieは消える。
$php_erromsg
直近のエラーメッセージが保持されている。
$http_responce_header
HTTPレスポンスヘッダが格納されている。
<?php
function get_contents() {
file_get_contents("http://example.com");
var_dump($http_response_header);
}
array(9) {
[0]=>
string(15) "HTTP/1.1 200 OK"
[1]=>
string(35) "Date: Sat, 12 Apr 2008 17:30:38 GMT"
[2]=>
string(29) "Server: Apache/2.2.3 (CentOS)"
[3]=>
string(44) "Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT"
[4]=>
string(27) "ETag: "280100-1b6-80bfd280""
[5]=>
string(20) "Accept-Ranges: bytes"
[6]=>
string(19) "Content-Length: 438"
[7]=>
string(17) "Connection: close"
[8]=>
string(38) "Content-Type: text/html; charset=UTF-8"
}
$argc
スクリプトに渡された引数の数。
スクリプトのファイル名は、常にスクリプトへの引数として渡される。
そのため$argcの最小値は1。
$argv
コマンドラインから実行したときスクリプトに渡された引数の配列。
最初の引数$argv[0]はスクリプトの名前なので、渡された値は[1]以降になる。
マジック定数
使われる場所によって変化する定数(マジック定数)というものがある。
この定数はコンパイル時に解決される。また大文字小文字を区別しない。
名前 | 説明 |
---|---|
LINE | ファイル上の現在の行番号。 |
FILE | ファイルのフルパスとファイル名 (シンボリックリンクを解決した後のもの)。 インクルードされるファイルの中で使用された場合、インクルードされるファイルの名前が返されます。 |
DIR | そのファイルの存在するディレクトリ。include の中で使用すると、 インクルードされるファイルの存在するディレクトリを返します。 つまり、これは dirname(FILE) と同じ意味です。 ルートディレクトリである場合を除き、ディレクトリ名の末尾にスラッシュはつきません。 |
FUNCTION | 関数名。無名関数の場合は、{closure} |
CLASS | クラス名。 クラス名には、そのクラスが宣言されている名前空間も含みます (例 Foo\Bar)。 トレイトのメソッド内で CLASS を使うと、 そのトレイトを use しているクラスの名前を返します。 |
TRAIT | トレイト名。 トレイト名には、宣言された名前空間も含みます (例 Foo\Bar)。 |
METHOD | クラスのメソッド名。 |
NAMESPACE | 現在の名前空間の名前。 |
ClassName::class | 完全に修飾されたクラス名。 |
式
PHPにおいては殆どのものが 式 となる。
$a = 5
5
は 5という値を持つ式。
$a
は5
という値を持つ式になる。
…🤔
演算子
演算子の優先順位
演算子ごとに優先順位がある。
同じ優先順位のものがあるとき、左側から処理されるのか、右側から処理されるのかは演算仕事によって異なる。
算術演算子
例 | 名前 | 結果 |
---|---|---|
+$a | 同一 | $aをint や floatに変換する |
-$a | 負にする | $aの逆 |
$a + $b | 加算 | $aと $bの合計 |
$a - $b | 減算 | $aと $bの差 |
$a * $b | 乗算 | $aと $bの積 |
$a / $b | 除算 | $aおよび $bの商 |
$a % $b | 剰余 | $a を $b で割った余り |
$a ** $b | 累乗 | $a の $b の乗 |
代入演算子
代入(値渡し)
$a = 3; // $a に 値3を代入する
$a += 5; // $a+5 の結果を $a に代入する
$b = "hello"; // $b に 文字列helloを代入する
$b .= "there!"; // $b . "there!"と同じ。
参照渡し
$a = 3;
$b = &$a; // $b は $a への参照です
print "$a\n"; // 表示: 3
print "$b\n"; // 表示: 3
$a = 4; // change $a
print "$a\n"; // 表示: 4
print "$b\n"; // 表示: 4
// $b の参照先は $a であり、その値が変わったからです
ビット演算子
例 | 名前 | 説明 |
---|---|---|
$a & $b | ビット積 | $a と $bの論理和をとる |
$a | $b | ビット和 | $a と $bの論理積をとる |
$a ^ $b | 排他的論理和 | $a と $b の排他的論理和をとる |
~ $a | 否定 | ビットを反転する |
$a << $b | 左シフト | $a のビットを左に $b ビットシフトする |
$a >> $b | 右シフト | $a のビットを右に $b ビットシフトする |
比較演算子
例 | 名前 | 説明 |
---|---|---|
$a == $b | 等しい | $a と $b が等しいときにtrue |
$a === $b | 等しい | $a と $b が同じ型で等しいときにtrue |
$a != $b | 等しくない | $a と $b が等しくないときにtrue |
$a <> $b | 等しくない | $a と $b が等しくないときにtrue |
$a !== $b | 等しくない | $a と $b が同じ型でなく、等しくないときtrue |
$a < $b | より少ない | $a が $b より少ないときにtrue |
$a > $b | より多い | $b が $a より多いときにtrue |
$a <= $b | より少ないか等しい | $a が $b より少ないか等しいときtrue |
$a => $b | より多いか等しい | $b が $a より多いか等しいときtrue |
$a<=> $b | 宇宙船演算子 |
|
エラー制御演算子
PHPの式の前に付けた場合、その式により生成されたエラーメッセージは無視される。
/* 意図的なエラー */
$my_file = @file ('non_existent_file') or
die ("Failed opening file: error was '" . error_get_last()['message'] . "'");
// この演算子は関数だけでなく、全ての式で動作します。
$value = @$cache[$key];
// インデックス $key が存在しない場合でも、警告を発生しません。
実行演算子
```````を使うと実行演算子というものになる
実行演算子はシェルコマンドとして扱われるようになるらしい。
$output = `ls- al`;
echo "<pre>$output</pre>";
加減子/減算子
いわゆるインクリメント・デクリメント。
プラスとマイナス記号を前に書くか、後ろに書くかで動きが若干異なる
例 | 名前 | 説明 |
---|---|---|
++$a | 前置加算子 |
|
$a++ | 後置加算子 |
|
--$a | 前置減算子 |
|
$a-- | 後置減算子 |
|
文字列に対しても使えるが文字コードによって返ってくる文字が違うのであんまり使わないほうがいいかも…。
論理演算子
例 | 名前 | 説明 |
---|---|---|
$a and $b | 論理積 | $a と $b が true の場合 true |
$a or $b | 論理和 | $a と $b のどちらが true の場合 true |
$a xor $b | 排他的論理和 | $a と $b のどちらかが true かつ 両方とも trueでないとき true |
!$a | 否定 | $a が trueでないとき true |
$a && $b | 論理積 | $a と $b が true の場合 true、$aがfalseのときは$bは評価しないためちょっと軽い |
$a ||$b | 論理和 | $a と $b のどちらかが true の場合、true。$aが false のときは$bを評価しないためちょっと軽い |
and ,or の方が && || より優先度が高い。
文字列演算子
.
で変数をつなげると文字列を結合する。
.=
と言うかたちで+=
みたいに書ける。
<?php
$a = "Hello ";
$b = $a . "World!"; // $b は、"Hello World!" となります。
$a = "Hello ";
$a .= "World!"; // $a は、"Hello World!" となります。
?>
配列演算子
例 | 名前 | 結果 |
---|---|---|
$a + $b | 結合 | $a と$b を結合する |
$a == $b | 同等 | $aと$bのキーとペアが等しい場合trueを返す |
$a ===$b | 同一 | $aと$bのキーとペアと並び順とデータ型が一致する場合true |
$a != $b | 等しくない | $a と $b が等しくないとき true |
$a <> $b | 等しくない | $a と $b が等しくないとき true |
$a !== $b | 同一でない | $a が $b と同一でない場合に true。 |
結合と同等と同一は便利そう
型演算子
instansof
を使うとその変数の型が一致するかどうか調べることができる。
class MyClass{}
classs NotMyClass{}
$a = new MyClass;
var_dump($a instance of MyClass); // -> bool(true)
var_dump($a instance of NotMyClass) // ->bool(false)
特定のクラスを継承しているか、親クラスも調べることができる
class ParentClass{}
class MyClass extends ParentClass{}
$a = new MyClass;
var_dump($a instanceof MyClass); // -> bool(true)
var_dump($a instanceof ParentClass); // -> bool (true)
interfaceも調べることができる
interface MyInterface{}
class MyClass implements MyInterface{}
$a = new MyClass;
var_dump($a instanceof MyClass); // -> bool(true)
var_dump($a instanceof MyInterface); // ->bool(true)
制御構造
すべてのPHPスクリプトは一連の文からなる。
文は、代入、関数コール、ループ、条件文、何もしない空。文はセミコロンで終了する。
文を()でくくることでグループ化できる。