SitePoint Sponsor

User Tag List

Results 1 to 25 of 25
  1. #1
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Trying out this MVC thing, few questions

    So, I am trying out building a simple MVC framework (just to learn about them and better understand how they work).

    I'm currently following this tutorial right here: http://www.phpit.net/article/simple-mvc-php5/

    So I have a file system that is something like this (modified the tutorial a bit):

    Code:
    public_html [ ]
    
    - classes [ ]
        -  base_controller.class.php
        -  registry.class.php
        -  router.class.php
        -  template_engine.class.php
    
    - controllers [ ] 
        -  index_controller.class.php
            - tpl [ ]
                - index.tpl.php
        -  registration_controller.class.php
            - tpl [ ]
                - registration.tpl.php
        -  user_controller.class.php
            ....
    
    - tpl [ ]
        - global.tpl.php
    
    - index.php
    Now, I am just wondering where to place tihngs. If for example, I want to add a class that contains some supporting functionality for registration (registration_controller.class.php), or login class (user_controller.class.php) where would I place these files?

    Also, currently the framework provides DB and Template engine access to all the controllers. But say I wanted to add some support for sessions (some controllers may require a login, others may not), how would I go about implementing that?

    Any tips would be appreciated. Thanks

  2. #2
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also which do you guys think is the "better" approach:

    PHPIt.net has a tutorial where the Database, template engine, session classes are passed around inside a registry class.

    The OnLAMP tutorial uses inheritance to make sure the modules have DB/template/ and session access.

    What do you guys think?

  3. #3
    SitePoint Guru
    Join Date
    Nov 2005
    Location
    Midwest
    Posts
    777
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think mixing your layers (database & session) classes is never a good idea. When coding, I always try to separate my areas of concern. For example…

    Presentation Layer - consists of your html, jsp/asp/php and javascript. Code here should only focus on presentation of data. It should not be implementing any logic.

    Event / Control Layer – This layer should address the control of your application. For example, the user clicks the Sign In button. This button should call the SignInEvent which directs all traffic related to processing a users sign in. This layer should also be the only layer that access Session.

    Business Layer – your business layer in the Java world would be a bean. It is where all logic exists to complete the business function. It gets called but your event layer but it could also get called by a web service or a automated testing script (which is not even through a browser which is why session should not be accessed from here).

    Data Access Layer – all logic needed to access your data.

    There a re a variety of reasons why separating your layers is so important. For example, lets say you want to convert from a MySQL database to a MS SQL database. If your code is not layered, your data access code could be located all over your site which requires a great amount of research to find the needed changes, to make the needed changes and then to test the needed changes. Having an interface into your data access layer lets the developer easily determine where the code that needs changing lives while also reducing the amount of testing required.

    Layering your code also reduces the complexity of each section you are designing. It also allows code to be more reusable and readable. Getting into good layering habits is crucial for large sites that require multiple people to make changes to.

    I know this did not directly answer your question… maybe this will help more.

    A login class would look something like…

    Login.htm – present the user with a form to provide username / password.

    LoginEvent.java – checks to make sure the user provided a username / password. If so, it calls the login bean.

    LoginBean.java – it contains all methods required to validate a username / password. For example, it should contain a method like validateLogin.

    validateLogin( String username, String password )
    {
    return isValidUser( username, password )
    }
    Data Access Layer – this contains the SQL to check if the user is valid.

    isValidUser( String username, String password )
    {
    Setup SQL
    Execute SQL
    Check return code, etc
    If valid, return true else return false
    }

    Notice in this section, the isValidUser code is the only code that would change if the database changed. Also, the isValidUser code could be reused in a variety of locations since the code is not all in one event.

    I hope some of this information helped.

  4. #4
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi, thanks for the post!

    So I am debating about how to build this. Currently my two options are:

    1) Use a registry class to hold references to my base classes (template engine, db access, etc).

    or

    2) Use inheritence to build my structure like so:

    Class Module <- Class User Auth <- Class DB

    Where Module extends user auth, user auth extends DB, and so on.

    Thoughts?

  5. #5
    SitePoint Guru
    Join Date
    Nov 2005
    Location
    Midwest
    Posts
    777
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Inheritance is a good practice to get into but I am not sure why you would want Class User Authorization to extend Class DB. Remember, inheritance is about the “is-a” relationship. Do you feel Class User Auth “is a” Class DB?

    Here is an example of inheritance.
    http://java.sun.com/docs/books/tutor...heritance.html

    I would have User Authorization create an instance of class DB.

    For example (this is not perfect code… just trying to show an example)

    Code:
    Public boolean validUser( String username, String password) 
    {
    	boolean status = false;
    
    	//-- Instantiate Data Access Object
    	DataAccess da = new DataAccess();
    
    	//-- Build SQL statement
    	strSQL = “SELECT userID from tblUsers WHERE username = username AND password = password”;
    
    	//-- execute SQL
    	da.connect();
    	ResultSet rs = da.executeQuery( strSQL );
    
    	//-- Record found so the user is valid
    	If( rs.next() )
    	{
    		status = true;
    	}
    
    	return status;
    }
    DataAccess is your instance class DB.

    da.connect would include code necessary to connect to the database such as DB drivers, DB username & password, and then establish the connection.

  6. #6
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Right, my thoughts on the use of inheritance are the same as yours. Authorization "is-a" database is incorrect, but Authorization "has-a" database is right. Thus, I feel the use of aggregation would be more appropriate.

    However, let me know what you think of this article: http://www.onlamp.com/pub/a/php/2005...mvc_intro.html

  7. #7
    SitePoint Guru
    Join Date
    Nov 2005
    Location
    Midwest
    Posts
    777
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I can not disagree that authorization “has a” database so I guess my comment would be style related. When using a Data Access layer, I prefer to create an instance of it. As applications grow, so does the complexity of base classes. I do not want my base classes to know about the Data Access layer (unless they are the ones that are using it). I normally have very generic base classes which almost all of my events can extend. If your Data Access is in your base classes then I see the number of base classes growing since there are many times when you do not need a Data Access layer.

  8. #8
    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)
    If in doubt, aggregation is always the better choice over inheritance. You can achieve the same effect with aggregation, but with a lower degree of coupling between objects. The only real benefit of inheritance, is that it's slightly easier to reuse code.

  9. #9
    SitePoint Guru whisher's Avatar
    Join Date
    May 2006
    Location
    Kakiland
    Posts
    732
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by whydna View Post
    So, I am trying out building a simple MVC framework (just to learn about them and better understand how they work).

    I'm currently following this tutorial right here: http://www.phpit.net/article/simple-mvc-php5/

    So I have a file system that is something like this (modified the tutorial a bit):

    Code:
    public_html [ ]
    
    - classes [ ]
        -  base_controller.class.php
        -  registry.class.php
        -  router.class.php
        -  template_engine.class.php
    
    - controllers [ ] 
        -  index_controller.class.php
            - tpl [ ]
                - index.tpl.php
        -  registration_controller.class.php
            - tpl [ ]
                - registration.tpl.php
        -  user_controller.class.php
            ....
    
    - tpl [ ]
        - global.tpl.php
    
    - index.php
    Now, I am just wondering where to place tihngs. If for example, I want to add a class that contains some supporting functionality for registration (registration_controller.class.php), or login class (user_controller.class.php) where would I place these files?

    Also, currently the framework provides DB and Template engine access to all the controllers. But say I wanted to add some support for sessions (some controllers may require a login, others may not), how would I go about implementing that?

    Any tips would be appreciated. Thanks
    I've peeped into the tutorial and I want to point out to you
    a better registry class (imho ) as teaching example.
    I'm also trying to get a better understanding about MVC
    PHP Code:
    class RegistryException extends Exception{
        public function 
    __construct($message,$code=0){
          
    parent::__construct($message$code);
          }
        public function 
    __toString(){
           return 
    " ".__CLASS__ "<br /> Line : <b>[{$this->line}]</b><br /> Code :<b>[{$this->code}]</b><br /> Msg : {$this->message}<br /> File : <b>{$this->file}</b>\n";
        }
    }
    final class 
    Registry{
           private static 
    $instance null;
         private 
    $cache= array();
        private function 
    __construct(){}
        private static function 
    getInstance(){
            if(
    is_null(self::$instance)){
                
    self::$instance = new Registry();
            }
            return 
    self::$instance;
        }
        public static function 
    has($key){
            
    $registry self::getInstance();
            return isset(
    $registry->cache[$key]);
        }
        public static function 
    get($key){
            
    $registry self::getInstance();
            if(!isset(
    $registry->cache[$key])){
             throw new 
    RegistryException("Key ".$key." is not set in ".__CLASS__);
            } 
              return 
    $registry->cache[$key];
        }
        public static function 
    set($key$value){
            
    $registry self::getInstance();
               
    $registry->cache[$key] = $value;
        }
        public function 
    del($key){
            
    $registry self::getInstance();
            if(!isset(
    $registry->cache[$key])){
                throw new 
    RegistryException("Key ".$key." is not set in ".__CLASS__);
            }
            unset(
    $registry->cache[$key]);
        }
    }
    class 
    A{
        public 
    $testA'Testing registry';
        public function 
    __construct(){
            
    Registry::set('A'$this);
        }
    }
    class 
    B{
        public function 
    __construct(){
            try{
                
    $aRegistry::get('A');
                echo 
    $a->testA;
            }
            catch(
    RegistryException $e){
                
    //$e = cause
                
    throw $e;
            }
        }
    }
    try{
        
    $a= new A();
        
    $b= new B();
    }
    catch(
    RegistryException $e){
        echo 
    $e;

    In this way you can instance A once and you can use it
    in whatever class you need it.

    Bye.

  10. #10
    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 whisher View Post
    a better registry class (imho ) as teaching example.
    I'm also trying to get a better understanding about MVC
    ...
    In this way you can instance A once and you can use it
    in whatever class you need it.
    And what's the practical difference between your example, and this:
    PHP Code:
    class {
      public 
    $testA 'Testing registry';
      public function 
    __construct() {
        
    $GLOBALS['A'] = $this;
      }
    }
    class 
    {
      public function 
    __construct() {
        
    $a $GLOBALS['A'];
        echo 
    $a->testA;
      }


  11. #11
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can anyone tell me what they like/don't like about the onLAMP tutorial?

  12. #12
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, he defines his "Object" class (shown below) as Abstract, yet there are no abstract methods in the class. Is this legal in PHP?

    PHP Code:
    <?php

      
    require_once('Log.php');

      
    /**
      * FR_Object
      *
      * The base object class for most of the classes that we use in our framework.
      * Provides basic logging and set/get functionality.
      *
      * @author Joe Stump <joe@joestump.net>
      * @package Framework
      */
      
    abstract class FR_Object
      
    {
          
    /**
          * $log
          *
          * @var mixed $log Instance of PEAR Log 
          */
          
    protected $log;

          
    /**
          * $me
          *
          * @var mixed $me Instance of ReflectionClass
          */
          
    protected $me;

          
    /**
          * __construct
          * 
          * @author Joe Stump <joe@joestump.net>
          * @access public 
          */
          
    public function __construct()
          {
              
    $this->log Log::factory('file',FR_LOG_FILE);
              
    $this->me = new ReflectionClass($this);
          }

          
    /**
          * setFrom
          *
          * @author Joe Stump <joe@joestump.net>
          * @access public
          * @param mixed $data Array of variables to assign to instance
          * @return void
          */
          
    public function setFrom($data)
          {
              if (
    is_array($data) && count($data)) {
                  
    $valid get_class_vars(get_class($this));
                  foreach (
    $valid as $var => $val) {
                      if (isset(
    $data[$var])) {
                          
    $this->$var $data[$var];
                      }
                  }
              }
          }

          
    /**
          * toArray
          *
          * @author Joe Stump <joe@joestump.net>
          * @access public
          * @return mixed Array of member variables keyed by variable name
          */
          
    public function toArray()
          {
              
    $defaults $this->me->getDefaultProperties();
              
    $return = array();
              foreach (
    $defaults as $var => $val) {
                  if (
    $this->$var instanceof FR_Object) {
                      
    $return[$var] = $this->$var->toArray();
                  } else {
                      
    $return[$var] = $this->$var;
                  }
              }
      
              return 
    $return;
          }

          
    /**
          * __destruct
          *
          * @author Joe Stump <joe@joestump.net>
          * @access public
          * @return void
          */
          
    public function __destruct()
          {
              if (
    $this->log instanceof Log) {
                  
    $this->log->close();
              }
          }
      }

    ?>

  13. #13
    SitePoint Guru whisher's Avatar
    Join Date
    May 2006
    Location
    Kakiland
    Posts
    732
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    And what's the practical difference between your example, and this:
    PHP Code:
    class {
      public 
    $testA 'Testing registry';
      public function 
    __construct() {
        
    $GLOBALS['A'] = $this;
      }
    }
    class 
    {
      public function 
    __construct() {
        
    $a $GLOBALS['A'];
        echo 
    $a->testA;
      }

    You avoid using global vars I think it's best pratice, isn't it ?


    Bye.

  14. #14
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by whisher View Post
    You avoid using global vars I think it's best pratice, isn't it ?


    Bye.
    What kyber wants to point out is that your registry-implementation is actually nothing else than $_GLOBALS, you just hide it behind a class.
    All the problems with $_GLOBALS do also apply on your registry, since your registry is global in scope.

  15. #15
    SitePoint Guru whisher's Avatar
    Join Date
    May 2006
    Location
    Kakiland
    Posts
    732
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by myc View Post
    What kyber wants to point out is that your registry-implementation is actually nothing else than $_GLOBALS, you just hide it behind a class.
    All the problems with $_GLOBALS do also apply on your registry, since your registry is global in scope.
    I agree but it is more OOP and you don't use $GLOBALS.
    Zend Framework Zend/Registry.php has quite the same implementation

    Bye.

  16. #16
    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 whisher View Post
    I agree but it is more OOP and you don't use $GLOBALS.
    I wouldn't call it object oriented. There are no objects in that implementation -- Only classes.

    Quote Originally Posted by whisher View Post
    Zend Framework Zend/Registry.php has quite the same implementation
    I fail to see their point either. If anything, I find it a bit depressing, that Zend are teaching bad practises like this, when the propose to do the opposite.

  17. #17
    SitePoint Guru
    Join Date
    Nov 2003
    Location
    Huntsville AL
    Posts
    706
    Mentioned
    4 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    I wouldn't call it object oriented. There are no objects in that implementation -- Only classes.


    I fail to see their point either. If anything, I find it a bit depressing, that Zend are teaching bad practises like this, when the propose to do the opposite.
    The static oriented Zend registry is a hold over from their early design. Initially, Zend was on this static craze and tried to avoid objects in an effort to be different.

    The delivered Registry (while still containing the original static functions) can be instantiated and passed around.

  18. #18
    SitePoint Member
    Join Date
    Sep 2007
    Location
    Germany
    Posts
    11
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So a registry implementing the singleton pattern would be the better solution?

    (First post and sorry for my bad english... I'm from germany and did not pay much attention in my english classes )

  19. #19
    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 mAu888 View Post
    So a registry implementing the singleton pattern would be the better solution?
    No, avoiding global symbols altogether, would be the better solution. That means passing an instance of the registry around or better yet, pass actual dependencies.

  20. #20
    SitePoint Member
    Join Date
    Sep 2007
    Location
    Germany
    Posts
    11
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, for example, this would be "good"?
    Code PHP:
    <?php
    class Registry
    {
    	// functions ...
    }
     
    class Foo
    {
    	protected $_registry;
     
    	public function __construct(Registry $registry)
    	{
    		$this->_registry = $registry;
    	}
    }
     
    class Bar
    {
    	protected $_registry;
     
    	public function __construct(Registry $registry)
    	{
    		$this->_registry = $registry;
    	}
    }
     
    /**
     * controller.php
     */ 
    $registry = new Registry();
    // do something with the registry, e.g. assign some values etc.
     
    $foo = new Foo($registry);
    $bar = new Bar($registry);
    ?>

  21. #21
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes thats better

    You can even go one step further, and make the dependencies more obvious, for example

    PHP Code:
    class WhatSoEver
    {
      protected 
    $db;
      protected 
    $request;

      public function 
    __construct($registry)
      {
         
    $this->db $registry->get("db");
         
    $this->request $registry->get("request);
      }

    That way the dependencies are not hidden inside your code, because you determine them clearly in your constructor

  22. #22
    SitePoint Guru whisher's Avatar
    Join Date
    May 2006
    Location
    Kakiland
    Posts
    732
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'd like to see the light so I've tried this:

    PHP Code:
    class RegistryException extends Exception
        public function 
    __construct($message,$code=0){ 
          
    parent::__construct($message$code); 
          } 
        public function 
    __toString(){ 
           return 
    " ".__CLASS__ "<br /> Line : <b>[{$this->line}]</b><br /> Code :<b>[{$this->code}]</b><br /> Msg : {$this->message}<br /> File : <b>{$this->file}</b>\n"
        } 

    final class 
    Registry
        private static 
    $instance null
        private 
    $cache= array(); 
        private function 
    __construct(){} 
        public static function 
    getInstance(){ 
            if(
    is_null(self::$instance)){ 
                
    self::$instance = new Registry(); 
            } 
            return 
    self::$instance
        } 
        public function 
    has($key){ 
            return isset(
    $this->cache[$key]); 
        } 
        public function 
    get($key){ 
            if(!isset(
    $this->cache[$key])){ 
             throw new 
    RegistryException("Key ".$key." is not set in ".__CLASS__); 
            } 
              return 
    $this->cache[$key]; 
        } 
        public function 
    set($key$value){ 
               
    $this->cache[$key] = $value
        } 
        public function 
    del($key){ 
           if(!isset(
    $this->cache[$key])){ 
                throw new 
    RegistryException("Key ".$key." is not set in ".__CLASS__); 
            } 
            unset(
    $this->cache[$key]); 
        } 

    class 
    A
        public 
    $testA'Testing registry'
        public function 
    __construct(){ 
            
    $registryRegistry::getInstance();
            
    $registry->set('A'$this); 
        } 

    class 
    B
        public function 
    __construct(){ 
            try{ 
                
    $registryRegistry::getInstance();
                
    $a$registry->get('A'); 
                echo 
    $a->testA
            } 
            catch(
    RegistryException $e){ 
                
    //$e = cause 
                
    throw $e
            } 
        } 

    class 
    C
        public function 
    __construct(){ 
            try{ 
                
    $registryRegistry::getInstance();
                
    $a$registry->get('A'); 
                echo 
    $a->testA
            } 
            catch(
    RegistryException $e){ 
                
    //$e = cause 
                
    throw $e
            } 
        } 

    try{ 
        
    $a= new A(); 
        
    $b= new B(); 
        
    $c= new C();

    catch(
    RegistryException $e){ 
        echo 
    $e



    I saw the post before mine so
    Is it better aggregation or singleton ?

    Bye.
    Bye.

  23. #23
    SitePoint Addict whydna's Avatar
    Join Date
    Jun 2006
    Posts
    258
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The onLAMP example does not use a registry whatsoever. So no global variables, or even variables that need to be passed.

    The use inheritance so that the modules inherit all these properties. Which is the better method?

  24. #24
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Posts
    27
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @wisher

    I dont like singletons at all, you need them very very seldom but they are really convenient, thus people like to (ab)use them.
    The problem with singletons is that they define dependencies at compile-time, so you cant change dependencies at runtime (for example passing a mock object in testing). This is a result of one of the main problems with static methods, they are always connected with a specific class (thus dependent on them) not with an instance.

    @whydna

    Personally I think they highly abuse inheritance in this example, since inheritance should be always a "is-a" relationship, but they use it for a "has-a" or "needs-a" relationship .. It may seem more convenient in the beginning, but you get a very strong coupling between the classes and flexibility is greatly limited.

  25. #25
    SitePoint Enthusiast
    Join Date
    Oct 2006
    Posts
    37
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm trying to understand the benefit of using a Registry more. I like the idea, but I'm not happy with the implementation. For example, when you have an object that uses the registry that is contained within another object (that might or might not need that registry) now is required to change its constructor.

    PHP Code:
    class User {
        private 
    $AccessList;

        public function 
    __construct($registry) {
            
    $this->AccessList = new AccessList($registry);
        }

    And if the AccessList is not created right away, I have to first store the registry (which shouldn't be done because it creates a references to something that might change).

    This seems inconvenient, as now everything depends on me passing around a registry even when it is not needed. I'd rather implement the Registry as a singleton with static methods.

    But what am I setting myself up for with this?

    This page seems to be have some useful information. But I'm not sure how correct it is: http://www.patternsforphp.com/wiki/Registry


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
  •