I know that in OOP you want every object (from a class) to be a "thing", eg. user, validator etc.
I know the basics about MVC, how they different parts interact with each other.
However, i wonder if the models in MVC should be designed according to the traditional OOP design, that is to say, should every model be a database/table/row (solution 2)?
Or is the intention more like to collect methods that are affecting the same table or a bunch of related tables (solution 1).
example for an Address book module in CodeIgniter, where i want be able to "CRUD" a Contact and add/remove it to/from a CRUD-able Contact Group.
Models solution 1: bunching all related methods together (not real object, rather a "package")
class Contacts extends Model {
function create_contact() {)
function read_contact() {}
function update_contact() {}
function delete_contact() {}
function add_contact_to_group() {}
function delete_contact_from_group() {}
function create_group() {}
function read_group() {}
function update_group() {}
function delete_group() {}
}
Models solution 2: the OOP way (one class per file)
class Contact extends Model {
private $name = '';
private $id = '';
function create_contact() {)
function read_contact() {}
function update_contact() {}
function delete_contact() {}
}
class ContactGroup extends Model {
private $name = '';
private $id = '';
function add_contact_to_group() {}
function delete_contact_from_group() {}
function create_group() {}
function read_group() {}
function upd开发者_运维问答ate_group() {}
function delete_group() {}
}
i dont know how to think when i want to create the models. and the above examples are my real tasks for creating an Address book. Should i just bunch all functions together in one class. then the class contains different logic (contact and group), so it can not hold properties that are specific for either one of them.
the solution 2 works according to the OOP. but i dont know why i should make such a dividing. what would the benefits be to have a Contact object for example. Its surely not a User object, so why should a Contact "live" with its own state (properties and methods). Cause i tend to think like this: If something needs a state, then i create a OOP class so that the methods could affect the state or other things based on the state.
so should models be "stateful" too? if they require no state, why should i create it according to the OOP pattern. then i could just bunch it all together like the "package" solution.
you experienced guys with OOP/MVC, please shed a light on how one should think here in this very concrete task (and in general when creating a model)
EDIT: come to think about Controllers in MVC. they are created according to the "package" solution. It makes me wonder...
should every model be a database/table/row (solution 2)?
No. Don't tie the definition of a model to its method of persistence. Although for simple applications you might extend a model from a database row object, you should keep them at least mentally separated.
Models are simply representations of entities in your domain, so by necessity they have state. Where you talk about a Contact model, you are really talking about a mapper or gateway, i.e. the object retrieving your model from the data store. It's unfortunate that so many ad hoc implementations of Active Record have muddied the waters on this.
Mappers can be implemented as a collection of static functions or as an object - however, the collection is less flexible if you want to extend or alter the behaviour for any reason (such as mocking for unit testing).
The model itself should simply be a collection of data, either stored as public properties or preferably with appropriate setters and getters (please don't just define a get/set function pair for every variable or you might as well just leave them public), along with other methods that operate on the data. It should have no concept of, or dependency on, the data store. It is the responsibility of the mapper to instantiate and initialize the model through its interface. Doing this will afford flexibility in how you can create and save your models. You can do it from the database, an XML file, in-code, from a serialized stream sent in over the network, whatever floats your boat really, all by substituting a different mapper, and the model remains completely unaware.
I don't know if there's a best way, but i'll share the way i do it...
I have a table gateway e.g. ContactTableGateway that contains all the sql for dealing with contacts. I like all the sql being in one place.
class ContactTableGateway extends Model {
function saveContact( Contact $contact )
function getContact ( $contact_id )
function createContact ( Contact $contact )
}
Then i have a contact class that basically just has getters and setters ( or public properties ). Objects of this class are used as arguments for the table gateway to save/create
class Contact extends Model {
function getName()
function getAddress()
function getEmail()
....
}
Heres a simplified example
if ( isset( $_POST ) ) {
// some validation here
$contact = new Contact;
$contact->name = $_POST['name'];
$contact->email = $_POST['email']
$contactTableGateway = new ContactTableGateway;
if ( $contactTableGateway->createContact( $contact ) ) {
echo "YAY";
}
}
I think your Solution #2 is superior as it's more molecular/modular, therefore, more understandable, flexible and extensible (in the OOP domain). It's also more resource friendly as it could allow you to only have to load the Contact class when no contact group functionality is required and vice-versa. That is the benefit of division.
If models need no state, that does not mean OOP/MVC does not apply. Table models may have no state in one's design but that is why we have static methods/members, i.e., Contact::read($id).
精彩评论