SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 70
  1. #1
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Write your own MVC with PHP

    this is the best MVC tutorial I came across so far,
    http://php-html.net/tutorials/model-...roller-in-php/

    I am new to MVC and I am still confused with the class Model and the class book in the example of that tutorial...

    for instance, I have my website and the content of my webiste is pulled from a database... so when I request a specific page for instance, http://www.mysite.com/index.php?pg=profile or with clean url http://www.mysite.com/profile

    so usually, I will get the content from the SQL query,

    $sql = "
    SELECT * FROM root_pages
    WHERE root_pages.pg_url = '".$_REQUEST['pg']."'
    ";

    so then should this $sql be put in the book class or model class??

    or this should be in the controller class actually?

    I have a directory folder which keeps all my CMS files, which contains update, insert, delete SQL queries, html forms, and pages that display the db items into lists, etc.

    so if I implement MVC on my website, then I am going to relocate these CMS files into different locations, like some in the model folder, and some in view folder and others in controller folder, is it correct??

    many thanks,
    Lau

  2. #2
    From space with love silver trophy
    SpacePhoenix's Avatar
    Join Date
    May 2007
    Location
    Poole, UK
    Posts
    5,014
    Mentioned
    103 Post(s)
    Tagged
    0 Thread(s)
    My own interpretation of MVC is (it may or maynot be technically correct but works for me):

    • Model Class: Contains all the queries, each function is one query, the return value either being the results or true/false depending on if the query run ok (mainly for updates and inserts).
    • View Class: I've recently changed how I do the view, now each function in the view class corresponds to a screen, the contents are concatenated into a string which is passed to the template for display, some of the information is grabbed from the model and/or controller as needed. Very limited processing (limited to checking if any results have been returned by a model, displaying one thing (usually something like "No matches found") or displaying the results as needed.
    • Controller Class: This does all the processing such as calculations passing data to and from model classes as needed.

    I use a single instance of a database class object which gets handed around to whichever model class needs to access the database.
    Community Team Advisor
    Forum Guidelines: Posting FAQ Signatures FAQ Self Promotion FAQ
    Help the Mods: What's Fluff? Report Fluff/Spam to a Moderator

  3. #3
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SpacePhoenix View Post
    My own interpretation of MVC is (it may or maynot be technically correct but works for me):

    • Model Class: Contains all the queries, each function is one query, the return value either being the results or true/false depending on if the query run ok (mainly for updates and inserts).
    • View Class: I've recently changed how I do the view, now each function in the view class corresponds to a screen, the contents are concatenated into a string which is passed to the template for display, some of the information is grabbed from the model and/or controller as needed. Very limited processing (limited to checking if any results have been returned by a model, displaying one thing (usually something like "No matches found") or displaying the results as needed.
    • Controller Class: This does all the processing such as calculations passing data to and from model classes as needed.

    I use a single instance of a database class object which gets handed around to whichever model class needs to access the database.
    thanks for sharing your practice, what is a single instance of a database class object?

  4. #4
    From space with love silver trophy
    SpacePhoenix's Avatar
    Join Date
    May 2007
    Location
    Poole, UK
    Posts
    5,014
    Mentioned
    103 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lauthiamkok View Post
    thanks for sharing your practice, what is a single instance of a database class object?
    The index.php page creates an instance of the database object, that database object is then passed (Aggregation) to both the page view and page controller classes via their constructors, the page view and page controller classes then pass (again via aggregation) to the view and controller objects respectivly. Both the view and controller objects create new instances of the model objects that they need, the model objects are passed the database object via their constructor.

    This keeps the number of open database connections at the same time down to a minimum (1 unless there is a problem) and cuts out the overhead of opening multiple database connections. I've also just switched the session management over to using the database.

    There may well be people who think that is the wrong way but that's the way I do it and it works for me.
    Community Team Advisor
    Forum Guidelines: Posting FAQ Signatures FAQ Self Promotion FAQ
    Help the Mods: What's Fluff? Report Fluff/Spam to a Moderator

  5. #5
    SitePoint Zealot
    Join Date
    Feb 2009
    Location
    Bristol
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's not strictly true

    The View recieves user input, which (in the context of web applications) is generally passed to the Model via the Controller.

    The Controller is little more than a traffic cop that co-ordinates the show.

    The topic of what the M in MVC means is pretty huge. First, you need to understand "the domain". The domain is the real world system you are "modelling" in your application, and your Model needs to embody this.

    So, if you were creating an app for air traffic management, you'd need Model classes to represent each of the entities in the system - i.e Employees, Passengers, Aeroplaines, Airports. Then you'd need Models to represent other, less easily discerned aspects of the domain, like Flight Plans, Accidents etc. Some of these elements might be what is called a Service - this code doesn't represent an object, but rather a service to help two Entities in your system interact. So, that's the basic concept of a Model, it embodies the BUSINESS LOGIC of the DOMAIN. The how is the next part.

    Model classes that are just OOP wrappers for database interaction are what is called "anemic domain models". Generally speaking, OOP wrappers around SQL calls are known as Transaction Scripts - they provide a convenient API for the Database Abstraction Layer (DBAL). There's nothing wrong with this approach, but it's not the true meaning of a Model (IMO). All object oriented methods for handling database interaction can be grouped under the term Data Access Objects - but just as all Dogs are Animals, not all Animals are Dogs. Within the field of Data Access objects, there are two principal patterns that you will see again and again.

    The first is Active Record (much loved by Ruby enthusiasts) in which each object in your system represents a 1:1 relationship with a table in your database. Some AR systems de-normalise data in their tables to allow for more complex objects to map to tables. The pattern is really simple, and it's easy to see why it's so popular.

    The other main pattern is Data Mapper (which comprises the core unit of Domain Model). DM aggregates data from several disparate tables, and "hydrates" the data into an object in your system. A Rich Domain Model will be able to handle generation of complex object graphs - objects which contain other families of objects and so on. The term ORM (Object Relational Management) relates to both patterns in practice, but in principle I think it only really applies to Data Mapper - since that pattern handles data relations more explicitly than Active Record.

    Confused? No problem - it is very confusing! There is a lot of controversy around the validity of ORM systems. OOP is intended to make code human readable - to embody human domain concepts in code. ORM's are an attempt to bridge the gap between that style of coding, and the relational nature of databases - with mixed degrees of success. One could argue that forcing OOP paradigms onto RDBMS is not a great use of code (much like forcing classical OOP paradigms into Javascript)

    My advice - create DAO's that embody your most common SQL transactions as functions. Then, create entities that can utilise these DAO's to embody behaviours. So a User object would have a Data Access class within it to handle CRUD stuff, but would also contain a bunch of methods not specific to data interaction.

    Hope that helps

  6. #6
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    989
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by sunwukung View Post
    ...
    The first is Active Record (much loved by Ruby enthusiasts) in which each object in your system represents a 1:1 relationship with a table in your database. Some AR systems de-normalise data in their tables to allow for more complex objects to map to tables. The pattern is really simple, and it's easy to see why it's so popular.

    The other main pattern is Data Mapper (which comprises the core unit of Domain Model). DM aggregates data from several disparate tables, and "hydrates" the data into an object in your system. A Rich Domain Model will be able to handle generation of complex object graphs - objects which contain other families of objects and so on. The term ORM (Object Relational Management) relates to both patterns in practice, but in principle I think it only really applies to Data Mapper - since that pattern handles data relations more explicitly than Active Record.

    ...
    Couple of points here:

    It's probably easier from both a development and readability for Active Record
    to handle complex objects (think $user->orders[1]->items[0]->product->name). The same can be achieved with Data Mapper, but there are more issues to overcome.

    On 1:1 mappings, I'd argue that if your database is designed sensibly to start with, a 1:1 object:table mapping is inevitable in most cases, even desired.


    As for MVC, you're right it's a layer in the system and contains all the business logic. However, it almost certainly cannot be represented by a single class. It will contain the business logic (which is often wrongly put in the controller) that accesses and manipulates entities within the system. All the data mappers, entities and business logic are part of this Model layer.

    One other thing I'd like to add here is that unlike some frameworks would have you believe (CakePHP i'm looking at you) there's no need for each controller to have a specific related model.

  7. #7
    SitePoint Zealot
    Join Date
    Feb 2009
    Location
    Bristol
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    Couple of points here:
    It's probably easier from both a development and readability for Active Record
    to handle complex objects (think $user->orders[1]->items[0]->product->name). The same can be achieved with Data Mapper, but there are more issues to overcome.
    For sure, I'm not advocating DM over AR. The more research you do into a Rich Domain Model, the more of a pain in the ass it seems to be (relative to a straightforward transaction script). Why go to such extraordinary lengths to hide the data store? ORM syntax often ends up being as verbose as a straight query!

    Quote Originally Posted by TomB View Post
    On 1:1 mappings, I'd argue that if your database is designed sensibly to start with, a 1:1 object:table mapping is inevitable in most cases, even desired.
    hmmm - While certainly desirable from the perspective of the ORM, I'm not sure you could maintain proper database normalisation.

    Quote Originally Posted by TomB View Post
    As for MVC, you're right it's a layer in the system and contains all the business logic. However, it almost certainly cannot be represented by a single class.
    Sorry, that wasn't what I was implying - the Model layer is indeed comprised of many Domain Objects (Model classes) and Services/Logic components to help with their interaction. This is the trouble with the M part of the MVC concept - the Model is a massive subject, the VC layer simply serves to expose the Model via the web interface. So easy to wrap up that particular headache in the DBAL acronym...

    Quote Originally Posted by TomB View Post
    One other thing I'd like to add here is that unlike some frameworks would have you believe (CakePHP i'm looking at you) there's no need for each controller to have a specific related model.
    Completely - you may as well put the logic in the controller - although if you don't successfully generate a Domain Model and fall back on Transaction Scripts you start to see something like that emerging - Model classes simply serving to delegate business logic out of the Controllers and becoming define by the actions/commands they correspond to, rather than the Domain component they represent.

    @lauthiamkok To bring it back down to earth - the Model can be as complex or as simple as you want, although you may find that what is simple at the beginning yields greater complexity at the end.
    The patterns discussed here are not vital to implementing a Model. They are just methods people have established in the past that have yielded a productive API. In layman's terms, the M in MVC is the part of your application concerned with doing the heavy lifting i.e. working out prices, getting records, updating records blah blah blah. The V and the C are simply the mechanism for interacting with it (which is where pre-rolled frameworks help).

    One example is form validation - some people advocate putting validation in the form itself, other people who prefer the ORM route put the validation in the Domain Objects. In practice, it's a bit simpler to put that stuff in the forms, but it's not as elegant. The point is, either way will work! That's why it can get confusing, there's a lot of ways to skin the MVC cat - but that's where the "design" part comes into play - it's almost an aesthetic choice.

  8. #8
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    989
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by sunwukung View Post
    hmmm - While certainly desirable from the perspective of the ORM, I'm not sure you could maintain proper database normalisation.
    Can you provide a real world example? The ORM will need to handle relationships anyway so as long as the relationships are set up I fail to see how keeping the entities 1:1 is an issue, even when tables are linked one-to-one. For example the classic order item - product link. What's wrong with doing $order->items[0]->product->name; rather than $order->items[0]->productName; I can't see any real benefit in the latter, it's just combining multiple records into one entity.


    Completely - you may as well put the logic in the controller - although if you don't successfully generate a Domain Model and fall back on Transaction Scripts you start to see something like that emerging - Model classes simply serving to delegate business logic out of the Controllers and becoming define by the actions/commands they correspond to, rather than the Domain component they represent.
    This is somewhere I've been struggling recently and had to do pretty much exactly this in some places...

    The problem is, where an action is affecting multiple entities, e.g. a "add reply" to a forum topic type scenario.

    There's a lot of logic here which has no clear place to put it:
    -the new post needs to be added.
    -a list of users who have asked for email notification of replies needs to be fetched
    -an email needs to be sent to those users

    All of this could be done in the controller, but then it's not reusable.

    Should the logic be put into the save routine (be it part of a mapper or on the Reply object itself in the style of active record)? This presents more problems:

    -It couples the Reply mapper to the User mapper so it can find the users
    -It couples the Reply mapper to the E-mailing script
    -It gives a save routine the ability to send out mails (!) this should not be desired functionality as it is not clear to anyone looking at the code. If I call $mapper->save($data); it should do only that. It's not very OO having a method perform multiple actions.

    So what's the alternative here? I just did exactly what you said above, moved the logic into its own class so that it's not in the controller, which gives me only re-usability as an advantage of having it in the controller. It does seem wrong, but so do the alternatives I can think of.

  9. #9
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SpacePhoenix View Post
    The index.php page creates an instance of the database object, that database object is then passed (Aggregation) to both the page view and page controller classes via their constructors, the page view and page controller classes then pass (again via aggregation) to the view and controller objects respectivly. Both the view and controller objects create new instances of the model objects that they need, the model objects are passed the database object via their constructor.

    This keeps the number of open database connections at the same time down to a minimum (1 unless there is a problem) and cuts out the overhead of opening multiple database connections. I've also just switched the session management over to using the database.

    There may well be people who think that is the wrong way but that's the way I do it and it works for me.
    Thanks for explaining this!

  10. #10
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sunwukung View Post
    My advice - create DAO's that embody your most common SQL transactions as functions. Then, create entities that can utilise these DAO's to embody behaviours. So a User object would have a Data Access class within it to handle CRUD stuff, but would also contain a bunch of methods not specific to data interaction.
    Thanks for this reply. There are a lot to take in! lol

    What does DAO stand for btw?

    Thanks!

  11. #11
    SitePoint Zealot
    Join Date
    Feb 2009
    Location
    Bristol
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lauthiamkok View Post
    Thanks for this reply. There are a lot to take in! lol

    What does DAO stand for btw?

    Thanks!
    1: I personally wouldn't advocate building your own ORM unless
    a) it's for academic interest
    b) you're a sucker for punishment
    c) you have a genuine new twist on the ORM concept

    2: As far as real world examples are concerned, I'd check out Redbean or Doctrine 2 (when it's launched). The former is built more along the Active Record lines, the latter seems to have more Data Mapper functionality.

    Active Record is just simpler to implement - since the object itself takes care of database interaction - and tends to look something like this:

    Code:
    $User = new User(1);//denotes id in user table
    $User->changeVariable($value);
    $User->save;
    Ideally there should be some mechanism to avoid this problem
    Code:
    $User = new User(1);
    $User2 = new User(1); //same record, different object
    $User->changeVariable($up);
    $User2->changeVariable($down);
    $User->save();
    $User1->save();// uh oh - you just wrote a new value by accident
    So you might have something like this instead to mitigate the problem. In this example, the Active Record class maintains an internal array of instantiated classes.
    Code:
    $User = ActiveRecord::load('user',1);
    $User = ActiveRecord::load('user',2);//same object, different reference variable
    $User->changeVariable($up);
    $User2->changeVariable($down);
    $User->save();//this will save $down
    $User1->save();// no change
    You would never see the users instantiated next to each other like this, but if you load the user in one part of the script, and it gets loaded again elsewhere - you can get this kind of problem.
    That doesn't even demonstrate memory management mechanisms to prevent thousands of records being hydrated into classes by default...

    DAO means Data Access Object -I fell into my own trap, it's a generic term for an object within the DBAL, Database Abstraction Layer. What I meant to say is wrap up your statements in a transaction script, and try and group them by purpose.

    I often just use an abstract DAO class to contain my most common transactions (a typical Transaction Script):
    Code:
    select, 
    selectID,
    selectWhere,
    selectFilter //allows for more complex queries
    insert,
    update,
    delete.
    The main purpose of the class is to automate sql generation and quote values. Subsequent DAO classes can extend that, and add custom SQL where required. Not very pure - but pretty simple way to organise the project.

    An alternative route would be to make a fluent interface class instead, with functions like select(), where(), order() so that you could dynamically build a statement using those methods instead. Zend_DB uses something like this (as well as offering Table Gateways, Row Gateways - just Google these names, they're simple patterns to understand.)

    Ultimately, you're not honour bound to use ORM if you don't want to, and in some cases it's just a hindrance. Mappers, Transactions, Active Records, whatever, just pick what works for your project.

  12. #12
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for explaining! I'm going to do further reading on these keywords (Mappers, Transactions, Active Records, ORM, DAO, etc)...

    Guess it could be rather difficult for some one with the designer background like me to get the hang of it in the beginning... :-)

    Thanks a lot! :-)

  13. #13
    SitePoint Zealot
    Join Date
    Feb 2009
    Location
    Bristol
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey, I just noticed you're a janner, me too, born in Freedom Fields...
    you need any help, just give us a shout. Seriously, don't bend your head with the Model concept - it's all a matter of how far down the rabbit hole you want to go...unless you're working in a team or on some massive Java app, you don't need to be a purist.

  14. #14
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by sunwukung
    My advice - create DAO's that embody your most common SQL transactions as functions. Then, create entities that can utilise these DAO's to embody behaviours. So a User object would have a Data Access class within it to handle CRUD stuff, but would also contain a bunch of methods not specific to data interaction.
    yes

    Quote Originally Posted by sunwukung
    1: I personally wouldn't advocate building your own ORM unless
    b) you're a sucker for punishment
    and… yes

    Quote Originally Posted by lauthiamkok
    What does DAO stand for btw?
    Data Access Object. Its just a class or series of class that organize data access methods. You create methods as you need them vs. having an automated system for generic tasks. With a DAO you have all the flexibility to model your domain as you choose without being tied down by automated methodology.

    Here is a really simple example of a DAO used to route requests:

    PHP Code:
    <?php 
    /*
    * Route data access layer 
    */
    class DAORoute extends DAO {
        
        
    /*
        * @param str module name
        * @param int sites id
        * @return array route data 
        */
        
    public function fetchRoute($strSitesInternalUrl,$intSitesId) {
            
    $strSQL sprintf(
                
    "SELECT * FROM NAVIGATION_LINKS WHERE sites_internal_url = '%s' AND sites_id = %s"
                
    ,$this->_objMCP->escapeString($strSitesInternalUrl)
                ,
    $this->_objMCP->escapeString($intSitesId)
            );
            
            return 
    array_pop($this->_objMCP->query($strSQL));
        }
        
        
    /*
        * @param int navigation links id
        * @return array route data 
        */
        
    public function fetchNavLinkById($intId) {
            
    $strSQL sprintf(
                
    "SELECT * FROM NAVIGATION_LINKS WHERE navigation_links_id = %s"
                
    ,$this->_objMCP->escapeString($intId)
            );
            
            return 
    array_pop($this->_objMCP->query($strSQL));
        }
        
    }
    ?>
    Each method there has been written to the resolve problems at hand in a fashion that takes reuse into consideration – nothing is automated.
    The only code I hate more than my own is everyone else's.

  15. #15
    SitePoint Wizard
    Join Date
    Apr 2007
    Posts
    1,399
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Yes, it's a must to understand MVC. From your original first post. Sounds like it should be named "How to use MVC?" vs How to write your own. I for one will not write MVC framework since there are many choices to pick from. Another reason to know MVC is that it's cross language platform. Sure~ each MVC framework has it's own flavor but the core of MVC is same.

  16. #16
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sunwukung View Post
    Hey, I just noticed you're a janner, me too, born in Freedom Fields...
    you need any help, just give us a shout.
    awww... great to know someone who is from the design/ artistic background and
    knows programming languages

    sure will keep coming here when I get stuck with these things

    Quote Originally Posted by sunwukung View Post
    Seriously, don't bend your head with the Model concept - it's all a matter of how far down the rabbit hole you want to go...unless you're working in a team or on some massive Java app, you don't need to be a purist.
    I am very excited in turning my php level to OOP and MVP. but I know that I cannot be a purist! lol

    thanks!

  17. #17
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sg707 View Post
    Yes, it's a must to understand MVC. From your original first post. Sounds like it should be named "How to use MVC?" vs How to write your own. I for one will not write MVC framework since there are many choices to pick from. Another reason to know MVC is that it's cross language platform. Sure~ each MVC framework has it's own flavor but the core of MVC is same.
    thanks for the opinion. I can understand your point. I know there are many frameworks out there we can use, just like there are many site builders like drupal, wordpress, etc.

    my personal problem is, probably I came from the design background, I find very difficult to use wordpress and drupal after many attempts. so I aim to write my own programme to run my website and my freelance websites.

    I find the CMS in wp and drupal are very over the top, one of my client hates it (wp's), and I don't know how to fix it when the site having an issue with wp system, so I tend to build my own CMS for myself and clients.

    I have learned so much by coding every from scratch on my own! of cos, forums like this help me a lot too!

  18. #18
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    after reading so many articles from online tutorials and posts from the forum about MVC,

    here is my 'MVC' that runs my wesite, I hope I am doing it correctly!??

    the files and codes are:

    index.php

    PHP Code:
    <?php
    include_once("config.php");
    include_once(
    "controllers/page_controller.php");
    include_once(
    "models/shared/db.php");
    include_once(
    "models/public/page_model.php");
    include_once(
    "models/public/page_entity.php");

    $controller = new page_controller();
    $controller -> invoke();
    ?>
    config.php

    PHP Code:
    /* Database connection details and params */
    # the host used to access DB
    define('DB_HOST''localhost');

    # the username used to access DB
    define('DB_USER''root');

    # the password for the username
    define('DB_PASS''****');

    # the name of your databse 
    define('DB_NAME''********'); 
    page_controller.php

    PHP Code:
    /**
     * This file handles the retrieval and serving of page
     */ 
    class page_controller {
        public 
    $page_model;
        
        public function 
    __construct()  
        {  
            
    $this->page_model = new page_model();

        } 
        
        public function 
    invoke()
        {
            if (!isset(
    $_REQUEST['pg']))
            {
                
    //if no special page is requested, we'll show the default page to Home
                
    $page $this -> page_model -> get_page('home');
                include 
    'views/site.php';
                
    //print_r($page);
            
    }
            else
            {
                
    //show the requested page
                
    $page $this->page_model->get_page($_REQUEST['pg']);
                include 
    'views/site.php';
                
    //print_r($page);
            
    }
        }

    page_model.php

    PHP Code:
    /**
     * The page Model does the back-end heavy lifting for the page Controller
     */
    class page_model {
        
        
    /**
         * holds instance of database connection
         */
        
    private $db;
            
        public function 
    __construct()
        {
            
    $this -> db = new _db(DB_HOST,DB_USER,DB_PASS,DB_NAME);
        }
        
        
    /**
         * fetch the page based on supplied request
         * @param string $pg
         * @return array $page
         */
        
    public function get_page($pg)
        {
            
    //filter the request and store it in the variale
            
    $pg_title strtolower(str_replace('-'' '$pg));
        
            
    //prepare query
            
    $sql "
                SELECT *
                FROM root_pages
                
                LEFT JOIN root_templates
                ON root_pages.tmp_id = root_templates.tmp_id
                
                WHERE root_pages.pg_url = '"
    .$pg_title."'
                "
    ;
           
            
    //execute query    and store the array in the variale
            
    $page $this -> db -> fetch_assoc($sql);
            
            
    //send it to the entity class and instantiate an object from it
            
    $page = new page($page);
            
            
    //return the result
            
    return $page;
        }

    page_entity.php

    PHP Code:
    /**
     * This is an entity class and it should be exposed to the View layer and represents the format exported by the Model view. 
     * In a good implementation of the MVC pattern only entity classes should be exposed by the model and they should not encapsulate any business logic. 
     * Their solely purpose is to keep data.
     */ 
    class page {
        public 
    $title;
        public 
    $content_1;
        public 
    $content_2;
        public 
    $content_3;
        public 
    $content_4;
        
        
    /**
         * fetch the array and keep the data in varibales
         * @param string $page
         */
        
    public function __construct($page)  
        {  
            
    $this -> title $page['pg_title'];
            
    $this -> content_1 $page['pg_content_1'];
            
    $this -> content_2 $page['pg_content_2'];
            
    $this -> content_3 $page['pg_content_3'];
            
    $this -> content_4 $page['pg_content_4'];
            
    //print_r($page);
        


    the result on the view page,

    PHP Code:
    <div id="body" class="align-center">

            <?php 
            
    echo 'Title: ' $page -> title '<br/>';
            echo 
    'Content: ' $page -> content_1 '<br/>';
            
    ?>
    </div>
    It works fine for me so far and I kind of like it!

    basically, my 'MVC' is developed from the tutorial here,

    http://php-html.net/tutorials/model-...roller-in-php/

    I hope it is a good guide line for a dummy like me!

    I still have another shopping cart class, do I have to re-work on it for MVC purposes??

    PHP Code:
    class _store 

        
    // seeing is this is the only function of the store class we might as well make it static 
        
    public static function get_store() 
        { 
            return new 
    SimpleXMLElement(file_get_contents(STORE_XML)); 
        } 


    class 
    _product

        
    // public variables are evil, make it private 
        
    private $_product null

        public function 
    __construct($id
        { 
            
    $store _store::get_store(); 

            foreach (
    $store as $product
            { 
                if (
    $product -> id == $id
                { 
                    
    $this -> _product $product
                    
    // we've now found the product, no need looking through the remaining products in the XML 
                    
    break; 
                }         
            } 

            if (
    is_null($this -> _product)) 
            { 
                
    // apperantly there is no product in the store with the given id 
                
    die ('Product with '.$id.' not found'); // or throw an exception, would be better 
            

        } 

        public function 
    get_price() 
        { 
            return 
    $this -> _product -> price
        } 
    }


    #shopping cart
    class _cart
    {
        
         private 
    $_contents = array();
         private 
    $_created;
         
         
    /**
          * The class constructor
          *
          */
         
    public function __construct() {
             
    $this->_created time();
         }
         
         
    /**
          * Add a product to the cart
          * @access public
          * @param $productID integer
          *
          */
         
    public function add_item($productID) {

             if (isset(
    $this->_contents[$productID])) {
                 
    $this->_contents[$productID]++;    
             } else {
                 
    $this->_contents[$productID] = 1;
             }
            
            
    //print_r($this->_contents);
         
    }
         
         
    /**
          * Remove product from cart
          * @access public
          * @param $productId integer
          *
          */
         
    public function delete_item($productID) {
             
             if (isset(
    $this->_contents[$productID])) {
                 unset(
    $this->_contents[$productID]);
             }
                 
         }
         
         
    /**
          * Change the quantity of a particular item held in the shopping cart
          *
          * @access public
          * @param integer $productID
          * @param integer $quantity
          */
         
    public function update_quantity($productID$quantity) {
             
    $this->_contents[$productID] = $quantity;
         }
         
         
    /**
          * Get all items currently in cart
          *
          * @access public
          * @return unknown
          */
         
    public function get_items() {
             return 
    $this->_contents;
         }
         
         
    /**
          * How many items are in the user's cart?
          * 
          * @access public
          * @return INTEGER
          *
          */
         
    public function count_items() {
             return 
    array_sum($this->_contents);
         }

         
    /**
          * Calculate the cost of all items in the cart
          * @access public
          * @return float
          *
          */
         
    public function calculate_cost() 
         {
             
             
    $cost 0.00;
             
             foreach(
    $this->_contents AS $id => $quantity) {
                 
    $product = new _product($id);
                
    $cost_string $product -> get_price();
                
    $cost_float "$cost_string0;
                
    $cost $cost + ($cost_float $quantity);
                 
    //$cost = $cost + ($product -> price * $quantity);
             
    }
             
             return 
    number_format($cost2);
            
    //return $cost_float;
             
         
    }
         

    Many thanks!
    Last edited by Mittineague; Jun 4, 2010 at 23:29. Reason: removing potentially sensitive information

  19. #19
    SitePoint Evangelist
    Join Date
    Dec 2008
    Location
    Plymouth, United Kingdon
    Posts
    449
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oddz View Post

    Data Access Object. Its just a class or series of class that organize data access methods. You create methods as you need them vs. having an automated system for generic tasks. With a DAO you have all the flexibility to model your domain as you choose without being tied down by automated methodology.
    thank you oddz for this...

  20. #20
    John 8:24 JREAM's Avatar
    Join Date
    Sep 2007
    Location
    Florida
    Posts
    1,508
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was writing one fairly simple and figuring out how a bootstrap is written, It looks like there are several ways to go about it -- I like the guy above who used invoke() and handled this through a class, I might try that but I'm just getting started so will have to see.

    I am using smarty also.

    index.php
    PHP Code:

    /** 
    *    Load Config 
    */
    require_once('config/paths.php');
    require_once(
    'config/database.php');
    require_once(
    'config/session.php');

    /** 
    *    Load Base MVC Objects
    */
    require_once('config/autoload.php');

    /**
    *    Check if an index() method exists in a class if no function is passed in the URI
    *    @param obj $object The created object based on the URI or default with no URI.
    */
    function try_default_method($object)
    {
        if (
    method_exists($objectDEFAULT_CONTROLLER_METHOD))
        return 
    $object->{DEFAULT_CONTROLLER_METHOD}();
        else
        return 
    false;
    }

    /**
    *    Handle URI (Bootstrap)
    *
    *    @param str $_GET[url] Set from .htaccess
    */
    if (isset($_GET['url'])) 
    {

    /**
    *    Create array of the URL
    *    @example    http://workspace/Controller/Function/Value
    */
        
    $url explode('/'$_GET['url']);
        
    $controller    $url[0];
        
    $function    = (isset($url[1])) ? $url[1] : NULL;
        
    $value        = (isset($url[2])) ? $url[2] : NULL;
        
    /** 
    *    Include the Controller and Instantiate it 
    */
        
    if (file_exists(CONTROLLERS."$controller.php"))
        {
            
    /** Create the Object */
            
    require_once(CONTROLLERS."$controller.php");
            
            
    $object = new $controller;
            
            
    /** See if there is a value before calling the Function    */
            
    if ($function != NULL)
            {
                if (!
    method_exists($object$function)) 
                {
                    echo 
    "
                        <h1>Error:</h1>
                        <b>function 
    $function()</b> does not appear to be 
                        inside the <b>
    $controller object.</b>
                        "
    ;
                    
    /** Stop PHP if the function doesn't exist */
                    
    exit;
                }
            
                
    /** Load the Value if it exists */
                
    if ($value != NULL)
                
    $object->$function($value);
                
                
    /** Otherwise do the function only */
                
    else
                
    $object->$function();            
            }
            
    /**
            *    If no function declared, 
            *    look for an index function and run it by default.
            */
            
    else
            {
                
    try_default_method($object);
            }
            
        }
        
        
    /** If Controller does not exist */
        
    else
        {
            echo 
    "<h1>Error:</h1> The file: <b>'".LIBRARY."$controller.php'</b> does not exist.";
            exit;
        }
        
    }
    /** 
    *    If no URL is passed in .htaccess, show a default Controller. 
    *    @desc Default controller is most likely 'index'
    */
    else 
    {
        if (
    file_exists(CONTROLLERS.DEFAULT_CONTROLLER))
        {
            require_once(
    CONTROLLERS.DEFAULT_CONTROLLER);
            
    /** Remove the .php extention */
            
    $DEFAULT_CONTROLLER_NAME basename(DEFAULT_CONTROLLER'.php');
            
            
    /** Load the Object */
            
    $object = new $DEFAULT_CONTROLLER_NAME;
            
    try_default_method($object);
        }
        else
        {
            echo 
    '<h1>Error:</h1> Your default controller: <b>'.CONTROLLERS.DEFAULT_CONTROLLER.'</b> does not exist.';
            exit;
        }


    autoload.php
    PHP Code:

    DEFINE 
    ('DEFAULT_CONTROLLER',    'index.php');

    /**
    *    The default method to run if a method is not defined
    *    @example This checks controller->index();
    */
    DEFINE ('DEFAULT_CONTROLLER_METHOD''index');

    /**
    *    Autoload Libraries into main Controller/Model
    */
    DEFINE ('AUTOLOAD_Database',    true);

    /** 
    *    Autoload Objects, Class names must match File names
    *
    *    @param array $sections Folders to scan for Classes
    */
    function __autoload($class)
    {

        
    /**
        * Do not neglect the trailing slash!
        * Add new subfolders here.
        */
        
    $sections = array(
            
    LIBRARY,
            
    LIBRARY.'database/',
            
    LIBRARY.'smarty/',
            
            );

        
    /** Iterate: Require each Object */
        
    foreach ($sections as $dir)
        {
            if (
    file_exists($dir $class '.php'))
            {
                require_once(
    $dir $class '.php');
                return;
            }
        }


    paths.php
    PHP Code:
    #
    # MUST INCLUDE TRAILING SLASH
    #
    DEFINE ('CONTROLLERS',    'app/controllers/');
    DEFINE ('MODELS',        'app/models/');
    DEFINE ('VIEWS',        'app/views/');
    DEFINE ('LIBRARY',        'libs/'); 
    database.php
    PHP Code:
    #
    # Database Information
    #
    DEFINE ('DB_HOST',        'localhost');
    DEFINE ('DB_NAME',        '********');
    DEFINE ('DB_USER',        'root');
    DEFINE ('DB_PASS',        ''); 
    libs/Controller.php (The base controller)
    PHP Code:

    class Controller
    {

    /**
    *    Load Smarty and Basics
    *
    *    @param object get_class($this) returns the child class for loading templates
    */
        
    public function __construct()
        {
            
    $this->smarty    = new Smarty;
            
    $this->smarty->compile_dir 'tmp/';
            
    $this->smarty->template_dir 'app/views/';
            
            
    $this->child_class strtolower(get_class($this));
            
            
    /** Load Database */
            
    if (AUTOLOAD_Database == true)
            
    $this->DB = new Database();

    /**
    *    This checks from session.php whether protected pages are on,
    *    if a page is not in the unprotected list, it will check the session.
    */        
            
    if (PROTECT_CONTROLLERS == true)
            {
                
    /** Create an array to check if the child class is unprotected */
                
    $arrUnprotected explode('|'UNPROTECTED_CONTROLLERS);
            
                if (!
    in_array($this->child_class$arrUnprotected))
                {
                    
    /** Do some Session checking */
                    
    if (isset($_SESSION['userType']) == 10)
                    echo 
    1;
                    
                    else
                    echo 
    'refresh to login';
                }
            }
            
        }

    /**
    *    Asssign a value Short Hand to Smarty
    *
    *    @param str $val Assignment name to call
    *    @param str $val2 Value of the Assignment
    */
        
    public function Assign($val$val2)
        {
            
    $this->smarty->assign($val$val2);
        }

    /**
    *    Smarty Function
    *
    *    @param str $page Use for a custom TPL to render
    */
        
    public function Render($page NULL)
        {
            if (
    $page != NULL)
            
    $this->smarty->display($this->child_class .'/'.$page '.tpl');
            
            else
            
    $this->smarty->display($this->child_class .'/default''.tpl');
        }


    app/controllers/index.php (example controller)
    PHP Code:
    <?php

    class Index extends Controller
    {

        public function 
    __construct() {    
            
    parent::__construct();
        }
        
        public function 
    index()
        {
            
    $this->Assign('intro''This is the home page');
            
    $this->Render();
        }
        
        
        public function 
    login()
        {
            if (isset(
    $_POST['login']) == 'jesse')
            {
                echo 
    'success';
            }
            else
                echo 
    'failure';
        }
        
        public function 
    register($do NULL)
        {
            
            
            
    $this->Assign('form'true);
            
            if (
    $do != NULL)
            {
                
    $this->Assign('form'false);
                
    $this->Assign('do'true);
            }
            
            
    $this->Render('register');
        }

    }
    Last edited by Mittineague; Jun 4, 2010 at 23:32. Reason: removing potentially sensitive information

  21. #21
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    JREAM - your use of defines makes me cringe, especially given that you put many security values in them:

    Quote Originally Posted by JREAM View Post
    database.php
    PHP Code:
    #
    # Database Information
    #
    DEFINE ('DB_HOST',        'localhost');
    DEFINE ('DB_NAME',        '********');
    DEFINE ('DB_USER',        'root');
    DEFINE ('DB_PASS',        ''); 
    Uhg... Learning from Wordpress' example I see.

    ----------------------------------------------

    ON topic - MVC is something I've practiced in most of my code since before I started writing PHP. In PHP with all the possible avenues of attack thanks to it being a on-the-fly interpreted language, MVC makes perfect sense and IMHO is how all code SHOULD be written.

    Though I prever to put the C FIRST, because the controller is what should be called FIRST! It goes hand in hand with my routing ALL requests through the root index.php - my controller. Also makes doing friendly URL's a hell of a lot easier later on since you can just redirect all calls to non-static files to index.php and explode $_SERVER['REQUEST_URI']...

    You have to think about the controllers job - it's traffic cop, an air traffic controller. It should decode the user request, load the appropriate models to process the data, and then handle the transfer of said data or responses for the requests to the view - in that order.

    That separation of tasks is also a perfect opportunity to harden the system by not using globals for everything. Even my index.php has everything wrapped in functions, a dummy wrapper for require_once that breaks scope of locals so values HAVE to be passed via the function handler (I usually do so by reference so memory use is kept under control) - even the database connection if you use PDO can be restricted in scope to local.

    SCOPE is very important if thinking security, especially in a scripted language... One of the whole reasons to use MVC is to keep you data processing isolated from the template. There is no reason for your View/Template to EVER need database access - so why would you pass the values to said functions or make them global in scope? Is it any wonder that EVAL and user uploads are such a risk?

    That's security programming 101 - never put security related info into globals or defines. It's also the number one mistake even many seasoned developers seem to make as if they've never even heard of the concept.

    In a lot of ways that is why I find many object based MVC's to in fact miss the point of using MVC in the first place, as they 'round robin' back and forth between the template and the data, - instead of just processing ALL the data, then showing all the data... and worse they store everything in the object in a manner at which it might as well all be globals in the first place! I've seen people claiming their code was MVC where the template (view) was even calling their object based data handlers directly. "Oh, but it's in an object so it's separate"

    COMPLETELY MISSING THE POINT. Calling the data handler is the CONTROLLERS job, not the VIEW'S... I would allow that the other direction, the MODEL calling the VIEW, but I really prefer a FULL separation of the two as neither should have access directly to each-others functionality or values. That's not just a security thing, that defeats the point of having them "separate" in the first place!

    It also doesn't help to load EVERY model as a single file on every call... That's loading tons of code that probably isn't even going to be executed... While that's not really an issue in a compiled language, PHP is interpreted and every piece of code has to go through the bytecode compiler, and consumes memory if run or not. This is more data to shove in/out of the cache on each request run or not, and in general why I dislike objects in interpreted languages with rare exceptions.

    ... and MVC does NOT need objects to work. Quite the contrary if you have at run-time includes available... Though yes, objects ARE nice to restrict scope, but if the class is globally available anyways, what's the difference between locals in a function and those in a object?

    Though I suppose my approach if you flowcharted it would be C > M > C > V. Controller processes the request, handles any security, calls the appropriate model which returns the output/data to the controller. It's then the controllers job to call the view/template. It does end up a bit more memory hungry than letting the Model call the View directly, but it generally runs faster since you can concentrate on each task instead of switching gears mid-processing from retrieving data to outputting data.

    Besides, RAM is cheap these days. When I can get a dedicated dual core atom 330 server with 2 gigs of RAM for $60/mo, I'm not sweating a little extra RAM overhead if it means less CPU overhead and more consistent disk access patterns.

    In a lot of ways it's like practicing separation of content from presentation in your HTML and CSS. Your template or the code behind the template has no business going to the database, and your database access has no business outputting results. Each has their own job, let them do it.

    I do kind-of break the controllers separation by letting it handle sessions, user logins and database connections - but I feel that's more true to the intent since the controller can then determine does the user have the rights to access the model - what models should even be ALLOWED access to the database, the data structure used to pass information, what PARTS of the data structure, etc, etc.

    In any case, it really is a better way of coding making everything simpler - from easy reskinning (to the point you can even let people use PHP in their skins with ZERO worries of them screwing up the data, so screw the overhead of 'templating systems' like smarty), to not having to wade through output to debug a data handling issue, to having your code end up more secure 'by default'.

  22. #22
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    989
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Quote Originally Posted by deathshadow60 View Post
    COMPLETELY MISSING THE POINT. Calling the data handler is the CONTROLLERS job, not the VIEW'S... I would allow that the other direction, the MODEL calling the VIEW, but I really prefer a FULL separation of the two as neither should have access directly to each-others functionality or values. That's not just a security thing, that defeats the point of having them "separate" in the first place!
    I'd argue that this is entirely wrong. The view SHOULD access the model and request what it needs. Without this, you lose the real power of MVC, it makes your controllers do far too much. If you're just displaying data there is no reason that the controller needs knowledge of the data. The controller passes the model to the view and the view requests the desired information.

    From the MVC article on wikipedia: "A view queries the model in order to generate an appropriate user interface (for example, the view lists the shopping cart's contents). The view gets its own data from the model. The controller may (in some implementations) issue a general instruction to the view to render itself. In others, the view is automatically notified by the model of changes in state (Observer) which require a screen update."

    In php it's slightly different and the model can't realistically perform a callback on the view because the view only ever has one state throughout its lifetime, but the principal stands.


    As an example, a simple forum. The controller would initialise the view and pass the model to it. The view would perform an action (predefined by the view) on the model... e.g. get the latest 20 posts. It would then display it. There's no reason for the controller to tell the model what the view requires, otherwise you're just adding an extra step.

  23. #23
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    As an example, a simple forum. The controller would initialise the view and pass the model to it. The view would perform an action (predefined by the view) on the model... e.g. get the latest 20 posts. It would then display it. There's no reason for the controller to tell the model what the view requires, otherwise you're just adding an extra step.
    See to me that defeats the point of having them "separate" in the first place. The "views" job is to show the data for user interaction. It shouldn't have access to the model - at that point you might as well go back to old-school spaghetti coding.

    But that's my problem with most peoples way of applying the MVC paradigm... but then you do have to adapt it to the nature of the application.

    Of course, a lot of my interpretation could simply come from my first 20 years of programming having drilled into my head "far calls bad... Far calls bad, avoid unnecessary procedures"

    So constantly handing off from view to model to view to model to view to model isn't exactly my idea of good programming. Let the controller figure out what we need, let the model get it, then have the view show it. Three simple steps.

    You do it the way you say (and many others approach it) the view ends up going to the model every five lines... I need the TITLE tag contents, call the model... I need the site title for the H1, call the model, I need to build the menu, call the model. I need to display the page contents, call the model, I need the stuff to generate in each side-bar item, call the model, display, call the model, display, call the model, display... Doesn't it make more sense to just let the controller tell the model "build this", let the model do it's job uninterrupted, then call the template to show everything? Worse it makes the VIEW control the logic flow of the application - which defeats the point of HAVING a controller in the first place!

    Though much of that re-interpretation of it comes from that there is no real-time interaction between the user and the page since we're generally talking websites. What's being requested is available to the controller the moment it's called, and it's not like the 'view' changes until you send a new page... So a lot of the things like going back and forth between view and model aren't even going to come up in your code (or at least shouldn't)

    Maybe I should come up with a cutesy acronym for my approach since it is a bit different? Controller, Acquisition, Show, CAS? Sounds good, reminds me of Close Air Support. Eh, not sure about the middle word. One of my problems with MVC is it's terminology isn't very clear... "model" is pretty damned vague, want to avoid that. Maybe CDS. Controller, Data, Show.

    How was it Wiezenbaum put it? "Any idiot with a primary school education can put out a whitepaper..."

  24. #24
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    989
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Well, while sometimes it 'feels' better to have the controller have exclusive access to the model. It seems cleaner to begin with, you have a nice one way data flow but you end up in a situation where the controller contains display logic. Should the controller be telling the view how many records to display or how to sort them? The view can have options set by the controller but when the controller is doing these kind of actions it severely reduces the re-usability of the view (every time you want to reuse it you have to perform the same requests to the model in each controller).

    By giving the view access directly to the model you no longer need to modify the controller when the client moves the goalposts requirements change. If you view needs to be modified to, for example "also put the billing address on the invoice" the view can request the address from the model without having to have it assigned by the controller... and every other controller which uses the view.

    It depends on whether you want thin views or thin controllers. I'd rather keep my controllers to a minimum as they're not going to be re-used. The more I keep out of the controller, the more code I can re-use.

    Edit: PHP makes MVC less intuitive because of the single request -> response method. If you think about it in terms of desktop application it makes more sense.

    Imagine a windows form, the controller initialises the model and the view, the view is populated from the model. The user modifies the data and presses save. Does this need to go through the controller? All the information is in the UI, if the view has access to the model it can simply send the data back to it. There's nothing new here, the controller has no real reason to do anything.

  25. #25
    Non-Member bronze trophy
    Join Date
    Nov 2009
    Location
    Keene, NH
    Posts
    3,760
    Mentioned
    23 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TomB View Post
    Well, while sometimes it 'feels' better to have the controller have exclusive access to the model. It seems cleaner to begin with, you have a nice one way data flow but you end up in a situation where the controller contains display logic. Should the controller be telling the view how many records to display or how to sort them? The view can have options set by the controller but when the controller is doing these kind of actions it severely reduces the re-usability of the view (every time you want to reuse it you have to perform the same requests to the model in each controller).
    Actually the DATA returned by the model should be telling the view how many to show... while the controller should be telling the model how many to get... since it's the controller. At least that's how I see it, YMMV. Controller says get this many, model says "ok, here's the data", controller says to view "here's the data, show it"

    You could MAYBE kick out the middle man of the controller getting the data and instead have the model say to the view "here it is, show it" - other way around doesn't make much sense to me since then it's not "view", it's doing the controllers job.

    Though in PHP I think of view as an output only element, since PHP, at least for writing web based software, is a "get it and show it" device without realtime interaction. To me the view shouldn't be handling input since again, that's the controller's job.

    It also means you can 'stack' results on the controller to be viewed all at once. Handy if you are working with a view not in sync with the data - that's not so much of a php application of it, as more when dealing with graphics like in OpenGL or DirectX, where if for example vSync is on or you are using a frame limiter, you might have the input and physics running full bore while only calling 'view' when the display is ready. Very common in multithreaded simulators where you want input, data and calculation granularity higher than the output.

    Part of the reason for that approach is the simple ability to throw out and use and entirely different view code without changing the logic structure of handling user input, data calculations, or data handling. You put any of that in VIEW and have VIEW calling it, you can't have them run unchained.

    Quote Originally Posted by TomB View Post
    By giving the view access directly to the model you no longer need to modify the controller when the client moves the goalposts requirements change. If you view needs to be modified to, for example "also put the billing address on the invoice" the view can request the address from the model without having to have it assigned by the controller... and every other controller which uses the view.
    where to me that's just another field to be shown, so the view code should be smart enough to iterate the data gathered by the model and say "ok, I need to show this too"

    Though admittedly, I have kind of a warped view on handling that.

    Quote Originally Posted by TomB View Post
    It depends on whether you want thin views or thin controllers. I'd rather keep my controllers to a minimum as they're not going to be re-used. The more I keep out of the controller, the more code I can re-use.
    Funny, I've got the exact opposite... more I can do the same way in the controller, the less my models have to do... More I do in the models, the less my view has to do.

    Since for me the view's only job is to take the data from an array and show it using semantic markup. It's why when I pull data I generally also pull it's TYPE. This is a text field, this is a date, this is a boolean - because what TYPE it is can be considered part of the data. That makes it so all the view has to do is format it with semantic markup.

    MY approach to building a webform follows this - I have an array in whatever .module.php that says what fields are present, what order they should be shown in, what type of field it is, is validation required - the template (view's) job is to go through that data and show it by type applying all the tags in a consistent manner. Again, WHAT's to be shown is the models job, HOW it's shown is the View's. (that same array is also used by the model to process the returned POSTDATA, and hooks are present in the markup in the form of classes so javascript validation could be applied as well).

    It's the Vinnie Barbarino approach. Who? What? Where?

    Quote Originally Posted by TomB View Post
    Edit: PHP makes MVC less intuitive because of the single request -> response method. If you think about it in terms of desktop application it makes more sense.
    I agree wholeheartedly with that, part of what I said above... and the approach you are saying is fine for event driven programs you put together in a RAD like the various visual languages (hell, it's pretty much HOW those work!). It breaks down in realtime applications, or as you noticed request/response ones which is why while you can still take the good ideas from it, in a lot of ways you have to change the picture a bit.

    ESPECIALLY if you take the differences between interpreted and compiled languages into account.


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
  •