Correct way of implementing a service layer in CodeIgniter applications

Please note, this is not necessarily the correct way of doing it, but I'm going to explain how a framework like might typically do it and then you can learn about other methods and decide the best one for your use-case. Therefore, I do not expect this answer to be the correct one, but I hope it imparts at least a little knowledge on how things are done before someone who actually knows what they're talking about comes along and chimes in (also to those people - please feel free to edit / downvote this answer :D). Finally this also has nothing to do with CodeIgniter but frameworks in general. Your question should not only be framed as framework-agnostic, but language-agnostic also.

So I'm going to offer an opinion here and that is of the fact that all modern frameworks, specifically in PHP, do not do MVC. Why is this important? Because we all need to be speaking the same language, and 'mvc' does not exist in PHP. That's a fact. Accept that and then we can move forward onto the bastardization of the concept that frameworks use; and CodeIgnitor is a particularly great example of 'MVC' bastardization; henceforth known as "mvc" with quotes.

The plus side is that frameworks like Symfony, for example, provide an initial opinionated architecture that at least contains some form of consistency across the application, and it goes something like this:

  1. A standard HTTP request comes in and hits the front-controller, typically app.php or app_dev.php depending on whether or not you are in development or production; one involves a lot of caching that needs to be run on each change and the other doesn't - which is perfect for development.

  2. A router matches the current url to a controller class and an 'action' (method) within that class.

  3. The dependency injection part of the framework figures out what objects are needed for everything from the controller forward into the model layer and back, and either instantiates or prepares to instantiate them when needed.

  4. The controller is instantiated with any required dependencies and the relevant method is executed. This is typically where you would start your development and 'hook your code in' to the framework.

  5. This is where you decide on your architecture, however, the most important thing from both a developer perspective and business perspective (for lower costs for future maintenance) is consistency.

  6. I personally prefer to ensure my code is decoupled from the framework. I pass in scalars taken from the request into an application-layer service, which uses objects from the model layer (passed-in via DI) to use domain objects. The point here is that domain objects are not directly passed into the controller, they are proxied through an application-layer medium, so you can theoretically replace the entire framework surrounding this and still, all you need to do is pass those scalars into this layer before they hit the model layer and it'll all still work (think CLI calls, no more controllers).

  7. The application-level service uses any required Repositories, Services etc (and passes those scalars into them, remember the separation?), which perform business logic, (typically these are where your design patterns come into play on a day-to-day basis), and then return that data to the application-level service.

  8. The service then returns the data to the controller and guess what? This is where frameworks tend to fuck up! Because there is no concept of a "View" in today's frameworks. There is only a template, and you pass that data to a template and bam that's it. So in your diagram, there is absolutely no concept of a view because that's not how things are done. And to be entirely honest, I'm still using templates because they're the fastest way of doing things, but until modern frameworks get their shit together and actually start using Views, we're out of luck and have to remain steadfast when confronting the fact that some (like Laravel) refer to themselves as "mvc" frameworks.

Note, Fabien Potencier explicitly states that Symfony was not an MVC framework - at least he knows what he's talking about there. Again, this is not purist, it's important we're all speaking the same, factually correct language in computing.

So, because you like diagrams so much, here's how some might do it with today's frameworks...

architecture This is for an application that has the concept of a Review and Criteria for each Review. And don't even get me started on Symfony forms, they're so coupled to everything they're not a serious part of any architecture.

How many effing layers do you need? We already have "MVC", in DDD we have the concept of "Application", "Domain" and "Infrastructure" seperation, so get those two working together first, then this "service layer"? Do you really need another layer, or is the above enough? Things to think about...

Extra architecture

See, you're not stuck with the framework / http request to get the application going as a result of this separation.

See the "services" in the above diagram? They're separated from the controller so you can throw scalars from anywhere and the application will still work. I think this will give you the separation you need. It's great to do things the right way, learn how to do it, and then learn how to control yourself and be pragmatic about it when it comes to the business and it's needs, but frameworks need to sort their stuff out - and you certainly wont be writing lovely code with CodeIgniter ;)