はじめに
バックエンド側(API側)の処理で必要な処理だけを急いで書いて、エラー処理は疎かになりがちで、書いてもいつも書き方がまちまちなので、ここでいったん整理した。
記載方法
まとめたといっても単純でtry catchを使用することである。
特定の不具合に関してはエラー処理を具体的に決めて処理をするということである。
記載例
コントローラファイル
App\Http\Controllers
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\QueryException;
use PDOException;
use Exception;
use App\Exceptions\FileExtensionException;
use App\Exceptions\CsvColumnMismatchException;
class MyController extends Controller
{
public function handleRequest(Request $request)
{
try {
// ファイル拡張子の確認
$this->validateFileExtension($request);
// CSVファイルのカラム確認
$this->validateCsvColumns($request);
// トランザクションとDB操作
$this->handleTransaction($request); // $request を渡す
return redirect()->route('success.page');
} catch (FileExtensionException $e) {
return back()->with('error', 'アップロードされたファイルはCSVではありません。');
} catch (CsvColumnMismatchException $e) {
return back()->with('error', 'CSVのカラムが一致しません。');
} catch (PDOException $e) {
return back()->with('error', 'データベースに接続できませんでした。');
} catch (QueryException $e) {
return back()->with('error', 'データベースクエリに問題がありました。');
} catch (Exception $e) {
\Log::error($e); // 例外をログに記録
return back()->with('error', 'データの操作中にエラーが発生しました。');
}
}
private function validateFileExtension(Request $request)
{
if ($request->file('csv_file')->getClientOriginalExtension() !== 'csv') {
throw new FileExtensionException();
}
}
private function validateCsvColumns(Request $request)
{
// ここではサンプルとしてCSVの最初の行を取得し、カラムを確認します。
$file = new \SplFileObject($request->file('csv_file')->path());
$header = $file->fgetcsv();
$expectedColumns = ['column1', 'column2', 'column3']; // 期待されるカラム名のサンプル
if ($header !== $expectedColumns) {
throw new CsvColumnMismatchException();
}
}
private function handleTransaction(Request $request) // $request を引数として受け取る
{
// トランザクション開始
DB::beginTransaction();
try {
// クエリ実行
$result = DB::table('some_table')->get();
// Eloquentモデルの保存
$model = new MyModel;
$model->some_field = $request->input('value'); // $request を使う
$model->save();
// トランザクションコミット
DB::commit();
} catch (Exception $e) {
// トランザクションロールバック
DB::rollback();
throw $e; // 例外を再スロー
}
}
}
例外ファイル
App\Exceptions
// FileExtensionException.php
namespace App\Exceptions;
use Exception;
class FileExtensionException extends Exception
{
// 任意で追加のコード
}
// CsvColumnMismatchException.php
namespace App\Exceptions;
use Exception;
class CsvColumnMismatchException extends Exception
{
// 任意で追加のコード
}
記載内容
Laravelを使用している。
csvファイルをアップしたのをテーブルに保存し、前画面に戻る例を挙げている。
エラーとして起こりうることとして色々あると思うが、何が起こるかを記載する。
今回は、エラーとして、ファイル拡張子、CSVファイルカラムのヘッダー確認を行なっている。
他に、ファイルの存在とアップロード確認、ファイルサイズ、csvのデータ行に対する検証等があるが、今回は割愛している。
要は何をエラーにするかを決めることである。
記載方法
1.本処理を書く。
ここではcsvアップとDB書き込みである。
必要に応じてメソッド化する(今回はメソッド化している)。
2.エラー処理をcatchで対応する。
既に存在する例外クラス、独自例外クラスは作成する。
ここが厄介なところかもしれない。
今回は以下既に存在する例外クラスを使用している。
useに記載する。
use Illuminate\Database\QueryException;
use PDOException;
use Exception;
これらの例外クラスは既に存在するので、useで記載する。
PDOExceptionは、PHPのPDO(PHP Data Objects)拡張で発生する可能性のあるエラーを表し、PHPの標準ライブラリに含まれています。
QueryExceptionは、LaravelのデータベースクエリビルダやEloquent ORMでデータベースクエリに関するエラーが発生した際に投げられる例外で、Laravelフレームワークに含まれる。
3.エラー処理作成
既存例外クラスは2で行う。
独自の例外クラスは、throw new クラス名()として対応。
そのクラスをApp¥Exceptionでフォルダを作成し、クラスを作成する。
今回はエラー状態を捕捉したいだけなので、例外クラスは空で構わない。
特定のエラー状態をプログラムが認識できるようになる。
その他
catch (Exception $e) で一般的なエラーをキャッチしているが、ここではエラーのロギングも行うといい。これによって、後でエラーを解析る。
おわりに
しばらくこれで様子を見る。
とりあえず例外を気にしない記載は控えていきたい。