I have regular use cases of PHP \Exception sub classes where I want to collect up data and then bundle it into a final error message. For example:
checking some data has contiguous days
$missing = new MissingAdjustmentDataException(''); $testDate = $period->getPreviousPeriod()->getEnd(); $z = 0; while ($testDate <= $period->getEnd() && $z < 500){ if (!in_array($testDate, array_column($activationRedemptionAdjustmentDays, 'effective') )){ $missing->addMissingRedemptionAdjustment($testDate); } if (!in_array($testDate, array_column($platformAdjustmentDays, 'effective') )){ $missing->addMissingPlatformAdjustment($testDate); } $testDate->add(new \DateInterval('P1D')); $z ; }
Then in my exception, I'm collecting the data in arrays:
class MissingAdjustmentDataException extends \Exception { private $missingRedemptionAdjustment = []; private $missingPlatformAdjustment = []; public function updateMessage() { $message = 'Missing Adjustment data: '; if ($this->missingRedemptionAdjustment){ $ra = []; foreach ($this->missingRedemptionAdjustment as $item){ $ra[] = $item->format('Y-m-d'); } $message .= 'RedemptionAdjustment: '.implode(',',$ra); } if ($this->missingPlatformAdjustment){ $pl = []; foreach ($this->missingRedemptionAdjustment as $item){ $pl[] = $item->format('Y-m-d'); } $message .= 'PlatformAdjustment: '.implode(',',$pl); } $this->message = $message; } public function inError() : bool { if ($this->missingRedemptionAdjustment || $this->missingPlatformAdjustment){ return true; }else{ return false; } } public function addMissingRedemptionAdjustment(\DateTime $dateTime){ $this->missingRedemptionAdjustment[] = clone $dateTime; $this->updateMessage(); } public function addMissingPlatformAdjustment(\DateTime $dateTime){ $this->missingPlatformAdjustment[] = clone $dateTime; $this->updateMessage(); } }
My main problem is that I cannot find a way to do the formatting of the message in a "lazy" way when $missing->getMessage() is called. It seems to have update $this->message inside the Exception every time I add a data point to the exception.
Is there a better way to do this?
CodePudding user response:
I've done something like this before. I don't recommend trying to force getMessage()
to do something different. I recommend implementing a getCustomMessage()
on your class instead. However, sometimes we just need to do what we need to do. So...
Because the getMessage()
function is final
in the Exception
class, in order to accomplish what you are doing you will have to write your own Base Exception Class. You will not be able to extend Exception
in any meaningful way to accomplish what you want in a single shot.
In other words write a new class that is a reflection of PHP's Exception class. As below
class MySuperAwesomeException implements Throwable {
// Re-implement all of existing Exception properties
/* Properties */
protected string $message = "";
private string $string = "";
protected int $code;
protected string $file = "";
protected int $line;
private array $trace = [];
private ?Throwable $previous = null;
//This is where you can write your getMessage()
final public getMessage(): string
// Re-write all of existing Exception methods or alter any as you see fit.
/* Methods */
public __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
final public getPrevious(): ?Throwable
final public getCode(): int
final public getFile(): string
final public getLine(): int
final public getTrace(): array
final public getTraceAsString(): string
public __toString(): string
private __clone(): void
}
For Reference: https://www.php.net/manual/en/class.exception.php
CodePudding user response:
You can execute updateMessage() while catching the exception
catch(MissingAdjustmentDataException $e) {
$e->updateMessage();
echo $e->getMessage();
}
You will find some advices and hacks in How to change exception message of Exception object?