I'm sure there are probably an infinite number of answers to this question given various scenarios so I'm really after what is considered best practice:
I'm developing a smallish app that handles bookings and payments. I'm using Stripe for processing the payments. These are just one-off payments, not subscriptions but along with it comes a bit of logic such as checking the StripeToken has not been submitted already, setting an API key, creating a charge and error checking. All in all it feel like the containing method for handling charges is very bloated.
What would be the best way to avoid this? Is this where repositories would come in useful or are they considered separate from the app? I know this is really how you interpret design patterns but I'm trying to get into the habit of separating concerns and developing in a forward-thinking way.
Do you use the cashier package for stripe ? Could handle a lot of code.
Anyway when using an external service like this, service classes are often the solution. Encapsulate the logic in a bare class which you inject in your controller.
Repositories are for a totally different purpose : getting things in and out the db.
Thanks, I had the feeling that the logic should live in its own class somewhere but wasn't sure if there was a standardised way to do this.
Most of the tutorials here always keep the controllers very slim. I know this is partly to do with the fact that the apps that are being built are pretty basic but it makes everything much more readable.
Update: no I'm not using Cashier. The only needs to make a one-off payment (without any registration) so I thought it might be best to use the stripe php library.
@chris_j Think about the controller as class just telling other classes what they should do. So here it will take your stripe service and tell it what it should do.
Sometimes it doesn't really matter that much where you put the other logic. Just take it out the controller and put it in a separate class, which might be called something like StripeBiller (for example).
Later on, if you don't like where you put it, you can change it. You might even change your whole directory structure.
The biggest improvement is gained by separating logic into distinct classes. Having an nice naming convention is secondary.
If you haven't already, you may want to watch Jeffrey's series on billing with Stripe.
My rule of thumb personally is: Six months later I need to add some functionality. How many files will I need to open to add it. If none, meaning add a class great. If one maybe two, good but maybe not the best option, but really depends. More then two I messed up some where. Views not included...
Services as a go between a repo and controller are great ways to accomplish this. Just like a model shouldn't mess with more then one table imo a repo should mess with more then one model. A controller just just pass methods around and a service should tie your repositories onto required methods together. My controllers call requests, middleware, one method, fire event listeners and direct views only.
I have worked on updated existing projects that utilize repos and command bus as a service layer by passing objects around. I personally not a user of command bus as it seems ridged and unnecessary if your using rep pattern anyways, but an option if you pass objects. Explicitly setting variables in a command bus imo is way to strict and ridged and breaks my rule above as it is almost guaranteed you'll open more then two files just to update a form input later.