#1
  1. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,660
    Rep Power
    171

    More on oop and mvc design


    Hi;

    I am trying to get into making a small mvc from start I have a few questions


    1 - When I use a framework I learned life gets much easier when I create 1 class per functionality! That way controllers almost never go over 50 lines of code. This as simple as it is, is completely different from class diagrams. I assume class diagrams note to place "everything" related to "customers" in customers class. That includes all methods. Please explain what is the right way! 1 controller per functionality Vs. all methods related to that "thing" in 1 class.


    2 - On creating uml class diagrams I read in several places: "Include all properties and methods in the class". Probably very naive thing to ask but what is the point of adding all attributes in the class in practise? Methods, understandable. They ARE going to be used as they are main functionalists and there is no point to a class without methods but, properties don't seem to be critical; at least for this example. Please show me what I am not getting.

    3 - This class below for example. When it comes to relationship between classes I am not clear. Is a class supposed to be a completely stand alone piece of code? Or is it ok the way I have done it? It is ok to get classes nested in each other. What determines the relationship between classes? In other words the methods here are communicating with other classes (views and models) and send / receive data between them.
    PHP Code:
    $this->view $this->load_view("view_customer")->display($this->customer_information); 
    I see a lot of different ways of writing classes on the web. Is my approach proper or is it going to get me into trouble once the code gets bigger? WHat should I consider before making methods from a class calling others? Here I am loading view and calling methods in the view.


    4 - How to deal with errors in this situations. I have commented out the lines where redirection or error notes are required. I am not sure what's the best way to deal with them. Please look at comments and tell me what is the proper way of handling such errors. For example compulsory argument not coming through.

    This is not complete working code, this is just the idea so please don't pick on security etc.
    PHP Code:
    require 'php_settings.php';
    require 
    'controller/Application_class.php';
    require 
    'controller/Customers.php';

    //SHow customer details
    $object_details = new customers();
    $object_details->get_details(5); 
    PHP Code:
    <?php 
        
    //Class customer
        
    class Customers extends application_class {
            
            private 
    $name;
            private 
    $email;
            private 
    $customer_information = array();
            private 
    $post_data = array();
            
            public function 
    get_details($id=NULL)
                {
                    if(
    $id==NULL || !is_numeric($id))
                        {
                            
    /* Handle error here? 1 - What is the best practise? Is it proper to handle the error 
                            in this controller or is it a better idea to validate somewhere else before sending $id here? */
                        
    }
                    else
                        {
                            
    $this->customer_information $this->load_model("model_customer")->customers_details($id);
                            
                            if(
    is_array($this->customer_information))
                                {
                                    
    $view $this->load_view("view_customer")->display($this->customer_information);
                                }
                            else
                                {
                                    
    /* What is the best way to show no results found? echo "No results found!";*/    
                                
    }    
                        }    
                }
                
            public function 
    edit_details($id=NULL)
                {
                    
    $this->post_data = array('name'=>$_POST['name'], 'email'=>$_POST['email']);    
                    if(
    $this->validate($this->post_data))
                        {
                            
    $this->customer_information $this->load_model("model_customer")->customers_update($this->post_data$id);
                        }
                    else
                        {
                            
    /* What is the best way to show errors? Redirect? load another view? Or something else?*/
                        
    }        
                }
                
            
    /*
             * List other methods related to this customer
             * customer_orders etc....
             * */        
        
    }
            

    ?>
    PHP Code:
    class model_customer
        
    {
            private 
    $data = array();
            public function 
    customers_details($id)
                {
                    
    //$sql = "";
                    //$this->data = db::results($sql);
                    //Create this array from database, but for now the database is not set so I make it manually:
                    
    $this->data = array('name' => 'Ben''email' => 'pmde@yahoo.com''address' => '102 / 198, GC 4217 Australia''phone' => '5598990900');
                    return 
    $this->data;
                }
        } 
    PHP Code:
    class Application_class
            
    {
                public function 
    load_model($model=NULL)
                    {
                        if(
    $model==NULL || !file_exists('model/'.$model.".php"))
                            {
                                
    /* What is the best way to show errors? echo "Model load Error?"; exit();*/
                            
    }
                        else 
                            {
                                include 
    'model/'.$model.".php";
                                return new 
    model_customer();
                            }        
                    }
                public function 
    load_view($view=NULL)
                    {
                        if(
    $view==NULL || !file_exists('view/'.$view.".php"))
                            {
                                
    /* What is the best way to show errors? echo "Model load Error?"; exit();*/
                            
    }
                        else
                            {
                                include 
    'view/'.$view.".php";
                                return new 
    View_customer();
                            }
                    }
                public function 
    validate($posted_data)
                    {
                        
    //Building validation class here
                    
    }        
            } 
    PHP Code:
    class View_customer{
        public function 
    display($data)
            {
                
    print_r($data);
                echo 
    "THis is view";    
            }

    Thank you
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    158
    Rep Power
    10
    1. Whichever you prefer. It's more about which you find easier to understand and maintain. One controller per functionality means you geet lots of controllers, which is not much cleaner than having large controllers.

    2. Diagrams are give you an overview of what you are building and leaving information out of the overview usually means that information well get messed up, forgotten about not designed proparly. For example; if you add the properties you will notice smells like identical properties that appear in many classes and should possibly by moved to a parent class. You may even find proparties that reeally should be a call to another class.

    3. I'm not sure I understand what you are asking.
    Classes are stand-alone code in the sense that a class is preferably black box thatyou put data into and get data out of. It should not make assumptions about the environment (except for the existance of other classes, think "autoloader")

    What you did seems fine to me, it's not my style, but if you're ok with the chained syntax then getting a view and displaying it using data from a method seems perfectly ok.


    4. As a general note: The point of having a default value for a method parameter is to allow the caller to call the method without providing a parameter. But you check the parameter and throw an error if the parameter has the default value. Effectively you are still not accepting callers to leave out the parameter, but instead of getting PHP's "missing parameter" error you throw a "bad value" error, which doesn't help for debugging.


    4a. If you want to know if the Id is valid *here* then it makes sense to check it *here*. Besides, there is no way of guaranteeing that any external validation has been done before the id is sent to this method (this method doesn't know where the ID came from)

    4b when an error occurs you'll want to display the fact to the user, so there should be some way to get the view to display the error. A simple echo would mess up the presentation to the user, stopping them from being able to navigate the site.
    if the error is not recoverable you could bail out using an exception, and rely on your main try/catch to handle the error elegantly.

    4c if a model doesn't exist there's only one thing you can do and that's bail out using an exception, and let whatever method called the load method to deal with the problem. Again, this method cannot, and should not display the error.
  4. #3
  5. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Location
    Saint-Petersburg, Russia
    Posts
    236
    Rep Power
    28
    If you are really interested in this whole matter, it would be of great help to learn java and ee / web development in java.

    Many Java-developers are kind of maniacs on program architecture etc - and you probably could learn good deal of strange things from here.

    I've tried one or two simpler PHP frameworks, but found that MVC idea here is often simplified.

    One of most common difference for java development is that there peoplde really do not like either "fat models" or "fat controllers" (while in PHP fat models and active records are popular).

    Your code is somewhat strange. What is "customers" and why they extend application? And why here is some "get_details"? Why "application" loads model and view?

    Most common design for complex applications I've seen includes some additional words so MVC looks like:
    - View - usually they are page templates;
    - Controllers - they serve preparing data (Model) for views;
    - Models - not necessarily same data as they are loaded from database - in many cases they could be temporary DTOs;
    - Services - business-logic classes invoked by controllers to perform any work on data;
    - DAOs - classes caring of storing and retrieving data entities from database;
    - Context - some class or mechanism which cares of linking controllers, services and daos between themselves etc.

    If you are really interested, I can show you very small framework (PHP) written by me from scratch to demonstrate this idea.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    158
    Rep Power
    10
    I've tried one or two simpler PHP frameworks, but found that MVC idea here is often simplified.
    PHP is an interpreted language with poor OOP support, you cannot and should not make your application more complex than it needs to be. And that's what you see in the frameworks; not so pretty solutions that, in the end, just work.
  8. #5
  9. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Location
    Saint-Petersburg, Russia
    Posts
    236
    Rep Power
    28
    PHP is an interpreted language with poor OOP support, you cannot and should not make your application more complex than it needs to be.
    I could not agree. Though I am professional java-developer, I tend to respect PHP for many features.

    Its OOP-implementation currently resembles javan OOP in most features. The same classes and interfaces, abstract methods. The same visibility levels (except 'default'), the same single-parent inheritance.

    Being an interpreted language, PHP allows a number of features not possible in java - mostly about dynamic generation of objects of unknown type. This is well seen in both persistence frameworks and web-service libraries. In java we are bound to pre-generate classes by WSDL etc.

    Of course I can name a number of serious disadvantages of PHP but I think it is not our goal now. But they are not about OOP
  10. #6
  11. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,660
    Rep Power
    171
    Originally Posted by Vinny42
    You may even find proparties that reeally should be a call to another class.
    Would you please show an example.
    Originally Posted by Vinny42
    Classes are stand-alone code in the sense that a class is preferably black box thatyou put data into and get data out of.
    Do you consider my controller stand alone?
    Originally Posted by Vinny42
    Besides, there is no way of guaranteeing that any external validation has been done before the id is sent to this method (this method doesn't know where the ID came from)
    What do you mean?
    Originally Posted by Vinny42
    4c if a model doesn't exist there's only one thing you can do and that's bail out using an exception, and let whatever method called the load method to deal with the problem. Again, this method cannot, and should not display the error.
    Is it ok to load models and views the way I have?
  12. #7
  13. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,660
    Rep Power
    171
    Originally Posted by rodiongork
    Your code is somewhat strange. What is "customers" and why they extend application? And why here is some "get_details"? Why "application" loads model and view?
    Hi;

    Customers is a class that looks after customers functionalities. For example login, display profile etc.

    applicaiton class loads models and views required.

    I have a central controller that almost all other classes share some of the methods. For example "loading view" is a task all classes will do.

    There is get_details because it loads customer's details. Not sure if me and you are on the same page or not.
  14. #8
  15. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,660
    Rep Power
    171
    Originally Posted by Vinny42
    PHP is an interpreted language with poor OOP support
    Really?
  16. #9
  17. Mad Scientist
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2007
    Location
    North Yorkshire, UK
    Posts
    3,661
    Rep Power
    4123
    PHP is an interpreted language with poor OOP support

    OOP in PHP came on leaps and bounds with PHP 5 (released nearly 10 years ago)

    5.3 added namespaces to help organise code and 5.4 introduced traits ('lateral inheritance', also called mixins in other languages)

    If you're looking for MVC, try to forget the view for the time being and consider this approach

    Front controller
    Set of Filters
    Secondary Controller
    Model

    Front controller => Understands the request, determines a filter list, kick starts the process (also called a router)

    Filters => modifies or shapes the request or response (or both)

    Secondary Controller => Does the actual business logic for the request. Communicates with modelled data

    Model => understands the application at a data level

    Then, here are some things I've faced:

    With this set up you can then use one of your output filters to sort out the view by running the data through a template or encoding it as json, xml, etc (depending on the request)

    When considering data, think about where data could come from (database, file system, user input) and consider interfacing these (create, read, update, delete (CRUD)) so you have a generic "data service". How will you add support for another database, would you want a default one?

    Consider using traits

    Try not to write include/require throughout your code and to use an autoloader instead (see the docs for spl_autoload)

    Consider maintaining a list of class names and file names for your autoloader, can you make it automatic?

    Consider making your own code generator for when you need a new package (model, controller, view classes)...then look at your boiler-plate code...can this be minimised? what's common? can it be abstracted to a trait? Do you need the initial code generator?

    Consider a form handling package (define, validate and render forms...build it to your data service interface)

    What about hooks/events and plugins? (see the observer pattern)
    I said I didn't like ORM!!! <?php $this->model->update($this->request->resources[0])->set($this->request->getData())->getData('count'); ?>

    PDO vs mysql_* functions: Find a Migration Guide Here

    [ Xeneco - T'interweb Development ] - [ Are you a Help Vampire? ] - [ Read The manual! ] - [ W3 methods - GET, POST, etc ] - [ Web Design Hell ]

IMN logo majestic logo threadwatch logo seochat tools logo