PHP の例外処理メソッド

Jun 09, 2018 am 09:55 AM
php 異常な

この記事では主にPHPにおける例外処理の方法を紹介していますので、興味のある方は参考にしていただければ幸いです。

PHP ランタイムに追加されるすべての新機能は指数関数的な乱数を作成するため、開発者はこの新機能を使用したり悪用したりする可能性があります。ただし、開発者が合意に達したのは、良いユースケースと悪いユースケースがいくつか出現してからでした。こうした新たなケースが出現すると、最終的に何が最良のアプローチか、何が最悪のアプローチかを識別できるようになります。

例外処理は、決して PHP の新しい機能ではありません。ただし、この記事では、PHP 5.3 の例外処理に基づく 2 つの新機能について説明します。 1 つ目はネストされた例外で、2 つ目は SPL (現在の PHP オペレーティング メカニズムのコア拡張機能) によって拡張された一連の新しい例外タイプです。これら 2 つの新機能については、本書にベスト プラクティスが記載されており、詳細に検討する価値があります。


特記事項: これらの機能の一部は、PHP 5.3 より前のバージョンにすでに存在しているか、少なくとも 5.3 より前のバージョンに実装できます。この記事で言及されている PHP 5.3 は、厳密には PHP ランタイムではありません。むしろ、コード ベースとプロジェクトが最小バージョンとして PHP 5.3 を採用することを意味しますが、この開発段階では、次のようないくつかのプロジェクトによる「2.0」の試みが強調表示されます。 Zend Framework、Symfony、Doctrine、PEAR

Background

PHP 5.2 のみ 例外クラス Exception。 Zend Framework/PEAR 開発標準によれば、このクラスはライブラリ内のすべての例外クラスの基本クラスです。 MyCompany という名前のライブラリを作成すると、Zend Framework / PEAR 標準に従って、ライブラリ内のすべてのコード ファイルは MyCompany_ で始まります。ライブラリ MyCompany_Exception に独自の例外基本クラスを作成する場合は、このクラスを使用して Exception を継承し、コンポーネント (コンポーネント) がこの例外クラスを継承してスローします。たとえば、コンポーネント MyCompany_Foo がある場合、コンポーネント内で使用する例外基本クラス MyCompany_Foo_Exception を作成できます。これらの例外は、MyCompany_Foo_Exception、MyCompany_Exception、または Exception をキャッチするコードによってキャッチできます。このコンポーネントを使用するライブラリ内の他のコードの場合、これは 3 レベルの例外 (MyCompany_Foo_Exception のサブクラスの数によってはそれ以上) であり、これらの例外を必要に応じて処理できます。


php5 では、基本例外クラスはすでにネストされた機能をサポートしています。ネスティングとは何ですか?ネストとは、特定の例外、または元の例外を参照することによって作成された新しい例外オブジェクトをキャッチする機能です。これにより、呼び出し元属性を、よりパブリックな型のオーバーヘッド ライブラリに表示される 2 つの例外クラスに反映できるようになり、もちろん元の例外動作を持つ例外クラスにも反映できるようになります。

これらの機能が役立つのはなぜですか?多くの場合、他のコードを使用して独自のタイプの例外をスローするのが最も効率的なコードです。このコードは、アダプター パターンを使用してカプセル化された適応性の高い機能を提供するサードパーティ コード ライブラリのコード、または例外をスローするためにいくつかの PHP 拡張機能を利用する単純なコードである可能性があります。


たとえば、コンポーネント Zend_Db では、アダプタ パターンを使用して特定の PHP 拡張機能をカプセル化し、アダプタ内で Zend_Db が PDO をカプセル化し、PDO が独自の例外をスローします。 PDOException の場合、Zend_Db はこれらの PDO 固有の例外をキャッチし、予測可能な既知のタイプの Zend_Db_Exception として再スローする必要があります。これにより、開発者は Zend_Db が常に Zend_Db_Exception タイプの例外をスローする (したがってキャッチできる) ことが保証されます。また、必要に応じて、最初にスローされた PDOException にアクセスすることもできます。

次の例は、架空のデータベース アダプターが埋め込み例外を実装する方法を示しています。

class MyCompany_Database
{
 /**
  * @var PDO object setup during construction
  */
 protected $_pdoResource = null;
  
 /**
  * @throws MyCompany_Database_Exception
  * @return int
  */
 public function executeQuery($sql)
 {
  try {
   $numRows = $this->_pdoResource->exec($sql);
  } catch (PDOException $e) {
   throw new MyCompany_Database_Exception('Query was unexecutable', null, $e);
  }
  return $numRows;
 }
 
}
ログイン後にコピー

埋め込み例外を使用するには、次のようにします。キャッチされた例外の getPrevious() メソッドを呼び出す:

// $sql and $connectionParameters assumed
try {
 $db = new MyCompany_Database('PDO', $connectionParams);
 $db->executeQuery($sql);
} catch (MyCompany_Database_Exception $e) {
 echo 'General Error: ' . $e->getMessage() . "\n";
 $pdoException = $e->getPrevious();
 echo 'PDO Specific error: ' . $pdoException->getMessage() . "\n";
}
ログイン後にコピー

最近実装された PHP 拡張機能 どちらも OO (オブジェクト指向) インターフェイスを備えているため、これらの API はエラーで終了するのではなく、例外をスローする傾向があります。 。例外をスローできる PHP の拡張機能には、PDO、DOM、Mysqli、Phar、Soap、SQLite などがあります。

新機能: 新しいコア例外タイプ

PHP 5.3 開発では、いくつかの興味深い新しい例外タイプを紹介しました。これらの例外は PHP 5.2 に存在していました。これらの新しい例外タイプは SPL 拡張機能に実装されており、マニュアル (こちら) にリストされています。これらの新しい例外タイプは PHP コアの一部であり、SPL の一部でもあるため、PHP 5.3 (およびそれ以降) でコードを実行している人なら誰でも使用できます。アプリケーション層のコードを作成するときはそれほど重要ではないように見えますが、コード ライブラリを作成または使用するときは、これらの新しい例外タイプを使用することがより重要になります。


那么为什么新异常是普通类型?以前,开发者试图通过在异常消息提醒中放入更多的内容来赋予异常更多的含义。虽然这样做是可行的,但是它有几个缺点。一是你无法捕获基于消息的异常。这可是一个问题,如果你知道一组代码是同样的异常类型与不同的提示消息对应不同异常情况下,处理起来的难度将相当的大。例如,一个认证类,在对$auth->authenticate();;它抛出异常的相同类型的(假设是异常),但不同的消息对应两个具体的故障:产生故障原因是认证服务器不能达到但是相同的异常类型却提示失败的验证消息不同。在这种情况下(注意,使用异常可能不是处理认证响应最好的方式),这将需要用字符串来解析消息从而处理这两种不同的情况。

这个问题的解决办法显然是通过某种方式对异常进行编码,这样就可以在需要辨别如何对这种异常环境做出反应的时候能够更加容易的查询到。第一个反应库是使用异常基类的$code属性。另一个是通过创建可以被抛出且能描述自身行为的子类或者新的异常类。这两种方法具有相同的明显的缺点。两者都没有呈现出想这样的最好的例子。两者都不被认为是一个标准,因此每个试图复制这两种解决方案的项目都会有小的变化,这就迫使使用这需要回到文档以了解所创建的库中已经有的具体解决方案。现在通过使用SPL的新的类型方法,也称作php标准库;开发者就可以以同样的方式在他们的项目中,并且复用这些项目的新的最佳的方法已经出现。


第二个缺点是使用详细信息的做法使得理解这些异常情况对那些非英语或英语能力有限的开发者来说十分困难。这可能会使的开发者在试图理解异常信息的含义的过程十分的缓慢。许多开发者也会写关于异常的文章,因为还未出现一个统一的整合过的标准所要有同这些开发者数量相同的不同的版本来描述异常消息所描述的情况。

所以我如何去使用它们,就用这些让人无语的密密麻麻的细节描述?

现在在SPL中有总共13个新的异常类型。其中两个可被视为基类:逻辑异常和运行时异常;两种都继承php异常类。其余的方法在逻辑上可以被拆分为3组:动态调用组,逻辑组和运行时组。

动态调用组包含异常 BadFunctionCallException和BadMethodCallException,BadMethodCallException是BadFunctionCallException(LogicException的子类)的子类,这意味着这些异常可以被其直接类型(译者注:就是异常自身的类型,大家都知道异常有很多种)、LogicException,或者Exception抓到(译者注:就是catch)你应该在什么时候使用这些?通常,你应该在由一个无法处理的__call()方法产生的情况,或者回调无法不是一个有效的函数(简单说,当某些东西并非is_callable())时使用。

例如:

// OO variant
class Foo
{
 public function __call($method, $args)
 {
  switch ($method) {
   case 'doBar': /* ... */ break;
   default:
    throw new BadMethodCallException('Method ' . $method . ' is not callable by this object');
  }
 }
 
}
 
// procedural variant
function foo($bar, $baz) {
 $func = 'do' . $baz;
 if (!is_callable($func)) {
  throw new BadFunctionCallException('Function ' . $func . ' is not callable');
 }
}
ログイン後にコピー

一个直接的例子,在__call时call_user_func()。这组异常在开发各种API动态方法的调用、函数调用时非常有用,例如这是一个可以被SOAP和XML-RPC客户端/服务端能够发送和解释的请求。


第二组是逻辑(logic )组。这组由DomainException、InvalidArgumentException、LengthException、OutOfRangeException组成。这些异常也是LogicException的子类,当然也是PHP的Exception的子类。在有状态不定,或者错误的方法/函数的参数时使用这些异常。为了更好地理解这一点,我们先看看最后一组异常

最后一组是运行时(runtime )组。它由OutOfBoundsException、OverflowException、RangeException、UnderflowException、UnexpectedValueExceptio组成。这些异常也是RuntimeException的子类,当然也是PHP的Exception的子类。在“运行时”(runtime)的函数、方法发生异常时,这些异常(运行时组)会被调用


逻辑组和运行时组如何一起工作?如果你看看对象的剖析,通常是发生的是两者之一。首先,对象将跟踪并改变状态。这意味着对象通常是不做任何事情。它可能会传递结构给它,它可能会通过setter和getter设置一些东西(译者注:例如$this->foo='foo'),或者,它可能会引用其他对象。第二,当对象不跟踪或改变状态,这代表正在操作——做它该做的事。这是对象的运行时(runtime)。例如,在对象的一生中,它可能被创建,设置一些东西,那么它可能会被setFoo($foo),setBar($bar)。在这些时候,任何类型的LogicException应该被提高。此外,当对象内的方法被带参数调用时,例如$object->doSomething($someVariation);在前几行检查$someVariation变量时,可能抛出一个LogicException。完成检查$someVariation后,它继续做它该做的doSomething(),这时被认为是它的“运行时”(runtime),在这段代码中,可能抛出RuntimeExcpetions异常。


要理解得更好,我们来看看这个概念在代码中的运用:

class Foo
{
 protected $number = 0;
 protected $bar = null;
 
 public function __construct($options)
 {
  /** 本方法抛出LogicException异常 **/
 }
  
 public function setNumber($number)
 {
  /** 本方法抛出LogicException异常 **/
 }
  
 public function setBar(Bar $bar)
 {
  /** 本方法抛出LogicException异常 **/
 }
  
 public function doSomething($differentNumber)
 {
  if ($differentNumber != $expectedCondition) {
   /** 在这里,抛出LogicException异常 **/
  }
   
  /**
   * 在这里,本方法抛出RuntimeException异常
   */ 
 }
 
}
ログイン後にコピー

现在理解了这一概念,那么,对代码库的使用者来说,这是做什么的呢?使用者可以随时确定对象的异常状态,他们可以用异常的具体的类型来捕获(catch)异常,例如InvalidArgumentException或LengthException,至少也是LogicException。通过这种级别的精度调整,和类型的多样,他们可以用LogicException捕获最小的异常,但也可以通过实际的异常类型获得更好的理解。同样的概念也适用于运行时的异常,可以抛出更多的特定类型的异常,并且不论是特定或非特定类型的异常,都可以被捕获(catch)。它可以给使用者提供更详细的情况和精确度。

下面是一个关于SPL异常的表,您可能会有兴趣

类库代码中的最佳实践

PHP 5.3 带来了新的异常类型, 同时也带给我们新的最佳实践. 除了将某些特定的异常(如: InvalidArgumentException, RuntimeException)标准化外, 捕捉组件级的异常, 也很重要. 关于这方面, ZF2 wiki 和 PEAR2 wiki 上面有深入的探讨.

简而言之, 除了上面提到的各种最佳实践, 我们还应该用 Marker Interface 来创建一个组件级的异常基类. 通过创建组件级的 Marker Interface, 用在组件内部的异常既能继承 SPL 的异常类型, 也能在运行时被各种代码捕捉. 我们来看下列代码:

// usage of bracket syntax for brevity
namespace MyCompany\Component {
 
 interface Exception
 {}
 
 class UnexpectedValueException 
  extends \UnexpectedValueException 
  implements Exception
 {}
 
 class Component
 {
  public static function doSomething()
  {
   if ($somethingExceptionalHappens) {
    throw new UnexpectedValueException('Something bad happened');
   }
  }
 }
 
}
ログイン後にコピー

如果调用上面代码中的 MyCompany\Component\Component::doSomething() 函数, doSomething() 抛出的异常可以当作下列异常类型捕捉: PHP 的 Exception, SPL 的 UnexpectedValueException, SPL 的 RuntimeException, 该组件的MyCompany\Component\UnexpectedValueException, 或该组件的 MyCompany\Component\Exception. 这为捕捉你的类库组件中的异常提供了极大的便利. 此外, 通过分析异常的类型, 我们也能看出某个异常的含义.

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。

相关推荐:

使用Snoopy类解析html文件的方法

php针对数组的删除、转换、分组、排序

php针对文件操作及字符串加密的方法

以上がPHP の例外処理メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

See all articles