When you start developing software using objects (especially when those objects use Dependency Injection), you find that common functionality starts to gravitate into their own specialised classes that are reused. This makes maintaining and enhancing the software MUCH easier, and results in higher quality software.
Example:
Many applications use sessions, for storing all sorts of stuff. When all session data is managed by a specialised session manager class, all the code that is responsible for dealing with the session is kept in one place. If you want to change the way you application uses session data (perhaps to make it more secure, or more efficient), you only need to change code in one place.
I made the jump to OOP PHP three months ago and it is one of the best things I have done.
I started off with PHP Object-Orientated Solutions and have just finished Real-world Solutions for Developing High-quality PHP Frameworks and Applications. Both of those books have helped me a lot, and I highly recommend them.
The learning curve is quite high. But I guarantee, you will be glad you've turned to OOP.
Warning: The information in this posts is extremely outdated. It represents my understanding of MVC pattern as it was more then 2 years ago. It will be updated when I get round to it. Probably this month (2013.09).
Damn it! (2017.11).
Model itself should not contain any SQL. Ever. It is meant to only contain domain business logic.
The approach i would recommend is to separate the responsibilities, which are not strictly "business logic" into two other other sets of constructs : Domain Objects and Data Mappers.
For example, if you are making a blog, then the Model will not be Post. Instead most likely the model will be Blog , and this model will deal with multiple Domain Objects: multiple instances of Post, Comment, User and maybe other objects.
In your model, the domain objects should not know how to store themselves in database. Or even be aware of the existence of any form of storage. That is a responsibility of Data Mappers. All you should do in the Model is to call $mapper->store( $comment );. And the data mapper should know how to store one specific type of domain objects, and win which table to put the information ( usually the storage of of single domain object actually affects multiple tables ).
Some code
(only relevant fragments from files):
I assume that you know how to write a good constructor .. if you have doubts, read this article
nothing is namespaced in example, but it should be
anything that begins with _ in example is protected
domain object is responsible for validating the given parameters
view receives and decides how to present it
mapper takes the object and puts in it all the required information from storage ( it doesn't have to be DB .. it could be taken from some file, or an external REST API )
I hope this will help you understand the separation between DB logic and business logic ( and actually , presentation logic too )
Few notes
Model should never extend Database or ORM, because Model is not a subset of them. By extending a class, you are declaring that has all the characteristics of the superclass, but with minor exceptions.
class Duck extends Bird{}
class ForestDuck extends Duck{}
// this is ok
class Table extends Database{}
class Person extends Table{}
// this is kinda stupid and a bit insulting
Besides the obvious logic-issues, if your Model is tightly coupled with underlaying Database, it makes the code extremely hard to test (talking about Unit Testing (video)).
I personally think, that ORMs are useless and in large project - even harmful. Problem stems from the fact that ORMs are trying to bridge two completely different ways of approaching problems : OOP and SQL.
If you start project with ORM then, after short learning curve, you are able to write simple queries very fast. But by the time you start hitting the ORM's limitations and problems, you are already completely invested in the use of ORM ( maybe even new people were hired , who were really good at your chosen , but sucked at plain SQL ). You end up in situation where every new DB related issue take more and more time to solve. And if you have been using ORM based on ActiveRecord pattern, then the problems directly influence your Models.
Instead of that dreadful abomination, you should learn how to utilize spl_autoload_register():
spl_autoload_register( function( $classname ){
$filename = 'inc/classes/' . $classname . '.class.php';
if ( !file_exists( $filename) ){
throw new Exception("Could not load class '$classname'.".
"File '$filename' was not found !");
}
require $filename;
});
And you should register the autoloader in your index.php or bootstrap.php file, and do it only once per loader (this ability lets you define multiple loaders, but that's used, when you have third party library, which has own autoloader .. like in case of SwiftMailer).
P.S. please learn to use prepared statements with MySQLi or PDO.
Update
Since you are just now learning OOP, here are few things, which you might find useful:
PHP object oriented solutions http://www.amazon.com/dp/1430210117
i really enjoyed this book when i was getting rolling with php
One word: cohesion.
When you start developing software using objects (especially when those objects use Dependency Injection), you find that common functionality starts to gravitate into their own specialised classes that are reused. This makes maintaining and enhancing the software MUCH easier, and results in higher quality software.
Example:
Many applications use sessions, for storing all sorts of stuff. When all session data is managed by a specialised session manager class, all the code that is responsible for dealing with the session is kept in one place. If you want to change the way you application uses session data (perhaps to make it more secure, or more efficient), you only need to change code in one place.
I made the jump to OOP PHP three months ago and it is one of the best things I have done.
I started off with PHP Object-Orientated Solutions and have just finished Real-world Solutions for Developing High-quality PHP Frameworks and Applications. Both of those books have helped me a lot, and I highly recommend them.
The learning curve is quite high. But I guarantee, you will be glad you've turned to OOP.
Model
itself should not contain any SQL. Ever. It is meant to only contain domain business logic.The approach i would recommend is to separate the responsibilities, which are not strictly "business logic" into two other other sets of constructs : Domain Objects and Data Mappers.
For example, if you are making a blog, then the Model will not be Post. Instead most likely the model will be Blog , and this model will deal with multiple
Domain Objects
: multiple instances of Post, Comment, User and maybe other objects.In your model, the domain objects should not know how to store themselves in database. Or even be aware of the existence of any form of storage. That is a responsibility of
Data Mappers
. All you should do in the Model is to call$mapper->store( $comment );
. And the data mapper should know how to store one specific type of domain objects, and win which table to put the information ( usually the storage of of single domain object actually affects multiple tables ).Some code
(only relevant fragments from files):
_
in example isprotected
from
/application/bootstrap.php
from
/framework/classes/ModelFactory.php
file
/application/controllers/SomeController.php
file
/application/models/FooModel.php
I hope this will help you understand the separation between DB logic and business logic ( and actually , presentation logic too )
Few notes
Model should never extend Database or ORM, because Model is not a subset of them. By extending a class, you are declaring that has all the characteristics of the superclass, but with minor exceptions.
Besides the obvious logic-issues, if your Model is tightly coupled with underlaying Database, it makes the code extremely hard to test (talking about Unit Testing (video)).
I personally think, that ORMs are useless and in large project - even harmful. Problem stems from the fact that ORMs are trying to bridge two completely different ways of approaching problems : OOP and SQL.
If you start project with ORM then, after short learning curve, you are able to write simple queries very fast. But by the time you start hitting the ORM's limitations and problems, you are already completely invested in the use of ORM ( maybe even new people were hired , who were really good at your chosen , but sucked at plain SQL ). You end up in situation where every new DB related issue take more and more time to solve. And if you have been using ORM based on ActiveRecord pattern, then the problems directly influence your Models.
Uncle Bob calls this "technical debt".
Few books
loosely related to subject
Instead of that dreadful abomination, you should learn how to utilize
spl_autoload_register()
:And you should register the autoloader in your
index.php
orbootstrap.php
file, and do it only once per loader (this ability lets you define multiple loaders, but that's used, when you have third party library, which has own autoloader .. like in case of SwiftMailer).P.S. please learn to use prepared statements with MySQLi or PDO.
Update
Since you are just now learning OOP, here are few things, which you might find useful:
Lectures:
Books: