【PHP入門】基本文法(変数, 演算子, 制御構造, 関数)

変数、演算子、制御構造、関数など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 (式){
case1:
  // 処理
  break;
case2:
  // 処理
  break;
case3:
  // 処理
  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