133 votes

PHP: les exceptions vs erreurs?

Peut-être que je suis absent quelque part dans le manuel PHP, mais quelle est exactement la différence entre une erreur et une exception? La seule différence que je peux voir c'est que les erreurs et les exceptions sont traitées différemment. Mais ce qui provoque une exception et ce qui les provoque une erreur?

99voto

gnarf Points 49213

Les Exceptions sont jetés - ils sont destinés à être pris. Les erreurs sont généralement irrécupérable. Disons par exemple - vous avez un bloc de code qui permet d'insérer une ligne dans une base de données. Il est possible que cet appel échoue (ID en double) - vous souhaitez avoir une "Erreur" qui dans ce cas est une "Exception". Lorsque vous insérez ces lignes, vous pouvez faire quelque chose comme ceci

try {
  $row->insert();
  $inserted = true;
} catch (Exception $e) {
  echo "There was an error inserting the row - ".$e->getMessage();
  $inserted = false;
}

echo "Some more stuff";

L'exécution du programme continuera - parce que vous avez "pris" l'exception à la règle. Une exception sera traitée comme une erreur, sauf si il est pris. Il vous permettra de continuer l'exécution du programme suite à l'échec.

59voto

Kris Points 11892

J'ai l'habitude de set_error_handler à une fonction qui prend l'erreur, déclenche une exception afin que quoi qu'il arrive je vais avoir des exceptions à traiter. Pas plus @file_get_contents seulement agréable et soigné try/catch.

En debug situations j'ai aussi un gestionnaire d'exception qui génère un asp.net comme la page. Je vais l'afficher sur la route, mais si on le demande, je vais poster un exemple plus tard.

edit:

Outre comme promis, j'ai coupé et collé à certains de mes code ensemble pour faire un exemple. J'ai enregistré le ci-dessous pour fichier sur mon poste de travail, vous pouvez voir les résultats ici.

<?php

define( 'DEBUG', true );

class ErrorOrWarningException extends Exception
{
    protected $_Context = null;
    public function getContext()
    {
    	return $this->_Context;
    }
    public function setContext( $value )
    {
    	$this->_Context = $value;
    }

    public function __construct( $code, $message, $file, $line, $context )
    {
    	parent::__construct( $message, $code );

    	$this->file = $file;
    	$this->line = $line;
    	$this->setContext( $context );
    }
}

/**
 * Inspire to write perfect code. everything is an exception, even minor warnings.
 **/
function error_to_exception( $code, $message, $file, $line, $context )
{
    throw new ErrorOrWarningException( $code, $message, $file, $line, $context );
}
set_error_handler( 'error_to_exception' );

function global_exception_handler( $ex )
{
    ob_start();
    dump_exception( $ex );
    $dump = ob_get_clean();
    // send email of dump to administrator?...

    // if we are in debug mode we are allowed to dump exceptions to the browser.
    if ( defined( 'DEBUG' ) && DEBUG == true )
    {
    	echo $dump;
    }
    else // if we are in production we give our visitor a nice message without all the details.
    {
    	echo file_get_contents( 'static/errors/fatalexception.html' );
    }
    exit;
}

function dump_exception( Exception $ex )
{
    $file = $ex->getFile();
    $line = $ex->getLine();

    if ( file_exists( $file ) )
    {
    	$lines = file( $file );
    }

?><html>
    <head>
    	<title><?= $ex->getMessage(); ?></title>
    	<style type="text/css">
    		body {
    			width : 800px;
    			margin : auto;
    		}

    		ul.code {
    			border : inset 1px;
    		}
    		ul.code li {
    			white-space: pre ;
    			list-style-type : none;
    			font-family : monospace;
    		}
    		ul.code li.line {
    			color : red;
    		}

    		table.trace {
    			width : 100%;
    			border-collapse : collapse;
    			border : solid 1px black;
    		}
    		table.thead tr {
    			background : rgb(240,240,240);
    		}
    		table.trace tr.odd {
    			background : white;
    		}
    		table.trace tr.even {
    			background : rgb(250,250,250);
    		}
    		table.trace td {
    			padding : 2px 4px 2px 4px;
    		}
    	</style>
    </head>
    <body>
    	<h1>Uncaught <?= get_class( $ex ); ?></h1>
    	<h2><?= $ex->getMessage(); ?></h2>
    	<p>
    		An uncaught <?= get_class( $ex ); ?> was thrown on line <?= $line; ?> of file <?= basename( $file ); ?> that prevented further execution of this request.
    	</p>
    	<h2>Where it happened:</h2>
    	<? if ( isset($lines) ) : ?>
    	<code><?= $file; ?></code>
    	<ul class="code">
    		<? for( $i = $line - 3; $i < $line + 3; $i ++ ) : ?>
    			<? if ( $i > 0 && $i < count( $lines ) ) : ?>
    				<? if ( $i == $line-1 ) : ?>
    					<li class="line"><?= str_replace( "\n", "", $lines[$i] ); ?></li>
    				<? else : ?>
    					<li><?= str_replace( "\n", "", $lines[$i] ); ?></li>
    				<? endif; ?>
    			<? endif; ?>
    		<? endfor; ?>
    	</ul>
    	<? endif; ?>

    	<? if ( is_array( $ex->getTrace() ) ) : ?>
    	<h2>Stack trace:</h2>
    		<table class="trace">
    			<thead>
    				<tr>
    					<td>File</td>
    					<td>Line</td>
    					<td>Class</td>
    					<td>Function</td>
    					<td>Arguments</td>
    				</tr>
    			</thead>
    			<tbody>
    			<? foreach ( $ex->getTrace() as $i => $trace ) : ?>
    				<tr class="<?= $i % 2 == 0 ? 'even' : 'odd'; ?>">
    					<td><?= isset($trace[ 'file' ]) ? basename($trace[ 'file' ]) : ''; ?></td>
    					<td><?= isset($trace[ 'line' ]) ? $trace[ 'line' ] : ''; ?></td>
    					<td><?= isset($trace[ 'class' ]) ? $trace[ 'class' ] : ''; ?></td>
    					<td><?= isset($trace[ 'function' ]) ? $trace[ 'function' ] : ''; ?></td>
    					<td>
    						<? if( isset($trace[ 'args' ]) ) : ?>
    							<? foreach ( $trace[ 'args' ] as $i => $arg ) : ?>
    								<span title="<?= var_export( $arg, true ); ?>"><?= gettype( $arg ); ?></span>
    								<?= $i < count( $trace['args'] ) -1 ? ',' : ''; ?> 
    							<? endforeach; ?>
    						<? else : ?>
    						NULL
    						<? endif; ?>
    					</td>
    				</tr>
    			<? endforeach;?>
    			</tbody>
    		</table>
    	<? else : ?>
    		<pre><?= $ex->getTraceAsString(); ?></pre>
    	<? endif; ?>
    </body>
</html><? // back in php
}
set_exception_handler( 'global_exception_handler' );

class X
{
    function __construct()
    {
    	trigger_error( 'Whoops!', E_USER_NOTICE );		
    }
}

$x = new X();

throw new Exception( 'Execution will never get here' );

?>

8voto

Alex Weinstein Points 5839

Une chose à ajouter ici est sur la gestion des exceptions et des erreurs. Dans le but de le développeur de l'application, à la fois les erreurs et les exceptions sont de "mauvaises choses" que vous souhaitez enregistrer pour en savoir plus sur les problèmes que votre demande a - afin que vos clients une meilleure expérience sur le long terme.

Il est donc logique d'écrire un gestionnaire d'erreur, qui fait la même chose que ce que vous faites pour les exceptions.

6voto

evan Points 4825

Re: mais quelle est exactement la différence entre une erreur et une exception?"

Il y a beaucoup de bonnes réponses sur les différences ici. Je vais juste ajouter quelque chose qui n'a pas encore été parlé de la performance. Plus précisément, c'est la différence entre jeter/gestion des exceptions et la manipulation d'un code de retour (soit le succès ou une erreur). Généralement, en php, cela signifie le retour false ou null, mais ils peuvent être plus détaillées comme avec les fichier de téléchargement: http://php.net/manual/en/features.file-upload.errors.php Vous pouvez même retourner un objet d'Exception!

J'ai fait quelques séries de représentations dans différents langages/systèmes. En règle générale, la gestion des exceptions est d'environ 10 000 x plus lent que la vérification d'une erreur de code de retour.

Donc, si absolument, positivement besoins pour terminer l'exécution avant même d'avoir commencé - eh bien, vous êtes hors de la chance parce que le voyage dans le temps n'existe pas. Sans voyage dans le temps, les codes de retour sont l'option la plus rapide disponible.

Edit:

PHP est hautement optimisé pour la gestion des exceptions. Monde réel, les tests montrent que le lancement d'une exception est à seulement 2-10x plus lent que de retourner une valeur.

4voto

Lan Points 413

Je pense que la réponse que vous cherchez, c'est que;

Les erreurs sont la norme des choses que vous êtes habitué, comme en écho à un $variable qui n'existent pas.
Les Exceptions sont uniquement à partir de PHP 5 partir et venir lorsque vous traitez avec des objets.

Pour faire simple:

Les Exceptions sont les erreurs que vous obtenez lorsque vous traitez avec des objets. L'instruction try/catch vous permet de faire quelque chose à leur sujet cependant, et est utilisé comme le if/else. Essayez de faire cela, si problème, n'importe pas, faire.

Si vous n'avez pas "attraper" une exception, puis il se transforme en erreur standard.

Les erreurs sont le php regards croisés des erreurs qui habituellement d'arrêter votre script.

Try/catch est souvent utilisé pour établir des connexions de base de données comme AOP, ce qui est bien si vous souhaitez rediriger le script ou de faire autre chose si la connexion ne fonctionne pas. Mais si vous voulez juste pour afficher le message d'erreur et arrêter le script alors vous n'avez pas besoin, à l'exception non interceptée se transforme en une erreur fatale. Ou vous pouvez utiliser un site de gestion d'erreur.

Espère que ça aide

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X