laravel-actions icon indicating copy to clipboard operation
laravel-actions copied to clipboard

How to catch exceptions in handle methods

Open kai0310 opened this issue 2 years ago • 7 comments

Hey there 👋 Thanks for the great package.

I present here as an example a program that throws an error in a handle method and catches this error and displays it in a modal. This is the smallest example that presents this problem.

Minimum code ✍️

class CreateOrder
{
    use AsAction;

    /**
     * @throws CannotOrderItemException
     */
    public function handle(Item $item): Order
    {
        $unpaid = Auth::user()?->orders()->delivered()->notPaid()->count();

        if ($unpaid >= Order::MAX_ORDER) {
            return throw CannotOrderItemException::hasUnpaid();
        }
        
        // and create Order Object.....  
    }
}
try {
    $order = CreateOrder::run($this->item);
} catch (CannotOrderItemException $e) {
    // show error modal
}

What's at stake 🤧

The IDE will tell me that a CannotOrderItemException is never thrown within a try. This may be because execution is done only once via the run method. However, since it is not an independent run method, it is not possible to specify separately the exceptions that may be thrown. If I write code that throws exceptions in a handle method using Laravel Actions, how is it smart to resolve these? スクリーンショット 2022-03-13 17 43 22

kai0310 avatar Mar 13 '22 08:03 kai0310

@lorisleiva Oops. I forgot to mentions it.

kai0310 avatar Mar 28 '22 15:03 kai0310

This requires a little extra effort, but it should work:

class CreateOrder
{
    use AsAction;

    use \Lorisleiva\Actions\Concerns\AsObject {
        \Lorisleiva\Actions\Concerns\AsObject::run as parentRun;
    }

    /**
     * @see static::handle()
     * @param mixed ...$arguments
     * @return mixed
     * @throws CannotOrderItemException
     */
    public static function run(...$arguments)
    {
        return self::parentRun(...$arguments);
    }
    
    /**
     * @throws CannotOrderItemException
     */
    public function handle(Item $item): Order
    {
        $unpaid = Auth::user()?->orders()->delivered()->notPaid()->count();

        if ($unpaid >= Order::MAX_ORDER) {
            return throw CannotOrderItemException::hasUnpaid();
        }
        
        // and create Order Object.....  
    }
}

travisaustin avatar Mar 28 '22 23:03 travisaustin

@travisaustin Thanks! However, it is only a first aid kind of thing, and I don't think it is a smart thing to do.

kai0310 avatar Mar 29 '22 16:03 kai0310

What about registering it as a Laravel Exception and handling it there?

Wulfheart avatar Mar 29 '22 16:03 Wulfheart

@Wulfheart

Thank you very much. However, I still can't seem to figure out how to do that.

kai0310 avatar Mar 29 '22 22:03 kai0310

No idea. Just a hint for you...

Wulfheart avatar Mar 29 '22 23:03 Wulfheart

I think you shouldn't be throwing an exception, but instead returning a kind of 'Result' object.

jameshulse avatar Oct 18 '22 22:10 jameshulse

Ah, pretty good 👍🏻

I was feeling that throwing it as an exception would make the code more readable, but I guess I can solve it by returning a new object like a (e.g., Result) object! thanks

kai0310 avatar Oct 19 '22 04:10 kai0310

This is not a problem with this package, but with the PHPDocument specification. As such, I am closing this issue.

It seems we need to discuss how to use the package, not how to solve the problem as a package.

kai0310 avatar Oct 19 '22 04:10 kai0310