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

dpower's avatar

Best Practice Advice: Embed API implementation inside Model or elsewhere?

I'm creating a Laravel application in which each Client (model) can specify API connections to zero or more CRMs (of various species). For instance, a Client might have zero or more ActiveCampaign accounts, zero or more MailChimp accounts, zero or more Convert Kit accounts, etc.

I'll add new CRMs to the application over time.

Because both the API implementation and supported features (i.e. lists, tags, fields, notes, etc.) for each CRM can differ wildly, it makes intuitive sense to use a distinct Eloquent Model for each CRM. (NB: Cramming them all into a single model seems like a bad idea since I'll inevitably have to add fields to support new CRMs in the future. Tell me if you disagree.)

I've defined an abstract Interface with public methods to perform common CRM function... createContact(), addContactToList(), addTagToContact(), etc.

My question is this:

If each CRM is represented by its own Model, does it make sense to have the Model implement the interface (and related business logic)?

Or... should the implementation be handled by a distinct class that keeps the Model "clean" (i.e. separate from the business logic)?

Many thanks.

0 likes
5 replies
bugsysha's avatar

You shouldn't store any of the features in the database and control behaviour of the app with it. Have different implementations do that through polymorphism.

dpower's avatar

@bugsysha My explanation should have been clearer. I'm not storing CRM "features in the database" per se. I'm storing the Client's preferences in the database.

The crux of my question is whether I should embed business logic in the model or outside the model.

Let me know if I'm still not clear.

bugsysha's avatar

@dpower all of my understanding is based on assumptions so differences probably exist between your and my understanding what needs to be done. But still I don't see what kind of preferences? If they connect some service, or accounts as you call them, that should be the only thing that is in the database. Everything else should be abstracted and encapsulated through the code so it follows business logic.

Assuming you made a typo in business login and wanted to say business logic, I would say that it doesn't matter. If you do it properly by segregating, abstracting and encapsulating things well enough, both approaches will work without any issues.

From the codebase for the first version of Vapor made by Taylor Otwell you can see that he is using "model" approach, but in bunch of projects you can see how people make "outside of the model" approach also work. So not the best question in my opinion.

martinbean's avatar

@dpower You don’t need multiple Eloquent models. All of these services will let users authorise your app using OAuth. So, you let the user go through the OAuth flow and then Mailchimp etc will give you an access token. You store the access token for the service in your database. You then know if a user has connected X because you have an access token for it.

Most access tokens will also be transient (have a finite life) so you’ll also need to store the refresh token if you get one, and refresh the tokens server-side using task scheduling. If the user revokes the token via their say, Mailchimp account, you’ll usually receive a webhook so you can remove the token from your database.

For the actual interaction with these services, if you’re trying to use the same features from each (i.e. subscriber lists) then define an interface, then create individual service classes for each service that implements that interface but has an implementation specific for that service. This way, your application can just deal with methods defined by an interface and not worry about the actual implementation. If you need to change or add a new implementation, you can do so without touching any of your main application code.

dpower's avatar

@bugsysha Yes, I meant business logic. Apologies if the typo confused matters.

When I speak of "preferences" (i.e. another term I could have clarified better), I'm referring to specific CRM features the Client can optionally turn on or off. For instance, when a CRM API supports tagging, the Client may choose to leverage it through my app or not. Same goes for ecom transaction creation, note creation, custom field population, etc. The model needs to store the Client's preferences for each supported feature.

In any event, thanks for your feedback.

@martinbean Part of the issue is that each CRM supports a slightly different authorization method. Some use OAuth (as you've suggested). Others require an explicit API Key that needs to be copied and pasted from the CRM dashboard. Still others need a URL, Key, and Password. On top of that (as I've highlighted in my note to @bugsysha, above), each CRM supports a distinct feature set and I need to allow each Client to turn them on or off as they please and record their preferences.

There still may be rationale in designing a single, generic Eloquent model that handles all conceivable connection methods and feature set preferences. But the more I talk / write through this, carving each off each into its own model seems to make more sense. However, I remain open to feedback in the event I'm creating code that will be difficult for someone else to support going forward.

Thanks for sharing your expertise.

Please or to participate in this conversation.