Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

wkinne's avatar

Clean up large controller method

Hi!

I have a controller method that is very large but I am not sure the best way to clean it up.

There is a PurchaseController with one index method on it. This gets called when an order on the site happens.

My problem is theres a lot that goes on when an order happens. We validate the data, create or get a customer, get all the items, we either calculate a deposit or total amount paid depending on what they choose, send api calls to payment gateway, return errors if declined, then finally generate a PDF contract of the order and send emails.

So right now I just have a bunch of classes I create and that helps a bit but its still not very readable and testable.

When you have a bunch of different logic what is everyones opinion on the best approach? Maybe implement a repository and interface?

Any thoughts are very welcome!

Thank You

0 likes
4 replies
Drfraker's avatar

Sounds like you could be dispatching a few jobs on the queue to take care of the heavy lifting.

For example make a job called GeneratePdf. Your controller can dispatch that and move on to getting back to the user. You move all of that logic out of your controller and now you can dispatch that job from other parts of your code. :)

wkinne's avatar

Gotcha! Yea I was thinking that for the PDF generation and then I will fire an event to handle all the notification stuff.

I get a little confused on some of the simpler stuff. Like calculating discounts. Should that go on the order model or create helper functions for that?

Just trying to organize my logic properly.

Thanks for your feedback!

Drfraker's avatar

To me it depends on how complex your discounting logic is. If it is simple, leave in on the order model and have an applyDiscount method where you for example pass in a coupon code that gets checked for a discount amount. If it is complex and will grow more complex in the future you could separate it out into its own class called Discount and handle the logic there. Hard to say without seeing more. I would not create helper methods in a separate file, I'd make a dedicated class if it wasn't going to be in the order model.

biishmar's avatar

@wkinne validation: Use ValidateRequest Trait or for more freedom use form request (https://laravel.com/docs/5.6/validation#form-request-validation).

$this->validate($request,$rule)

creating or get customer: send the validated data to customer model and create or get. most likely get all item from here itself.

Customer::register($request)

Model Customer

public function register{
    static::firstOrCreate($request)
}

calculation and payment getway: create different method in the controller and move the code there for calculation and payment gateway return payment gateway response to post method. U can create method or can create class subscription

$this->subscription($request);

public function subscription{
    calculate and send the pay money to payment gateway and return to controller. 
}

PDF This is same as subscription can create method or class PDF

$this->registerpdf($request);

public function registerpdf{
    PDF::create or something ur code
}

Totally would be like..

Class Register

public function post {
    $this->validate($request,$rule);

    Customer::register($request);

    $payGateRes = $this->subscription($request);

    if(! $payGateRes) {
        return false or error msg
    }
    
    $pdfRes = $this->registerpdf($request);
    
    if(! $pdfRes) {
        return false or error msg
    }

    return true or success msg
}

Please or to participate in this conversation.