---
title: "Setting exceptions at the right place"
url: https://www.exakat.io/setting-exceptions-at-the-right-place/
date: 2019-09-26
modified: 2025-02-17
author: "dams"
description: "Setting exceptions at the right place : when you need to throw an exception somewhere else than the most useful line of code"
categories:
  - "Code auditing"
tags:
  - "debug"
  - "Exception"
  - "utility"
image: https://www.exakat.io/wp-content/uploads/2019/09/relocation.320.jpg
word_count: 704
---

# Setting exceptions at the right place

[![](https://www.exakat.io/wp-content/uploads/2019/09/relocation.320.jpg)](https://www.exakat.io/wp-content/uploads/2019/09/relocation.320.jpg)

## Exceptions at the line

[Exceptions](https://www.php.net/manual/en/language.exceptions.php) are configured with the file and line where they were thrown. This is the classic situation : the exception is thrown immediately where a problem is detected. 

## Exceptions at a wrong line

It is not always convenient to throw the exception in the code. In particular, when a new layer of code is added to handle common operations. After all, this is what functions and classes are for.

Here, the validation is exported to a separate function, so as to avoid repeating (and forgetting) the various exceptions. One significant drawback of this situation is that validateData() now centralizes all the exceptions. Every detected exception is thrown from this particular function.

Fatal error: Uncaught Exception: Id is missing id for Smith in /tmp/test.php:9
Stack trace:
#0 /tmp/test.php(3): validateData(...)
#1 {main}
thrown in /tmp/test.php on line 9

## A message to Exception

There is a solution to this problem : creating a custom exception. Exceptions, and all its native tree, are a good source of base exceptions. Most of the time, they are customized with a new message : 

Yet, the exception classes include a lot of properties, including file and line number. 

This way, the exception may be designing another place in the code than the one where the exception was thrown : 

The result looks like this : 

Fatal error: Uncaught Exception: Id is missing id for Smith in myfile.php:1000
Stack trace:
#0 /tmp/test.php(3): validateData(...)
#1 {main}
thrown in /tmp/test.php on line 9

## The right exception at the right place

You may notice that we only changed the file and line number with hard-coded values. This is not really helpful, since it doesn't designate any real code. Using the [magic constants](https://www.php.net/manual/en/language.constants.predefined.php) `__FILE__`and `__LINE__` leads to the same problem : it designates the current code, not the calling code.

The calling code, and its predecessors, is available with a call to debug_backtrace(). This native function builds the stack of calls that lead to the current execution. It returns an array of arrays : each contains the file, line, function or method, class and type of call. 

Here is the array, when [debug_backtrace()](https://www.php.net/manual/en/function.debug-backtrace.php) is called with the `DEBUG_BACKTRACE_IGNORE_ARGS`.

Array
(
[0] => Array
(
[file] => /tmp/test.php
[line] => 9
[function] => __construct
[class] => myException
[type] => ->
)

[1] => Array
(
[file] => /tmp/test.php
[line] => 3
[function] => validateData
)

)

We can now access the file and line we'd like to display : 

The resulting default error message is now pointing to useful coordinates. It may be personalized further with [__toString()](https://www.php.net/manual/en/language.oop5.magic.php#object.tostring) or a [getMessage()](https://www.php.net/manual/en/exception.getmessage.php) call, in the try/catch.

Fatal error: Uncaught Exception: Id is missing id for Smith in /tmp/test.php:3
Stack trace:
#0 /tmp/test.php(3): validateData(...)
#1 {main}
thrown in /tmp/test.php on line 9

## Wrapping up

Exceptions may be configured beyond simple messages : it is possible to customise the file and line number, and the message displayed when the exception is used with echo. This is much more convenient than the default behavior. 

Don't forget to [chain exceptions](https://www.php.net/manual/en/exception.construct.php) : always relay the previous exceptions to the newly created one, so that the whole chain of exceptions is available to the last receiver.