skip to Main Content

I’am kind of new to laravel and currently working with pipelines. As I know, if one step inside the Pipeline fail, the whole Pipeline get stopped at that step. That is exactly what I want, so I’am fine with that.

But I want to handle the given Exception from the failing step. And now is the question, how? I can’t find anything about that..

So my code for the pipeline looks like this (e.g.):

final readonly class CreateInboundPlanPipeline
{
    public function __invoke(DataContainer $container, Closure $next): DataContainer
    {
        //Init Normalizer
        $normalizer = new FBAInboundNormalizer();

        //Do something with $container
        $items = json_decode($container->__get('initialrequest')->input('items'));
        $response = $normalizer->createInboundPlan($items, $container->__get('initialrequest'));

        if($response['success']){
            $extendContainer = $container;
            $extendContainer->inboundplanid = $response["inboundPlanId"];
            $extendContainer->currentOperationId = $response["operationId"];
        }else{
            throw new Exception($response["message"]);
        }

        return $next($extendContainer);
    }   
}


public function handle(): void
{
    $filledContainer = app(Pipeline::class)
    ->send($this->container)
    ->through([
        CreateInboundPlanPipeline::class,
    ])
    ->then(function(){
        //Action after Pipeline
        //e.g. fill a model or smth
    });
}

E.g. if "CreateInboundPlanPipeline" throws an Exception, how could I catch and handle it?
I found the function "handleException" inside the Pipeline, is that the proper way?
Would look like this?

$filledContainer = app(Pipeline::class)
        ->send($this->container)
        ->through([
            CreateInboundPlanPipeline::class,
        ])
        ->then(function(){
            //Action after Pipeline
            //e.g. fill a model or smth
        })
        ->handleException(function(){
            //Handle Exception here
        });

2

Answers


  1. You should be able to try/catch the pipeline.

    use IlluminateSupportFacadesPipeline;
    
    try{
    
        $data = Pipeline::send($whatever)
            ->through([
                TaskOne::class,
                TaskTwo::class
            ])
            ->thenReturn();
    
    }catch(MyException $e){
        
        // Handle however you want
    }
    
    
    Login or Signup to reply.
  2. The handleException() method is protected and therefore not to be called as pipe(), finally(), and then() passing a callable but to be overwritten by extending the Pipeline class similar to the handleCarry() method.

    As the default handleException() implementation just throws the exception (it would void the then($destination) $destination() invocation), you can handle any exception in the pipelines’ first pipe:

    $pipeline = app(Pipeline::class)
        ->send($this->container)
        ->pipe(function($passable, Closure $next) {
            try {
                return $next($passable);
            } catch (Throwable $e) {
                //Action after Pipeline has thrown
                //e.g. fill a model or smth
            }
        })
        ->through([
            CreateInboundPlanPipeline::class,
        ])
        ->then($destination = function($passable) {
            //Action after Pipeline
            //e.g. fill a model or smth
        });
    

    Discussion:

    As you are currently debugging a lot, you can then move that along step-by-step ("pipe-by-pipe") by putting it between other -‍>pipe‍(‍.‍.‍.‍) or -‍>‌through‌(‍.‍.‍.‍) calls.

    The finally($callback) will be invoked regardless if you catch, bubble or re-throw the catched throwable.

    If you always want to handle exceptions for a pipeline consider to create a subtype and implement the handleException() method, it offers more fine-grained exception handling during pipeline execution.

    In general it might be more beneficial to not handle exceptions at all and just let them pass through and make them void the pipeline and then handle failed pipelines at a different place.

    E.g. as the other answer by Bennett demonstrates, it is possible to try/catch the whole -‍>‌then() call, but similar as shown in the variation per pipe() here, there is not much use of it apart it shows a more fine-grained option of the same thing: PHP try/catch exception handling.

    It is perhaps better not to debug and instead let the pipeline throw and fail. Pipelines are well-designed for that.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search