MVC - Codeigniter - model-view-controller

Where should intermediate code be placed? (something that ins't just storing/retrieving data from DB nor processing requests/views)
For example,
Say I have Listings and I create CRUD functions in the model. These Listings may require more complex tasks such as pausing and resuming, which may require some time calculations, error setting, etc. Should these be placed in the model or should I wrap a simple model in a library and use that as a middleman for the model?
At the moment I'm thinking of using Drivers/Libraries and keeping models rather simple, except for some dynamic SELECT filters. I'm getting a bit confused though, since I'm guessing I'd probably have to recheck variables, dependencies, etc in the model after doing it in the library, yes?
I'd most likely either squish everything together in the model and check once or separate and check twice?

The general rule of thumb is:
1) Perform all business logic in the models.
2) Perform actions like a traffic cop would in controllers. (directing users to new views based on results of activities.)
3) Perform only presentational logic in views.
Anything else that you would like to do that would be considered, "intermediary", could reside in a Library or Helper.
It should be noted though that if you write a Library, don't forget to get an instance of the current CI object in your class so that you have it to use with your internal class methods.
class Your_lib {
$CI =& get_instance();
...
}
Hope that helps.

Related

In MVC, should the Model or the Controller be processing and parsing data?

Until now, in my MVC application, I've been using the Model mainly just to access the database, and very little else. I've always looked on the Controller as the true brains of the operation. But I'm not sure if I've been correctly utilizing the MVC model.
For example, assume a database of financial transactions (order number, order items, amount, customer info, etc.). Now, assume there is a function to process a .csv file, and return it as an array, to be inserted into the database of transactions.
I've placed my .csv parse function in my Controller, then the controller passes the parsed information to a function in the Model to be inserted. However, strictly speaking, should the .csv parsing function be included in the Model instead?
EDIT: For clarity's sake, I specifically am using CodeIgniter, however the question does pertain to MVC structure in general.
The internet is full of discussion about what is true MVC. This answer is from the perspective of the CodeIgniter (CI) implementation of MVC. Read the official line here.
As it says on the linked page "CodeIgniter has a fairly loose approach to MVC...". Which, IMO, means there aren't any truly wrong ways to do things. That said, the MVC pattern is a pretty good way to achieve Separation of Concerns (SoC) (defined here). CI will allow you to follow the MVC pattern while, as the linked documentation page says, "...enabling you to work in a way that makes the most sense to you."
Models need not be restricted to database functions. (Though if that makes sense to you, then by all means, do it.) Many CI developers put all kinds of "business logic" in Models. Often this logic could just as easily reside in a custom library. I've often had cases where that "business logic" is so trivial it makes perfect sense to have it in a Controller. So, strictly speaking - there really isn't any strictly speaking.
In your case, and as one of the comments suggests, it might make sense to put the CSV functionality into a library (a.k.a. service). That makes it easy to use in multiple places - either Controller or Model.
Ultimately you want to keep any given block of code relevant to, and only to, the task at hand. Hopefully this can be done in a way that keeps the code DRY (Don't Repeat Yourself). It's up to you to determine how to achieve the desired end result.
You get to decide what the terms Model, View, and Controller mean.
As a general rule MVC is popular because it supports separation of concerns, which is a core tenet of SOLID programming. Speaking generically (different flavors support/ recommend different implementations), your model holds your data (and often metadata for how to validate or parse), your view renders your data, and your controller manages the flow of your data (this is also usually where security and validation occur).
In most systems, the Single Responsibility Principle would suggest that while business logic must occur at the controller level, it shouldn't actually occur in the controller class. Typically, business logic is done in a service, usually injected into the controller. The controller invokes the service with data from the model, gets a result that goes into the model (or a different model), and invokes the view to render it.
So in answer to your question, following "best practices" (and I'll put that in quotes because there's a lot of opinions out there and it's not a black and white proposition), your controller should not be processing and parsing data, and neither should your model; it should be invoking the service that processes and parses the data, then returning the results of aforementioned invocation.
Now... is it necessary to do that in a service? No. You may find it more appropriate, given the size and complexity of your application (i.e. small and not requiring regular maintenance and updates) to take some shortcuts and put the business logic into the controller or the model; it's not like it won't work. If you are following or intend to follow the intent of the Separation of Concerns and SOLID principles, however (and it's a good idea on larger, more complex projects), it's best to refactor that out.
Back to the old concept of decomposing the project logic as Models and Business Logic and the Data Access Layer.
Models was the very thin layer to represent the objects
Business Logic layer was for validations and calling the methods and for processing the data
Data Access Layer for connecting the database and to provide the OR relation
in the MVC, and taking asp.net/tutorials as reference:
Models : to store all the object structure
View: is like an engine to display the data was sent from the controller ( you can think about the view as the xsl file of the xml which is models in this case)
Controller: the place where you call the methods and to execute the processes.
usually you can extend the models to support the validations
finally, in my opinion and based on my experience, most of the sensitive processes that take some execution time, I code it on the sql server side for better performance, and easy to update the procedures in case if any rule was injected or some adjustments was required, all mentioned can be done without rebuilding your application.
I hope my answer gives you some hints and to help you
If your CSV processing is used in more than one place, you can use a CI library to store the processing function. Or you can create a CSV model to store the processing function. That is up to you. I would initially code this in the controller, then if needed again elsewhere, that is when I would factor it out into a library.
Traditionally, models interact with the database, controllers deal with the incoming request, how to process it, what view to respond with. That leaves a layer of business logic (for instance your CSV processing) which I would put in a library, but many would put in its own model.
There is no hard rule about this. MVC, however it was initially proposed, is a loose term interpreted differently in different environments.
Personally, with CI, I use thin controllers, fat models that also contain business logic, and processing logic like CSV parsing I would put in a library, for ease of reuse between projects.

How to prevent duplication of code

We're currently developing an E-commerce site. We have a public and admin module.
Sometimes we offer the same functionality in both modules like viewing of products or creating of orders. But there are also some functionalities that is present in either public or admin like adding of products (which is in admin).
Our problem is that common functionalities lead to duplication of logic. We need to implement it in both modules.
One way of solving the problem is to make use of layers. So what we did was move the common logic into the Model. However, the controller is still duplicating codes like the one shown below:
public function invoice() {
$this->Invoice->create();
$this->Invoice->setCustomer($this->getCurrentUser);
$invoice_items = // get list of items from post
$this->Invoice->setItems($invoice_items);
$this->Invoice->save();
}
My question is, is it wise to create a webservice that will encapsulate this logic and you just have to call it from the admin and public modules..
How does Magento implement the public and admin panels. And how does it manage its logic..
I would recommend you not to do that. From your question, it is not exactly clear what sort of 'logic' are you referring to, but it does not seem too complex from your example. In general, business logic should be coded within the Model, controller, or Helper portions of the code. It can even reside in a separate extension as long as you set dependencies properly in the main xml file of the extension.
It seems that you may benefit from placing your logic in a helper class. The default helper file resides under /app/code/community/company/extension-name/Helper/Data.php. Then you can call the helper method anywhere in the backend (Block, Module, or controllers) by using this piece of code:
Mage::helper('extension-name')->getLogic()
Or you can call the same helper method from the view (phtml files) like this:
$this->helper('extension-name')->getLogic()

How to encapsulate web2py business logic?

I just found web2py a couple days ago, and have been reading the documentation and through the source of a few example applications. I want to start programming more in Python. It seems that my take on MVC is a little skewed from theirs [web2py community].
After learning and working with PHP (and the Kohana framework), I'm used to the thin controller - fat model principle, where all business logic is placed in the model and the controller does nothing more than delegate what methods to perform on the model, and then passes data onto the view for rendering. However, it seems that 99% of the applications I've seen for web2py have fat controllers (putting all business logic in the actions), and the models are nothing more than table/constraint definitions.
I'm pretty well set on my view of a model, and I would rather put the business logic in the models (for re-usability and DRY code) but I haven't seen any code online that does this, although, to be fair, I haven't found an ample amount of applications. Can somebody point me in the right direction.
To be clear, I would like to make my models actual classes and encapsulate all business logic and database interactions into explicit methods. Something along the lines of...
class Article(object):
def get_article(self, id):
# Retrieve article by id, using db instance
pass
def get_latest_articles(self, limit):
# Retrieve latest articles
pass
def get_hot_articles(self, limit):
# Retrieve hot articles, based on algorithm for "hot"
pass
def create_article(self, data):
# Insert article
pass
def define_tables(self):
# Define schema the web2py way
pass
I haven't found the right way to do this.
I'm not very well rehearsed on web2py, but I know there are a lot of features. The DAL, for instance, seems to be a very powerful feature which is tightly integrated with other helpers. I wonder if splitting my business logic as stated above would limit any of these features?
I think part of the difference is that web2py uses a DAL (database abstraction layer) rather than an ORM. You might find this explanation helpful. As it points out, in some cases, computed fields or virtual fields may do what you want. Also, some of the methods defined in your example class would be quite simple DAL statements and would probably not be worth writing methods for.
Of course, if you want, you can define classes and functions in your models (or modules) and simply call them from your controllers -- whatever works best for you.

CodeIgniter $this->load->vars($array)

CodeIgniter has a method $this->load->vars($array) that is ideally used in the parent Controller to provide global access to system variables directly in the view. For example:
$this->data['username'] = "john";
$this->load->vars($this->data);
Then in the view, you can easily access john by echoing $username.
My question is, is it possible to use $this->load->vars($array) from within a Model instead of a Controller? This will allow me to abstract away some details from my Controller, making it cleaner. What changes would I have to make to get this working? Would you recommend it; do you think it breaks MVC?
Also, I'm using Datamapper ORM, so my models actually extend the Datamapper object and not the Model object.
Thanks!
Is it possible to use $this->load->vars($array) from within a Model instead of a Controller?
As mentioned, yes you can do this, you can even load a view from a Model, or even run $this->load->vars() in a view and load yet another view.
This will allow me to abstract away some details from my Controller, making it cleaner.
This is like sweeping the dirt under the rug, it didn't go away - it just went somewhere else where you are bound to deal with it later.
Would you recommend it; do you think it breaks MVC?
It's not going to "break" anything, but it implies that maybe your concept of MVC is somewhat broken. If it has nothing do do with the data layer and everything to do with the view layer, it doesn't belong in the Model. There's a good chance there may be some other stuff that doesn't quite belong there as well...
I'm using Datamapper ORM, so my models actually extend the Datamapper object and not the Model object.
You may need to call get_instance() and assign it to a variable or class property for use in DM models, so you can access the Codeigniter object.
Example: $CI =& get_instance(); $CI->load->vars();
Suggestion:
Return the data from the Model in the simplest, most reusable form possible, and then assign it to the view variables in the Controller. If I'm hunting down the source of some variables in a view file, the last place I'd look for them is in the Model. You may end up revisiting this project in the future, so try to be consistent as much as you can, and stick to the suggested, expected practices.

CodeIgniter: Decision making for creating of library & helper in CodeIgniter

After developing in CodeIgniter for awhile, I find it difficult to make decisions when to create a custom library and when to create a custom helper.
I do understand that both allow having business logic in it and are reusable across the framework (calling from different controller etc.)
But I strongly believe that the fact that CI core developers are separating libraries from helpers, there has to be a reason behind it and I guess, this is the reason waiting for me to discover and get enlightened.
CI developers out there, pls advise.
i think it's better to include an example.
I could have a
class notification_lib {
function set_message() { /*...*/}
function get_message() {/*...*/}
function update_message() {/*...*/}
}
Alternatively, i could also include all the functions into a helper.
In a notification_helper.php file, i will include set_message(), get_message(), update_message()..
Where either way, it still can be reused. So this got me thinking about the decision making point about when exactly do we create a library and a helper particularly in CI.
In a normal (framework-less) php app, the choice is clear as there is no helper, you will just need to create a library in order to reuse codes. But here, in CI, I would like to understand the core developers seperation of libraries and helpers
Well the choice comes down to set of functions or class. The choice is almost the same as a instance class verses a static class.
If you have just a simply group of functions then you only need to make a group of functions. If these group of functions share a lot of data, then you need to make a class that has an instance to store this data in between the method (class function) calls.
Do you have many public or private properties to store relating to your notification messages?
If you use a class, you could set multiple messages through the system then get_messages() could return a private array of messages. That would make it perfect for being a library.
There is a question I ask myself when deciding this that I think will help you as well. The question is: Am I providing a feature to my framework or am I consolidating?
If you have a feature that you are adding to your framework, then you'll want to create a library for that. Form validation, for example, is a feature that you are adding to a framework. Even though you can do form validation without this library, you're creating a standard system for validation which is a feature.
However, there is also a form helper which helps you create the HTML of forms. The big difference from the form validation library is that the form helper isn't creating a new feature, its just a set of related functions that help you write the HTML of forms properly.
Hopefully this differentiation will help you as it has me.
First of all, you should be sure that you understand the difference between CI library and helper class. Helper class is anything that helps any pre-made thing such as array, string, uri, etc; they are there and PHP already provides functions for them but you still create a helper to add more functionality to them.
On the other hand, library can be anything like something you are creating for the first time, any solution which might not be necessarily already out there.
Once you understand this difference fully, taking decision must not be that difficult.
Helper contains a group of functions to help you do a particular task.
Available helpers in CI
Libraries usually contain non-CI specific functionality. Like an image library. Something which is portable between applications.
Available libraries in CI
Source link
If someone ask me what the way you follow when time comes to create Helpers or Libraries.
I think these differences:
Class : In a nutshell, a Class is a blueprint for an object. And an object encapsulates conceptually related State and Responsibility of something in your Application and usually offers an programming interface with which to interact with these. This fosters code reuse and improves maintainability.
Functions : A function is a piece of code which takes one more input in the form of parameter and does some processing and returns a value. You already have seen many functions like fopen() and fread() etc. They are built-in functions but PHP gives you option to create your own functions as well.
So go for Class i.e. libraries if any one point matches
global variable need to use in two or more functions or even one, I hate using Global keyword
default initialization as per each time call or load
some tasks are private to entity not publicly open, think of functions never have public modifiers why?
function to function dependencies i.e. tasks are separated but two or more tasks needs it. Think of validate_email check only for email sending script for to,cc,bcc,etc. all of these needs validate_email.
And Lastly not least all related tasks i.e. functions should be placed in single object or file, it's easier for reference and remembrance.
For Helpers : any point which not matches with libraries
Personally I use libraries for big things, say an FTP-library I built that is a lot faster than CodeIgniters shipped library. This is a class with a lot of methods that share data with each other.
I use helpers for smaller tasks that are not related to a lot of other functionality. Small functions like decorating strings might be an example. Or copying a directory recursively to another location.

Resources