where to put business logic and others in MVC?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
raghavan20
DevNet Resident
Posts: 1451
Joined: Sat Jun 11, 2005 6:57 am
Location: London, UK
Contact:

where to put business logic and others in MVC?

Post by raghavan20 »

my questions are about where to put types of code in MVC model or do we need any more layer than the ones in MVC.
my questions may be bit unclear because i am unclear with a few concepts...

we know in a MVC model,
requests from pages and all logic may be business logic are handled by controllers
model takes care of database or other storage related fucntions
i am not really worried about views here

1. do you guys normally put all the DB or storage functions in model, if storage is file not DB

2. as in PHPCake, page requests, business logic and sending data to views are handled by controllers which i think is too much of work for controller instead i would say there should be a business layer to which the controller requests and business layer performs the actions, passes the result to the controller and the controller passes required data to the views

i would like to know how you guys split up application across layers and i would be happy if you can show your design model and explain them.


3. as in MVC, M can be used to perform load, save, disable & delete operations on object. let us take a CreditCard object, we can perform load, save, disable & delete in M but if i want some information like
3.1. list all cards that are disabled
3.2. is this card associated to atleast one order
3.3. list all master cards
where would you write all these functions. currently i have something called helpers which have their individual statements for each function to perform relevant functionalities but i still guess there should be a better place to put these. For this case, I have a CardHelper which will have functions as public static.


4. where will you put all your validation functions for a object. let us say you want to validate attributes in a card, where will you write this function. normally, validation is useful while saving object, but in some situations you might just want to verify the validity of the object, in such case this should accessible from everywhere. do you write this in CreditCard main class itself or anywhereelse?



5. do you guys ever write a SQL statement in a controller?

Thanks
User avatar
MrPotatoes
Forum Regular
Posts: 617
Joined: Wed May 24, 2006 6:42 am

Post by MrPotatoes »

personally i do all logic in the model. i'll use forums as an example

i want to show all forums like the index page to this place. there is a function that gets all the categories, forums and posts since last visit. from there i put it in order into an array and return that.

the controller gets all the information and gets the template, sets it, then displays it.

the controller gets the request from the HTTP/POST/URL and calls the controller, sets the template and BAM! done.

i'm thinking that i'm even going to put the form handling and validation within the model as well and leaving the controller as clean as possible. hmmmm

does that help any?
User avatar
raghavan20
DevNet Resident
Posts: 1451
Joined: Sat Jun 11, 2005 6:57 am
Location: London, UK
Contact:

Post by raghavan20 »

thanks for your reply.

i personally think and also from bigger examples i have seen, putting business logic in model will mess up as application grows. i am now personally taking out business logic out of model as it is ugly and become uneasy to handle it there.

model is supposed to do only kind of function, like doing operations on a database it does not really have to know how the business logic flows.

your controller logic is followed in many places but i think controller is doing much work than it should. i still have not studied how java beans are used, i want to use something like that where beans does all the business logic and some functions requests for business logic to be done and those requests should be visualized as from controller.

but still varied perspectives are welcome...
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

A lot depends on your definition of "business logic".

For example having a piece of logic which needs certain data using certain constraints (like selecting multiple forum posts posted on a specific date) is likely a Model method. You are retrieving data from a source. Whether that source is a database, a file cache, or an XML document is irrelevant - or should be in an ideal world, I'm not above putting small file store queries into a controller...so long as they are small, and limited to the current controller's action.

I view a Controller as the place where everything ties together. It's the heart of your workflow. When you reach a Controller you have to control when filtering, model calls, and view rendering takes place. The ease of use of the Controller is another matter. A Controller can be complemented by using additional helper objects like a Request, Response, various Chain/Filter objects (for example handling forms). In their absence a Controller can get complex and look a bit overworked. I have barely touched PHPCake, so don't quote me, but one would assume such objects are available?

3. as in MVC, M can be used to perform load, save, disable & delete operations on object. let us take a CreditCard object, we can perform load, save, disable & delete in M but if i want some information like
3.1. list all cards that are disabled
3.2. is this card associated to atleast one order
3.3. list all master cards
where would you write all these functions. currently i have something called helpers which have their individual statements for each function to perform relevant functionalities but i still guess there should be a better place to put these. For this case, I have a CardHelper which will have functions as public static.
Generally I look at the Model from two perspectives.

1) The CRUD actions: Create, Read, Update, Delete handled by an ORM or something of that simplistic nature
2) Modelled Logic: i.e. conditional selects, specific constraints, etc. - all bundled into Model methods utilising the ORM.

(ORM is likely optional - just another abstraction that's often worth having.)

Based on that view, your three credit card conditons would wind up in a Model class. Your CardHelper likely is just that. In my specific case I have a small ORM class that allows queries like:

Code: Select all

$creditCard = new Myapp_Credit_Card;
$creditCardCollection = $creditCard->getAll(); //array of Myapp_Credit_Card objects
foreach($creditCardCollection as $card) {
    echo $card->number, '<br />';
}
A query from your example (using some helper):

Code: Select all

class Myapp_Credit_Card_Helper {

// ...

    // non-static is another option - would reduce coupling
    public static function getCardByStatus($status) {
        $creditCard = new Myapp_Credit_Card;
        $creditCard->status = $status; // "disabled" or "enabled"
        return $creditCard->getAll(); // return array of objects for cards with given status
    }

// ...

}
As you might guess, I never write SQL in my controller if possible. I rarely even write SQL in my Models...;).
User avatar
raghavan20
DevNet Resident
Posts: 1451
Joined: Sat Jun 11, 2005 6:57 am
Location: London, UK
Contact:

Post by raghavan20 »

thanks maugrim for your reply.

i very well understand what functions you put under model and they are more similarly my current implementation.

now, let us take a business logic.
deleting an user who has cards, addresses, orders, etc.,
the business logic for deleting user will be

1. delete all cards associated to user
2. delete all addresses associated to user
3. delete all orders associated to user
4. delete all items for the user in shopping cart at DB
5. delete all saved items in DB for the user
6. delete the user from users table
7. do log of all the operations carried out and by who

this 7 steps process is a business logic flow. Now, where will you put this logic,,,in controller??

this can be called by many pages, like admin wanting to delete or customer wanting to unsubsribe...

if this logic of deletion is done in a business logic layer, a separate class,,any controller can send request and get the user deletion results and pass on to views for user output. i also think the business logic layer can call user model to delete user, orders, cart items, etc., and finally it can use a logger component to make a log. i also think you do not really do much SQL work in business logic, rather you ask model to do it.

my other important question is, which one do you actually call as controller...the page that gets GET and POST request for an action to be done or somethingelse?

i wld be interested in knowing your views on the above implementation...thanks
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I am definately no MVC expert, and I am still pretty new at it myself, but I will try to answer the best I can... if I'm wrong, somebody please correct me.

The way I see it, the view is the user interface--however the user interacts with your application, whether it be command line, html pages, or otherwise.

The model contains ONLY enough logic to explain itself. It gives the controller an api to work with it. It just provides a means to access the data you are trying to work with.

The controller lies the above all of this logic. It accepts requests from the view, and uses the methods and api supplied by the model to enter/extract data to then send back out to the view.
1. do you guys normally put all the DB or storage functions in model, if storage is file not DB
No... the model is not THE storage. I put the data in the database, and files in a filesystem... the model is merely a means of working with that data.
2. as in CakePHP, page requests, business logic and sending data to views are handled by controllers which i think is too much of work for controller instead i would say there should be a business layer to which the controller requests and business layer performs the actions, passes the result to the controller and the controller passes required data to the views
What you are proposing as a new layer is exactly what the controller is supposed to do. No need for a new layer. What would the controller do then?
i would like to know how you guys split up application across layers and i would be happy if you can show your design model and explain them.
Umm... I split it up like this... model, view, controller.
3. as in MVC, M can be used to perform load, save, disable & delete operations on object. let us take a CreditCard object, we can perform load, save, disable & delete in M but if i want some information like
I assume you're talking about credit card numbers in a database?
3.1. list all cards that are disabled
Then your model would have a method like findAll('`disabled` = 1') or findDisabled()
3.2. is this card associated to atleast one order
Then your model would have a method like findOrders() or hasOrder() maybe?
3.3. list all master cards
Model again with a method like findAll(`type` = 'mastercard') or findMastercards()
where would you write all these functions. currently i have something called helpers which have their individual statements for each function to perform relevant functionalities but i still guess there should be a better place to put these. For this case, I have a CardHelper which will have functions as public static.
This is model logic... it goes in the model
4. where will you put all your validation functions for a object. let us say you want to validate attributes in a card, where will you write this function. normally, validation is useful while saving object, but in some situations you might just want to verify the validity of the object, in such case this should accessible from everywhere. do you write this in CreditCard main class itself or anywhereelse?
Well a "credit card validation" class/library would go in a library directory... but where to call upon it is a good question... I may be wrong about this one, but I would call it from the controller...

Code: Select all

$card = new CreditCard($model);
if($card->isValid())
{
    $model->save();
}
5. do you guys ever write a SQL statement in a controller?
Never... sql goes in the model.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Ok, the last example pointed where you were heading...

If you take the C in MVC - it's usually a Controller. Now a Controller is not a single monolithic entity. You can have any number of Controllers, each of which can either be a standalone Command, or contain multiple Commands. That pattern is probably confusing so we'll call them Actions.

Now, good design practise dictates we do not duplicate code if at all possible. So you're quite right in believing common logic should not be duplicated on multiple Controllers. So what you're missing is that Model, View and Controller are separated layers. One should not determine the design of the other. Assuming this, you should have a single Action for the act of deleting card/user/etc. In any other Action where this is equally required - you should FORWARD to the central Action.

Once the central action has done it's job, it can forward again to a third Action (or even back to the first) to handle the View. A helper class is also a viable solution - so long as you realise it's essentially part of the Controller layer, just a more specific helper Controller for centralising duplicate code.

I don't think either option suggests more than the current MVC(+D) layers though...
User avatar
MrPotatoes
Forum Regular
Posts: 617
Joined: Wed May 24, 2006 6:42 am

Post by MrPotatoes »

Maugrim_The_Reaper wrote:As you might guess, I never write SQL in my controller if possible. I rarely even write SQL in my Models...;).
i have yet to put any SQL into my controllers. i would prefer to remove it out of the model but i need to learn more about ORM and it's speed constraints and things of that nature. i've very mindful of the speed it takes to get things done. rendering too :D
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

A reason MVC confuses is because the concepts of layers and separations are the most difficult things in software development -- and MVC is all about layers and separations.

For example, the question was asked about whether there should be SQL in the Controller. If you think about that question a little it might give you a better understanding of MVC, layers and separations. Let's say you have a PHP file called forum_controller.php. Ok ... it's called the controller, so what's in it must me controller code. Now you add some data base queries (and "SQL") into that file to fetch posts and pass that data to the View. That's not putting SQL or "business logic" into the Controller -- that's putting Model code and Controller code into the same file. And that is a design decision and you can certainly do that. You can mix Model code and Controller code together in the same function. That's called a Transaction Script (hey we implemented a pattern!) and implementing it is a design decision. And design decisions have an effect on things like flexiblity, maintainablity, speed of development, etc. One of PHP's strengths is that it makes writing Transaction Scripts very easy and it is a pattern that is appropriate for some solutions.

I guess what I am saying is that every application has Model code, View code and Controller code. The design decision is how to organise that code. If you want to implement the MVC pattern then you organize the application so that the Model code is clearly separated into the Domain Layer and is as independent as possible from everything but Datasource code. The View and Controller are in the Presentation Layer, and a separated so that the dependencies between them are clear. Usually the View is as independent as possible from everything but Model code. This can be done all in one file, in two files, three files or ten files. The Layers, Separations and Dependencies are there based on the design -- regardless of the file layout. Obviously making Layers and Dependency separations also align with file separations is very helpful. Conversely, having Layers and Dependency separation spill over file boundaries can cause problems in maintaining dependencies when things get mixed up.

I am also not sure that there has been a clear definition about the Model and View (forget the Controller for now) ... and it can me confusing because it is not always clear where to draw the line. Traditionally the Model is WHAT is to be displayed and the View is HOW it is to be displayed. That's not always helpful, but a good reality check on where the separation should be in web application is to imagine what code you would change to make the application output something other than HTML (e.g. PDF or CLI text). Everything that you would need to change to output to a different "device" is probably View code. The code you would not have to change is probably Model code.

However MVC takes things a step further because in the example I just gave, not all the code that you would NOT have to change belongs in the Domain layer. It's program flow code. So Controller code is code that is in the Presentation layer, but that probably does not change when the output device/viewer changes. If you switch from HTML to PDF that would be a separate View but the same Controller and Model probably.

The most important thing is to first think in terms of Layers and Separations so that your design is clean and clear. If you get those things right then fudging the exact line as to where the View/Controller boundary lies becomes the interesting/fun/challenging part.
(#10850)
User avatar
raghavan20
DevNet Resident
Posts: 1451
Joined: Sat Jun 11, 2005 6:57 am
Location: London, UK
Contact:

Post by raghavan20 »

thanks guys for your definitions...


i would appreciate if you can show frameworks of your application implementing MVC model.
User avatar
raghavan20
DevNet Resident
Posts: 1451
Joined: Sat Jun 11, 2005 6:57 am
Location: London, UK
Contact:

Post by raghavan20 »

Maugrim_The_Reaper wrote:
Once the central action has done it's job, it can forward again to a third Action (or even back to the first) to handle the View. A helper class is also a viable solution - so long as you realise it's essentially part of the Controller layer, just a more specific helper Controller for centralising duplicate code.

I don't think either option suggests more than the current MVC(+D) layers though...
can you explain me what do you mean by D?

I am glad that you understand that most of the times we repeat most of the main actions and they have to be centralized; now where will you put these code and what do you call this as?

EDIT: also i have a doubt what do you call these classes are and where will you put these classes into M or C not V anyway?

in a basic e-commerce application:
User class
Order class
Orderline class
Address class
Card class

basic helper classes:
FileHandler
DB class
FileUploader
Paginator
Post Reply