変数、演算子、制御構造、関数などPHPの基本知識について書いてます。他のプログラミング経験があるかたなら、すぐ理解できて参考になると思います。
豆知識
出力
// echo(変数と文字列を出力)
$name = "佐藤";
echo $name . "です。"; // 佐藤です。
// printf (フォーマットして出力)
$year = 2014;
$month = 8;
$day = 2;
//YYYYMMDD形式に変換して出力
printf('%04d%02d%02d', $year, $month, $day);
// sprintf(フォーマットして文字列を返す。出力しない。)
$year = 2014;
$month = 8;
$day = 2;
//YYYYMMDD形式に変換して$dateに格納
$date = (int)sprintf('%04d%02d%02d', $year, $month, $day);
// var_dump(値と型情報を表示)
$str = "test";
var_dump($str); // string(4) "test"
エスケープシーケンス
"(ダブルクォーテーション)
などの特殊文字を文字として表現したい場合、特殊文字の前に\
を付与します。\"
とすることで"
を表現できます。
HTMLタグのエスケープ
クロスサイトスクリプティングなどの対策として、安全にブラウザに値を表示するためにhtmlspecialchars()関数を利用します。htmlspecialchars()関数は、例えば<
を<
に変換します。ブラウザ表示する場合、原則すべてのデータにhtmlspecialchars()関数を使用した方がいいです。
//使用例
echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
第2引数にENT_QUOTES
を指定してます。指定すると、ダブルクォートもシングルクォートも変換します。この変換は必要なので必ず指定します。
URLエンコード
GETリクエストでパラメータを送る場合、URLではマルチバイト文字列を扱えないのでエンコードが必要です。
//エンコード(符号化)
string urlencode ( string $str )
//デコード(複合)
string urldecode ( string $str )
複数行の書き方
ヒアドキュメント
という記述ができます。
$str = <<<EOT
aaa
bbb
ccc
EOT;
var_dump($str);
string(11) "aaa
bbb
ccc"
データ、変数
定数
// defineまたはconstで定義します。constは名前空間の影響を受けます。
define('MAXHEIGHT', 250);
const MAXHEIGHT = 250;
// 定義済み定数
PHP_EOL // 実行された環境での改行コードを表します。
// PHPで改行したい場合、PHP_EOLを使うほうが好ましいです。
マジック定数
マジック定数
という、自動的に定義される定数が存在します。
名前 | 概要 |
---|---|
__LINE__ | 現在の行番号。 |
__FILE__ | ファイルのフルパスとファイル名。 |
__DIR__ | ファイルの存在するディレクトリ。 |
__FUNCTION__ | 関数名。 |
__CLASS__ | クラス名。 |
__METHOD__ | クラスのメソッド名。 |
__NAMESPACE__ | 現在の名前空間の名前。 |
配列
$x = array("Sun", "Mon", "Tue");
$x = ["Sun", "Mon", "Tue"]; // PHP5.4以降で使える
foreach ($x as $y) {
echo $y;
} // SunMonTue
連想配列
PHPにおいて添字配列
と連想配列
の間に違いはありません。添字配列は、連想配列でキーを添字にしたのと同じです。
$fruits = [
'apple' => 'red',
'banana' => 'yellow'
];
foreach ($fruits as $name => $color) {
echo "$name is $color" . PHP_EOL;
}
多次元連想配列
$list = [
'佐藤' => [
'ID' => 1,
'身長' => 158,
'体重' => 52
],
'鈴木' => [
'ID' => 2,
'身長' => 176,
'体重' => 60
]
];
「配列」と「オブジェクト」のアクセス方法の違い
オブジェクトデータ
に配列のアクセス方法でアクセスするとCannot use object of type stdClass as array
といったエラーが発生します。
// 配列の場合は次のようにアクセス
$user['name'];
// オブジェクトの場合は次のようにアクセス
$user->name;
オブジェクトで、アクセスしたいプロパティを動的に決める場合、以下のようにします。
$user->{'name' . $i};
オブジェクトと配列の相互変換
// 配列をstcClassに変換
$obj = (object) $arr;
// オブジェクトを配列に変換
$arr = (array) $obj;
スコープ
グローバルスコープ
PHPはブロックスコープ
がないため、ブロック内で定義した変数をブロックを抜けた後も使用できます。
ローカルスコープ
「関数」「クラスのメソッド」内のスコープです。自動的にローカル内でグローバル変数を利用することはできません。ローカルスコープ内でグローバルスコープ内で定義された変数を参照したい場合は、globalキーワード
を使用します。
制御構造
if
if (条件) {
// 処理
} elseif (条件) {
// 処理
} else {
// 処理
}
for
for ($x = 1; $x <= 10; $x++) {
// 処理
}
foreach
foreach ($params as $key => $value) {
// 処理
}
switch
switch (式){
case 値1:
// 処理
break;
case 値2:
// 処理
break;
case 値3:
// 処理
break;
default:
// 処理
}
break, continue, return, exit
以下のような違いがあります。
break
for
foreach
while
do-while
switch
構造内の処理を抜けます。
continue
ループ処理をスキップします。
return
関数内で呼び出されると、その関数の実行を停止し、引数を関数の値として返します。
グローバルスコープで呼び出されると、現在実行中のスクリプトを終了します。
exit
現在のスクリプトを終了します。
三項演算子
// expr1がTRUEならexpr2を、FALSEならexpr3を返す
(expr1) ? (expr2) : (expr3)
// [5.3以降] expr1がTRUEならexpr1を、FALSEならexpr3を返す
// 最初の項に未定義の変数を与えるとNOTICEレベルの警告発生
expr1 ?: expr3
// [7.0以降] expr1がNULLまたは未定義ならexpr2を、それ以外の場合はexpr1を返す
(expr1) ?? (expr2)
7.0以降では、いままでisset
で判定していた箇所を??(Null合体演算子)
に置き換えることができます。
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
$username = $_GET['user'] ?? 'nobody';
外部ファイル読込
require、require_once
失敗した場合に致命的なエラーを発生し、スクリプトの処理がそこで止まります。
include、include_once
失敗した場合に警告を発生し、スクリプトの処理は続行します。
関数
引数にデフォルト値を設定
function add($value1, $value2 = 100) {
$sum = $value1 + $value2;
return $sum;
}
可変長引数
function xxx() {
$num = func_num_args(); // 引数の数を代入
$args = func_get_args(); // 引数を配列として代入
}
静的変数
関数の呼び出しが終了しても値を保持したままにするには、変数にstaticキーワードを付けます。
function xxx() {
static $count = 0; //最初にこの関数が呼ばれた時だけ初期化される。
$count++;
return $count;
}
戻り値で複数の値を返す
戻り値は1つしか指定できません。複数の値を返すには戻り値に配列やオブジェクトを指定します。
型宣言(タイプヒンティング)
// クラス名、インタフェース名 (php5.0以上)
function test(MyClass $class){
}
// array (php5.1以上)
function test(array array){
}
// スカラー型[float, int, string] (php7.0以上)
function test(int integer){
}
不正な型であった場合
- PHP5 ⇒ recoverable fatal error。
- PHP7 ⇒ TypeError 例外をスロー。
暗黙の型変換
php7からスカラー型もタイプヒンティングできるようになりました。ですが、厳密な型検査
と弱い型検査
の2つのモードがあるので注意が必要です。弱い型検査
では暗黙の型変換が行われます。
厳密な型検査
を行うには、以下のようにファイルの先頭に記述します。
<?
declare(strict_types=1);
すると、このファイル内で関数を呼び出した際、厳密な型検査
が行われます。
※参考URL
http://php.net/manual/ja/functions.arguments.php#functions.arguments.type-declaration
phpDocumentor
例を示します。
/**
* 関数の概要を記述
*
* @param string $arg パラメーターの説明や事前条件など記述
* @param integer $arg2 パラメーターの説明や事前条件など記述
* @return integer 戻り値について説明を記述
* @throws LogicException 例外が発生するケースなど記述
*/
function test(string $arg, integer $arg2){
}
※タグの使い方の参考URL
https://www.phpdoc.org/docs/latest/index.html
例外
実装例
例外の実装例です。
function division($v1, $v2) {
if ($v2 === 0) {
throw new Exception("Division by zero."); // 例外を投げる
}
return $v1/$v2;
}
try {
echo division(6, 3), PHP_EOL;
echo division(3, 0), PHP_EOL; // 例外発生。catch句へ移る。
echo division(8, 2), PHP_EOL;
} catch (Exception $e) {
echo 'Exception:' . $e-getMessage() . PHP_EOL; // Exception:Division by zero.
}
if文で条件分岐すると正常処理、エラー処理が混在して処理の流れがわかりづらくなります。
それに対し、例外処理ではtry句内に正常な処理だけを記述し、catch句内にはエラー処理だけを記述するので処理の流れがわかりやすくなります。
標準エラーを例外に変換
PHPの組込み関数は基本的に例外ではなくエラーを吐きます。例外として扱いたい場合、エラーハンドラの設定でエラーを例外に変換する必要があります。
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
エラー、例外クラスの階層
Throwable スロー可能なあらゆるオブジェクトが実装する基底インターフェイス。
Error PHPのすべての内部エラーの基底クラス。
ArithmeticError 数学的な操作でエラーが発生したときにスロー。
DivisionByZeroError 数値をゼロで割ろうとしたときにスロー。
AssertionError assert() によるアサーションが失敗したときにスロー。
ParseError eval() を呼んだときなどの PHP コードのパースに失敗したときにスロー。
TypeError 関数に渡す引数の型が不一致、戻り値の型が不一致。組み込み関数に渡す引数の数が違うときにスロー。
Exception すべてのユーザー例外の基底クラス。
ErrorException エラー例外。
LogicException プログラムのロジック内でのエラーを表す例外。この類の例外が出た場合は、自分が書いたコードを修正すべき。
BadFunctionCallException 未定義の関数をコールバックが参照したり、引数を指定しなかったりしたときににスロー。
BadMethodCallException 未定義のメソッドをコールバックが参照したり、引数を指定しなかったりしたときににスロー。
DomainException 定義したデータドメインに値が従わないときにスロー。
InvalidArgumentException 引数の型が期待する型と一致しなかったときにスロー。
LengthException 長さが無効なときにスロー。
OutOfRangeException 無効なインデックスを要求したときにスロー。
RuntimeException 実行時にだけ発生するようなエラーの際にスロー。
OutOfBoundsException 値が有効なキーでなかった場合にスロー。
OverflowException いっぱいになっているコンテナに要素を追加した場合にスロー。
RangeException プログラムの実行時に範囲エラーが発生したことを示すときにスロー。
UnderflowException 空のコンテナ上で無効な操作 (要素の削除など) を試みたときにスロー。
UnexpectedValueException いくつかの値のセットに一致しない値であった際にスロー。
※参考URL
http://php.net/manual/ja/spl.exceptions.php
http://php.net/manual/ja/reserved.exceptions.php