未経験からweb系プログラマーになるための独学履歴~例外処理~

##このコーナーについて

 私は根っからの文系なのでプログラミングや情報技術についてはITパスポート程度の知識しかなく、現在は全くの独学でコードや言語等のスキルの勉強はチュートリアル等でコードを書いて成果物を作りながら学んでいけるが、それらの過程で出てくる用語や技術についてはイマイチ学びきれない。
なので、折に触れて書籍及びQlita記事等のネットサーフィンで学んだ座学的知識をアウトプットすることがこのコーナーの目的である。

## 今回

パーフェクトPHPで学ぶ例外処理まで

## 例外処理

例外処理とはエラー(例外)が発生しても正常にスクリプトが動作するように行う処理。
プログラムの実行時のエラーを適切に処理するためのものと言ってもいい。

## 基本

```php:例外を投げる

<?php 

throw new $classname(引数);


 ?>

 ```

 ```php:例外をキャッチする

<?php

try {
	
	// 例外が起きる恐れがあるコード

} catch ($classname $e ) {
	
	// 例外発生時の処理
	
}


 ?>

 ```

 基本的な構文は以上の2つ。これを合わせて以下のようにするのが基本的な使い方。

 ```php:例外処理

<?php 

try {

	throw new $classname(引数);

} catch($classname $e ) {



}


 ?>

 ```

`$classname`の部分には例外クラスの名称、`$e`の部分には例外を受け取るための任意の変数を指定しておく。
では実際に使ってみる。

```php:実例1、問題の関数

<?php 
function warizan($val1,$val2) {
	return $val1 / $val2;
}

var_dump(warizan(2,0));


?>
```



```php:実例1の関数の実行結果

<br />
<b>Warning</b>:  Division by zero in <b>[...][...]</b> on line <b>3</b><br />
float(INF)

```

当然上記のようにエラーメッセージが出るのでこれを例外処理で投げて任意の処理に置き換えたいとすると


```php:実例1の例外処理

<?php

function warizan($val1,$val2) {

try {

	if($val2 === 0) { // 1
		throw new Exception("0では割れません");
	}

		return $val1 / $val2;

	} catch (Exception $e) { // 2

		return $e->getMessage(); // 3
	
	}

}

 ?>


```

こういうことになる。例外処理を書く上でのポイントは3つ。

## 1 例外を投げる

まずは例外処理を行う関数において起こるであろうエラーを自分で想定することが肝要である。
今回は簡単な割り算の関数なのですぐにエラーが想定できるが、実際のコードではそうはいかないのでエラーメッセージやアルゴリズムを参考に例外処理を考えていく。

閑話休題。
今回は割る数に0を入れてしまうとエラーになるのだから、`if`文で条件付して例外を投げてしまえばいい。
例外クラスの`Exception`については後述する。

## 2 例外を受け取る（キャッチする）

ここでは例外クラスの`Exception`のインスタンスを`$e`に代入している。
インスタンスがいつ作られたのかというと、コードをみれば分かる通り前述の1のときである。
つまり、大雑把に考えると以下のようなものと思っている。

```php:小学生並みの理解力

throw new Exception("0では割れません"); + catch (Exception $e) 
= $e = new Exception("0では割れません");



```

## 3 例外クラスのインスタンスにあるgetMessageメソッドへアクセスする

ここでは`catch`ブロック内に例外が発生したときの処理を書く。
つまり、必要であるなら1と同じように`throw`構文で例外を投げ、さらに`catch`ブロックを増やすということになる。
今回は、それはせずに受け取った例外に対してどのような反応を返すかということを定義するだけに留まっている。

`$e->getMessage()`とあるということは、インスタンスの中にある`getMessage`メソッドにアクセスしているということになる。
このメソッドは引数に設定された文字を例外メッセージとして取得するメソッドになるので、0では割れませんという文字列が値として`return`で返されることになる。

また、蛇足ではあるが例外が投げられたということはエラーが起きているということになるので、例外が投げられた時点で本来想定していた処理（今回なら割り算の実行結果を返す）は行われず、以上の処理の流れで例外処理が行われる。


以上の流れが例外処理の基本なので覚えておきたい。

## 補足 Exceptionって？

`Exception`とはPHPに備え付けられている例外処理をまとめたクラスのことで、PHPにおいて例外をスローする場合は必ず`Exception`あるいは大本である`Exception`を継承しているサブクラス（`～Exception`の形で表現されているクラス)にスローしなければならない。

Exceptionを継承しているサブクラスというのは例えば定義済みの例外の中では

```php:LogicException

LogicException extends Exception { // Exceptionを継承しているのがわかる。
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 継承したメソッド */
final public Exception::getMessage ( void ) : string
final public Exception::getPrevious ( void ) : Exception
final public Exception::getCode ( void ) : mixed
final public Exception::getFile ( void ) : string
final public Exception::getLine ( void ) : int
final public Exception::getTrace ( void ) : array
final public Exception::getTraceAsString ( void ) : string
public Exception::__toString ( void ) : string
final private Exception::__clone ( void ) : void
}


```

というものがある。
役割はプログラムのロジック内でのエラーを表す。
つまり、この例外に投げられた場合は書いたコードのロジックがおかしいということ。
さらにこれを継承した

```php:BadFunctionCallException

BadFunctionCallException extends LogicException { // LogicExceptionを継承していることがわかる。
/* 継承したプロパティ */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* 継承したメソッド */
final public Exception::getMessage ( void ) : string
final public Exception::getPrevious ( void ) : Exception
final public Exception::getCode ( void ) : mixed
final public Exception::getFile ( void ) : string
final public Exception::getLine ( void ) : int
final public Exception::getTrace ( void ) : array
final public Exception::getTraceAsString ( void ) : string
public Exception::__toString ( void ) : string
final private Exception::__clone ( void ) : void
}
```

というものもある。
ちなみに未定義の関数をコールバックが参照したり、引数を指定しなかったりした場合にこの例外に投げられる。
つまり、どこまでいってもExceptionが大本にあり、これらのクラスはそこから継承したプロパティやメソッドを使って各々の例外処理を行っているということがわかるので、最初にいったスローの際の決まり事にも納得が行くと思う。

PHPにおいての例外は参考の項目にマニュアルのURLを載せておくので各自参照してほしい。



## 参考
 
パーフェクトPHP
[[PHP超入門】クラス～例外処理～PDOの基礎](https://qiita.com/7968/items/6f089fec8dde676abb5b)
[例外](https://www.php.net/manual/ja/spl.exceptions.php)
[定義済みの例外](https://www.php.net/manual/ja/reserved.exceptions.php)