SitePoint Sponsor

User Tag List

Results 1 to 24 of 24
  1. #1
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    A question about the model (in MVC)

    Hi,
    In MVC (although I guess this doesn’t just apply to MVC) should my model classes/objects represent an entire database table, or an individual record in that table?

    For example, I have a table called “user”, and at the moment I have a class called “UserModel”, which extends the “Model” class. I guess it’s possible to manipulate the entire table and the individual records in one class, but something like this just doesn’t seem to make much sense in my mind:

    PHP Code:
    <?php

        $user 
    = new UserModel();
        
    $user->username 'test';
        
    $user->password 'password';
        
    $user->save(); // this would save those values as a new record
        
    $jack $user->findAll("username = 'jack'");
        
    ?>
    There is also the fact that the model does not have to be a database table does it? So in another model the whole idea of tables and records may not apply.

    Any comments would be greatly appreciated.

    Thanks,
    Jack

  2. #2
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Model represents a real business object. It's not just a data source. With that said, it can implement any of your said patterns and more.
    Saul

  3. #3
    SitePoint Enthusiast
    Join Date
    Sep 2005
    Posts
    55
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In MVC (although I guess this doesn’t just apply to MVC) should my model classes/objects represent an entire database table, or an individual record in that table?
    what you say above, and the code sample you gave, is essentially an Active Record, which simply is an object representing one row in the corresponding table. this is probably the most commonly used method of relating objects->data, as it is the simplest of the mapping patterns and for many is easiest to grasp/implement.

    There is also the fact that the model does not have to be a database table does it? So in another model the whole idea of tables and records may not apply.
    i highly doubt that you would mix a database and file system for your data/model, that would be silly for the reasons you mention above, why create extra hassle for yourself?

  4. #4
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by smithie View Post
    i highly doubt that you would mix a database and file system for your data/model, that would be silly for the reasons you mention above, why create extra hassle for yourself?
    Well, the data source can be as well a web service for example.
    Saul

  5. #5
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, I have been looking at active record, and that's where I got the idea of how to do it, what I don't really understand is why if an active record object represents a single row of a single table, why would you have a findAll method as part of that object? Surely it should be in another object, one that represents the whole table, rather than just one record?

    ** This is assuming the findAll method returns some sort of array of active record objects or something.

  6. #6
    SitePoint Enthusiast
    Join Date
    Sep 2005
    Posts
    55
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    http://www.martinfowler.com/eaaCatal...taGateway.html

    may help. then there's data mapper if you're feeling brave and dont mind doing some more complex work.

  7. #7
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jak-S View Post
    [...] what I don't really understand is why if an active record object represents a single row of a single table, why would you have a findAll method as part of that object? Surely it should be in another object, one that represents the whole table, rather than just one record? [...]
    Yes. Where did you come up with idea to name it findAll() as it does nothing but populates the model with data (single record).
    Saul

  8. #8
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm, well i've been reading through some rails tutorials, and from what I saw i thought findAll was use to do a query on the table with some conditions, the same as findByName is used to do a query but using one condition. I assumed it was part of the model object, but I guess not. Anyway, forget all that. This is what im going to do:

    My UserModel object will extend a class called Table, which will represent a database table, and have functions for querying that table for records (find, findByName etc.). The records that come back will be some sort of active record objects, and with those you can do things like modify one of the fields and then save it back to the database.

    What do you think?

  9. #9
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    virginia
    Posts
    188
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I haven't put much thought into this but what about something like this:

    PHP Code:
    $jack $user->username->findAll("jack"); 
    The usermodel class generates objects for each column in the database.

    PHP Code:
    Class UserModel
    {
        public 
    $username = new UserNameModel();

    If having the public var is considered bad practice then something like this maybe:

    PHP Code:
    $jack $user->UserName()->FindAll("jack"); 
    PHP Code:
    Class UserModel
    {
         private 
    $username = new UserNameModel();
         public 
    UserName()
         {
                return 
    $username;
         }


  10. #10
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jak-S View Post
    Hmm, well i've been reading through some rails tutorials, and from what I saw i thought findAll was use to do a query on the table with some conditions, the same as findByName is used to do a query but using one condition. I assumed it was part of the model object, but I guess not. Anyway, forget all that. This is what im going to do:

    My UserModel object will extend a class called Table, which will represent a database table, and have functions for querying that table for records (find, findByName etc.). The records that come back will be some sort of active record objects, and with those you can do things like modify one of the fields and then save it back to the database.

    What do you think?
    So you decided to use Table Gateway pattern (the link smithie posted). Yes, it is one way to do it. Keep in mind though that, as I said, Model is not the same as Data Source, and as mentioned previously, the source can be not only database. Thus your base Model class should not rely on one or another Data Source Architectural pattern.

    However, I think it is a common practice to do so, perhaps because of the nature of most web applications. So that's just my humble opinion.
    Saul

  11. #11
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by joflow View Post
    The usermodel class generates objects for each column in the database.
    What's the purpose of separate objects for each column?
    Saul

  12. #12
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There is never an easy, clear cut answer to this question I find, but for what it's worth I just have two generic class methods, *Record::get(); and *Record::getAll();

    What data is returned is upto how you build the SQL in regards to JOINs and WHERE clauses, etc on that Record, ie

    PHP Code:
    public function authenticate$username$password$is_hashed false ) {
                
    $username $this -> conn -> escape$username );
                
    $password $this -> conn -> escape$password );
                
    $this -> where"users.email = '".$username."'" );
                
    $this -> where"users.status = 'enabled'" );
                
                try {
                    
    $this -> get(); 
    ... 
    As to other patterns, I can't say that I've looked into the others in any depth; Well production script anyways as I tend to find that what I do use is enough.

  13. #13
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    virginia
    Posts
    188
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by php_daemon View Post
    What's the purpose of separate objects for each column?
    Good question...something about the 'username = jack' as a argument in the findall method bothered me.

    If you use an IDE with autocompletion...you wouldn't have to remember anything.

    plus couldn't it be used to models for datasources other then databases?

  14. #14
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by joflow View Post
    Good question...something about the 'username = jack' as a argument in the findall method bothered me.

    If you use an IDE with autocompletion...you wouldn't have to remember anything.

    plus couldn't it be used to models for datasources other then databases?
    A simple property would do, don't you think?
    Saul

  15. #15
    SitePoint Enthusiast
    Join Date
    Sep 2005
    Posts
    55
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by php_daemon View Post
    A simple property would do, don't you think?
    id second that. definitely overkill and unwise to have an object for each column. plus, think of the maintenance headache of such a system.

    most of the time, the underlying data storage is some kind of DB, and so active record (probably used by most; rails uses it also), table data gateway, and data mapper are available to you.

    FWIW (IMHO of course) active record/table data gateway will be more than sufficient for the average web app.

  16. #16
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    virginia
    Posts
    188
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by php_daemon View Post
    A simple property would do, don't you think?


    something like:

    PHP Code:
    $user->Select("username");
    $jack $user->findAll(); 
    That works.

    Sorry if I didn't understand your statement. I'm going back and forth with PHP and C#...and I sometimes mix the two. Properties in C# are formalized getters/setters..so I'm assuming this is what you meant by property.

  17. #17
    ✯✯✯ silver trophybronze trophy php_daemon's Avatar
    Join Date
    Mar 2006
    Posts
    5,284
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by joflow View Post
    something like:

    PHP Code:
    $user->SelectTable("username");
    $jack $user->findAll(); 
    That works.

    Sorry if I didn't understand your statement. I'm going back and forth with PHP and C#...and I sometimes mix the two. Properties in C# are formalized getters/setters..so I'm assuming this is what you meant by property.
    Not exactly. You can call them variables with no harm I guess, just that in OOP class variables are called properties. Yes, I know there's a distinction between the two in C#, but that's just something C# does for you. In PHP you still need the setters/getters only they are not formalized as in C#. And thus you have to call them manually instead of just assigning the value.

    What I mean:
    PHP Code:
    $user->setUsername("username"); 
    Saul

  18. #18
    SitePoint Zealot
    Join Date
    Dec 2004
    Location
    virginia
    Posts
    188
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm assuming that the user class would inherit from a DB class or own a DB object...since the SQL for setUsername(), setPassword(), setLocation(), setEmail() would be mostly the same.

    That seems to be about the best way to do it. Thanks for the insight.

  19. #19
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by php_daemon View Post
    So you decided to use Table Gateway pattern
    Yes, I think so seems like a good way to go, that way the methods to access lists of records and the methods to modify data of specific records would be in separate objects.

    Good question...something about the 'username = jack' as a argument in the findall method bothered me.
    What I really meant was something like this:

    PHP Code:
    $jacks $user->find("name = 'jack'"); 
    Where $user is an object representing the "user" table, and "username = 'jack'" is the condition that will be inserted into the WHERE clause of the SELECT statement. Therefore the find method will return an array of all user records where the name was jack.

    Thanks for everyone's help, if you think of anything else I would be happy to hear it.

  20. #20
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jak-S View Post
    PHP Code:
    $jacks $user->find("name = 'jack'"); 
    How about:
    PHP Code:
    $jacks $user->find(Array("name" => "jack")); 

  21. #21
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, well, just a different way to do the same thing, I actually have two methods now, one like this:

    PHP Code:
    $jack $user->find("name = 'jack'"
    And one like this:

    PHP Code:
    $jack $user->findBy('name''jack'
    Most of the time you will only need findBy(), but the point of find() is for specifying much more advanced conditions.

  22. #22
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The problem with your find() function is that you have to manually escape strings.

    If you want support for more complex queries, you could introduce a Query Object:
    PHP Code:
    $jacks $user->find(new Criterion("name""jack"CRITERION_EQUAL)); 

  23. #23
    SitePoint Enthusiast
    Join Date
    Jul 2006
    Posts
    80
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah i see what you mean, i will probably look into a query object at some point, but at the moment I'm just trying to get the basics of the table and record objects in, so i can at least start running basic queries and stuff.

  24. #24
    SitePoint Member
    Join Date
    Nov 2006
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    or just use parameterized queries, e.g. PDO can do parameterized queries

    PHP Code:
    $jack $userFinder->find("username = ?""jack"); 


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •