Skip to content

Commit

Permalink
Fix #324: Make BuildingException and NotFoundException friendly
Browse files Browse the repository at this point in the history
  • Loading branch information
np25071984 authored Jan 21, 2025
1 parent 56168c3 commit 911dbb0
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- New #380: Add `TagReference::id()` method (@vjik)
- Enh #384: Make `$config` parameter in `Container` constructor optional (@np25071984)
- Enh #324: Make `BuildingException` and `NotFoundException` friendly (@np25071984)

## 1.3.0 October 14, 2024

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"php": "^8.1",
"ext-mbstring": "*",
"psr/container": "^1.1|^2.0",
"yiisoft/definitions": "^3.0"
"yiisoft/definitions": "^3.0",
"yiisoft/friendly-exception": "^1.1.0"
},
"require-dev": {
"league/container": "^4.2",
Expand Down
21 changes: 19 additions & 2 deletions src/BuildingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@
use Exception;
use Psr\Container\ContainerExceptionInterface;
use Throwable;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;

/**
* It wraps all exceptions that don't implement `ContainerExceptionInterface` during the build process.
* Also adds building context for more understanding.
*/
final class BuildingException extends Exception implements ContainerExceptionInterface
final class BuildingException extends Exception implements ContainerExceptionInterface, FriendlyExceptionInterface
{
/**
* @param string $id ID of the definition or name of the class that wasn't found.
* @param string[] $buildStack Stack of IDs of services requested definition or class that wasn't found.
*/
public function __construct(
string $id,
private readonly string $id,
Throwable $error,
array $buildStack = [],
Throwable $previous = null,
Expand All @@ -32,4 +33,20 @@ public function __construct(

parent::__construct($message, 0, $previous);
}

public function getName(): string
{
return sprintf('Unable to build "%s" object.', $this->id);
}

public function getSolution(): ?string
{
$solution = <<<SOLUTION
Ensure that either a service with ID "%1\$s" is defined or such class exists and is autoloadable.
Ensure that configuration for service with ID "%1\$s" is correct.
SOLUTION;

return sprintf($solution, $this->id);
}
}
17 changes: 16 additions & 1 deletion src/NotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
use Exception;
use Psr\Container\NotFoundExceptionInterface;
use Throwable;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;

/**
* `NotFoundException` is thrown when no definition or class was found in the container for a given ID.
*/
final class NotFoundException extends Exception implements NotFoundExceptionInterface
final class NotFoundException extends Exception implements NotFoundExceptionInterface, FriendlyExceptionInterface
{
/**
* @param string $id ID of the definition or name of the class that was not found.
Expand Down Expand Up @@ -49,4 +50,18 @@ public function getBuildStack(): array
{
return $this->buildStack;
}

public function getName(): string
{
return sprintf('No definition or class found for "%s" ID.', $this->id);
}

public function getSolution(): ?string
{
$solution = <<<SOLUTION
Ensure that either a service with ID "%1\$s" is defined or such class exists and is autoloadable.
SOLUTION;

return sprintf($solution, $this->id);
}
}
9 changes: 9 additions & 0 deletions tests/Unit/BuildingExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public function testMessage(): void
$exception = new BuildingException('test', new RuntimeException('i am angry'));

$this->assertSame('Caught unhandled error "i am angry" while building "test".', $exception->getMessage());
$this->assertSame('Unable to build "test" object.', $exception->getName());
$this->assertSame(
<<<SOLUTION
Ensure that either a service with ID "test" is defined or such class exists and is autoloadable.
Ensure that configuration for service with ID "test" is correct.
SOLUTION,
$exception->getSolution()
);
}

public function testEmptyMessage(): void
Expand Down
7 changes: 7 additions & 0 deletions tests/Unit/NotFoundExceptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ public function testGetId(): void
$exception = new NotFoundException('test');

$this->assertSame('test', $exception->getId());
$this->assertSame('No definition or class found for "test" ID.', $exception->getName());
$this->assertSame(
<<<SOLUTION
Ensure that either a service with ID "test" is defined or such class exists and is autoloadable.
SOLUTION,
$exception->getSolution()
);
}

public function testMessage(): void
Expand Down

0 comments on commit 911dbb0

Please sign in to comment.