muharremozdemir
app/Exceptions/CustomExceptionInterface.php
interface CustomExceptionInterface
{
public function getId(): string;
public static function generateId(Throwable|string $class): string;
}
app/Exceptions/CustomException.php
abstract class CustomException extends Exception implements CustomExceptionInterface
{
public function getId(): string
{
return static::generateResponseCode(get_called_class());
}
public static function generateId(Throwable|string $class): string
{
$class = $class instanceof Throwable
? get_class($class)
: $class;
$name = (new ReflectionClass($class))->getShortName();
$name = str_replace('Exception', '', $name);
return Str::upper(Str::snake($name));
}
}
app/Exceptions/UserNotFoundException.php
class UserNotFoundException extends CustomException
{
public function __construct($message = "", $code = 404, Throwable $previous = null)
{
$message = $message ?: __("User not found.");
parent::__construct($message, $code, $previous);
}
}
app/Exceptions/Handler.php
// Kendime ait istisnaların otomatik raporlanmasını istemiyorum.
// Gerekirse ben kendim raporlarım:
protected $dontReport = [
CustomExceptionInterface::class,
];
app/Exceptions/Handler.php
public function register()
{
// ...
// Kendi ististianalarım json olarak dönecekse hepsine id ekliyorum.
// Böylece istek atan istemci 404 hatalarını ayırabiliyor.
$this->renderable(function (CustomExceptionInterface $e, $request) {
if ($request->expectsJson()) {
$data = [
'message' => $e->getMessage(),
'id' => $e->getId(),
];
return response()->json($data, $e->getCode());
}
abort($e->getCode(), $e->getMessage());
});
}
Kullanıma örnek olarak:
(çok mantıklı bir örnek değil ama maksat örnek olsun)
class UserService implements UserServiceInterface
{
public __construct(
public UserRepositoryInterface $userRepository
)
{
}
public function findOrFail(int $id): User
{
$user = $this->userRepository
->getBuilder()
->find($id);
if(!$user) {
throw new UserNotFoundException;
}
return $user;
}
}
public function show(Request $request, $id)
{
$user = $this->userService
->findOrFail($id);
return UserResource::make($user);
}
API isteği atıldığında ve User bulunamadığında:
404
{
"message": "User not found.",
"id": "USER_NOT_FOUND"
}
try...catch olarak
public function show(Request $request, $id)
{
try {
$user = $this->userService
->findOrFail($id);
} catch (Throwable $exception){
if($exception instanceof UserNotFoundException) {
// Burada bu istinasnaya özel bir işlem yapılabilir...
}
throw $exception;
}
return UserResource::make($user);
}
Yani aslında controller gibi Http katmanında direkt try...catch kullanmıyorum ama tüm istisnaları sanki try...catch kullanırmış gibi tek bir yerden yönetiyorum. Gerekirse ayrıca try...catch kullanabiliyorum, özellikle bir servisin içinde başka bir servis yöntemi kullandığım iç katmanlarda.