Obsługa wyjątków oraz return type

0

Cześć,
Piszę serwis dla entity Ticket i mam problem z wyjątkami. Jak jest najlepszy sposób na ich obsługę? Czy w serwisie powinienem tylko robić throw new Exception + return dane, ale bez zwracania message wyjątku, a w kontrolerze przechwytywać? Czy w poniższym kodzie jest dobrze zrobiona obsługa błędów? Zastanawiam się nad tym z racji tego, że dobrą rzeczą przy funkcji w serwisie jest dodanie typu zwracanego tzn:

public function add(array $ticketData, $author): Ticket

Tylko nie bardzo ogarniam to, czy powinien tutaj podać typ zwracanych danych olewając fakt, że może być rzucony wyjątek?

<?php

namespace App\Service;

use App\Entity\Ticket;
use App\Repository\TicketRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use Exception;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class TicketService
{
    /** @var TicketRepository */
    private $ticketRepository;

    /** @var EntityManagerInterface */
    private $entityManager;

    /** @var ValidatorInterface */
    private $validator;

    public function __construct(
        TicketRepository $ticketRepository,
        EntityManagerInterface $entityManager,
        ValidatorInterface $validator
    )
    {
        $this->ticketRepository = $ticketRepository;
        $this->entityManager = $entityManager;
        $this->validator = $validator;
    }

    public function add(array $ticketData, $author): Ticket
    {
        $subject = $ticketData['subject'];
        $description = $ticketData['description'];

        $ticket = new Ticket();
        $ticket->setSubject($subject);
        $ticket->setDescription($description);
        $ticket->setAuthor($author);
        $ticket->setStatus(Ticket::UNRESOLVED);

        $errors = $this->validator->validate($ticket);

        if (count($errors) > 0) {
            return (string)$errors;
        }

        try {
            $this->entityManager->persist($ticket);
            $this->entityManager->flush();
            return $ticket;
        } catch (Exception $ex) {
            return $ex->getMessage();
        }
    }

    public function update($ticketData, int $ticketId)
    {
        $subject = $ticketData['subject'];
        $description = $ticketData['description'];

        $ticket = $this->ticketRepository->find($ticketId);

        if (!$ticket) {
            throw new NotFoundHttpException('Ticket with id ' . $ticketId . ' does not exist!');
        }

        $ticket->setSubject($subject);
        $ticket->setDescription($description);

        try {
            $this->entityManager->flush();
            return $ticket;
        } catch (Exception $ex) {
            return $ex->getMessage();
        }
    }

    public function remove(int $ticketId)
    {
        $ticket = $this->ticketRepository->find($ticketId);

        if (!$ticket) {
            throw new NotFoundHttpException('Ticket with id ' . $ticketId . ' does not exist!');
        }

        try {
            $this->entityManager->remove($ticket);
            $this->entityManager->flush();
            return true;
        } catch (ORMException $e) {
            return false;
        }
    }

    public function getTicket(int $ticketId): ?Ticket
    {
        $ticket = $this->ticketRepository->find($ticketId);

        if (!$ticket) {
            throw new NotFoundHttpException('Ticket with id ' . $ticketId . ' does not exist!');
        }
        return $ticket;
    }

    public function getTickets(): array
    {
        return $this->ticketRepository->findAll();
    }

    public function changeStatus($ticketData, $ticketId): bool
    {
        $ticket = $this->ticketRepository->find($ticketId);
        $status = $ticketData['status'];

        if (!$ticket) {
            throw new NotFoundHttpException('Ticket with id ' . $ticketId . ' does not exist!');
        }

        $ticket->setStatus($status);

        try {
            $this->entityManager->flush();
            return true;
        } catch (Exception $ex) {
            return false;
        }
    }
}

oraz metoda add i update z TicketController

/**
 * @Rest\Post("/ticket")
 * @param Request $request
 * @return View
 */
public function add(Request $request)
{
    if ($request->getContent() == null) {
        throw new BadRequestHttpException('Request body cannot be null');
    }

    $ticketData = json_decode($request->getContent(), true);
    $user = $this->getUser();
    $result = $this->ticketService->add($ticketData, $user);

    if ($result instanceof Ticket) {
        return $this->view(['ticket_id' => $result->getId()], Response::HTTP_OK);
    }
    return $this->view(['error' => $result], Response::HTTP_BAD_REQUEST);
}

/**
 * @Rest\Put("/ticket/{ticketId}")
 * @param Request $request
 * @param int $ticketId
 * @return View
 */
public function update(Request $request, int $ticketId)
{
    if ($request->getContent() == null) {
        throw new BadRequestHttpException('Request body cannot be null');
    }

    $ticketData = json_decode($request->getContent(), true);
    $result = $this->ticketService->update($ticketData, $ticketId);

    if ($result) {
        return $this->view([], Response::HTTP_OK);
    }
    return $this->view(['error' => $result], Response::HTTP_BAD_REQUEST);
}
1

jaki wyjątek chcesz rzucać? ten co go łapiesz? to po co go w ogóle łapiesz?
a jak juz zwmieniać wyjątek na wartość zwracaną to na nulla a nie stringa

0

Tzn już chyba wiem co powinienem zrobić, napisać exception listener który mi ładnie sformatuje i złapie wyjątek :)

0

Zamiast robić takie coś:

$ticket = $this->ticketRepository->find($ticketId);

if (!$ticket) {
     throw new NotFoundHttpException('Ticket with id ' . $ticketId . ' does not exist!');
}

Możesz użyć param convertera. Zaoszczędzisz kilka linijek.

1 użytkowników online, w tym zalogowanych: 0, gości: 1