PHP で class を書いていて、try 〜 cache
文で例外処理がキャッチできなくてハマったのでメモ
別クラスの例外がキャッチできなかった例
<?php namespace MyProject\Package; class FileLoader { public function __construct() {} public function loadFile(string $file) { if ( !is_file($file) ) { throw new InvalidArgumentException("{$file} is not a file"); } $contents = file_get_contents($file); if ( $contents === false ) { throw new RuntimeException("Error reading file at {$file}."); } return $contents; } }
<?php namespace MyProject\Package; class MyClass { public function __construct(string $file) { $fileLoader = new FileLoader(); try { $data = $fileLoader->loadFile($file); // … } catch ( InvalidArgumentException $exception ) { // 例外処理 ... } } }
FileLoader クラスでファイルが存在しない時 (!is_file($file)
) に呼び出し元で例外をキャッチしたかったのですが、例外をキャッチできずに画面に InvalidArgumentException エラーが表示されてしまいました…
namespace がある場合 グローバルなクラスは \
始まりで呼び出す必要がある
Using
\
in front of class name, it mean you call theclass
from global space. If you don't use\
, it will call the class in samenamespace
with your code. But if you don't use namespace in your code, it will call class from global space.
cf. php - Difference between (Exception $e) and (\Exception $e) in try{}catch(){} - Stack Overflow
namespace のあるクラスでは
\
始まりのクラスは、global から呼び出している\
のないクラスは、今のクラスの namespace から呼び出している
<?php namespace Module\Example; class Test { try { } catch(Exception $e) { // will look up Module\Example\Exception } try { } catch(\Exception $e) { // will look up Exception from global space } }
先の例では例外を投げている部分 throw new InvalidArgumentException("{$file} is not a file");
のエラークラスが MyProject\Package\InvalidArgumentException
クラスのエラーという扱いになっていてうまくキャッチできてなかったのが原因のようででした
👇 コードを修正する
<?php namespace MyProject\Package; class FileLoader { public function __construct() {} public function loadFile(string $file) { if ( !is_file($file) ) { - throw new InvalidArgumentException("{$file} is not a file"); + throw new \InvalidArgumentException("{$file} is not a file"); } $contents = file_get_contents($file); if ( $contents === false ) { - throw new RuntimeException("Error reading file at {$file}."); + throw new \RuntimeException("Error reading file at {$file}."); } return $contents; } }
<?php namespace MyProject\Package; class MyClass { public function __construct(string $file) { $fileLoader = new FileLoader(); try { $data = $fileLoader->loadFile($file); // … - } catch ( InvalidArgumentException $exception ) { + } catch ( \InvalidArgumentException $exception ) { // 例外処理 ... } } }
これで意図したとおりに例外がキャッチできるようになりました!
PHP の namespace 未だによく分かってない…
[参考]