SitePoint Sponsor

User Tag List

Page 4 of 4 FirstFirst 1234
Results 76 to 87 of 87
  1. #76
    SitePoint Zealot Selatos's Avatar
    Join Date
    Aug 2002
    Location
    USA
    Posts
    144
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Widow Maker, I have finished my new template classes in a MVC pattern. I'm sorry to say that after using it, I'm starting to like MVC .
    Here's my code:
    PHP Code:
    controller.class.php:
    class 
    Controller {
    var 
    $template;
    var 
    $fragments;
    function 
    Controller() {
    $this->fragments = array();
    }
    //creates a new template class and saves a pointer to it
    function &createTemplate($style$template) {
    $temp = &new Template($style$template);
    $this->template = &$template;
    return 
    $temp;
    }
    //create a new Fragment and add stuff to it
    function &createFragment($data) {
    $frag = &new Fragment();
    $frag->add($data);
    $this->fragments[count($this->fragments)] = &$frag;
    return 
    $frag;
    }
    }
     
    template.class.php:
    //the template class
    //the final output layer
    //accepts mini-templates(fragments)
    class Template {
    var 
    $template;
    var 
    $fragments;
    //$style is filename of stylesheet
    //$template is html file with <php*> tags
    function Template($style$template) {
    $this->template file_get_contents($template);
    $this->fragments = array();
    $this->set("style"$style);
    }
    //overwrites a fragment with a new one, containing $val
    function &set($key$val, &$control) {
    unset(
    $this->fragments[$key]);
    $this->fragments["php".$key] = &$control->createFragment($val);
    return 
    $this->fragments["php".$key];
    }
    //set a Fragment(note: only one fragment can be in a space...to append more
    //modify the fragment to include more HTML)
    function setFragment($key, &$fragment) {
    $this->fragments["php".$key] = &$fragment;
    }
    //an error has occured
    function panic($message, &$control) {
    $this->set("error"$message, &$control);
    $this->show();
    @die();
    }
    function 
    show() {
    foreach (
    $this->fragments as $key => $val) {
    //get the contents of each fragment and send it to the template
    $this->template eregi_replace("<".$key.">"$val->show(), $this->template);
    }
    echo (
    $this->template);
    }
    }
    //the mini-template class accepted by Template
    class Fragment {
    var 
    $fragments;
    var 
    $page;
    function 
    Fragment() {
    $this->fragments = array();
    }
    //function to add content directly to the page
    function add($content) {
    $this->page .= $content."\n";
    }
    //function to add a fragment
    function addFragment(&$fragment) {
    $this->fragments[count($this->fragments)] = &$fragment;
    }
    //returns the contents of $page
    function show() {
    $temp $this->page;
    foreach (
    $this->fragments as $val) {
    $temp .= $val->show();
    }
    return 
    $temp;
    }
    }
     
    test.php(the code to use everything):
    //set the style and template file
    $style "style.css";
    $template "main.tpl.html";
    //require the class files
    require_once("controller.class.php");
    require_once(
    "template.class.php");
    $control = new Controller();
    //create the template and test set()
    $template = &$control->createTemplate($style$template);
    $fragmentA = &$template->set("title""Test of MVC Template", &$control);
    //create the fragment and test setFragment
    $fragment = &$control->createFragment("Body Content.<br>");
    $fragment->add("More Body Content.");
    $template->setFragment("body", &$fragment);
    //show everything
    $template->show(); 
    For new fragments, perhaps I want one that'll automatically put stuff in <div> tags, i just derive from Fragment and add a function to Controller to create that type of fragment. I'm also using my functions from the Page class that I posted earlier, which everyone said would be a headache to use, etc. for the subclasses of Fragment. Basically, DivFragment will have startDiv() and endDiv() in addition to add(), TableFragment will have all of the table functions, etc.

    Personally, I'm happy with this, but if you see room for further improvement of the classes, tell me and I'll work on yet another revision(that would make four versions ).
    Last edited by Selatos; Jul 26, 2004 at 10:57.

  2. #77
    public static void brain Gybbyl's Avatar
    Join Date
    Jun 2002
    Location
    Montana, USA
    Posts
    647
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    class Overload
    {
        public function 
    __construct()
        {
            
    $argv func_get_args();
            switch( 
    func_num_args() )
            {
                default:
                case 
    0:
                    
    $this->__construct0();
                    break;
                case 
    1:
                     if( 
    $argv[0] instanceof Object )
                     {
                         
    $this->__construct1$argv[0] );
                         break;
                     }
                     
    $this->__construct2$argv[0] );
            }
        }

        abstract public function 
    __construct0();
        abstract public function 
    __construct1Object $obj );
        abstract public function 
    __construct2$obj );

    Viola. Overloaded constructors.

    I don't see how this is "hacky"...
    That's how overloaded methods work: In strongly typed languages it just happens behind the scenes.

    I'm sure you could make it a little more pretty, but it's not like it's hard to follow the logic or anything.

    If nothing else, at least this "overloading" is FAST.

    instanceof is far faster than is_a(), which was the only class-checking operation in php 4. Having the unified constructor makes it easy to overload the constructor, as well, which saves development and maintenance time.

    That's how I usually do it, though I'm working on implementing a pattern that will make the operation more abstract and take less space.

    *edit*
    Ryan

  3. #78
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's how overloaded methods work: they choose which method to run AT run-time. In strongly typed languages it just happens behind the scenes.
    Just want to point out that in strongly-typed (compiled) languages it happens at compile-time

  4. #79
    public static void brain Gybbyl's Avatar
    Join Date
    Jun 2002
    Location
    Montana, USA
    Posts
    647
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Remember that PHP is loosely typed, and the type names that you associated with the parameters to methods and functions are just *hints*. According to the Zend Engine 2 changes, all that happens is that ze runs a " $blah instanceof YourType " as they are being passed in. There simply is no compile time check... correct me if I'm wrong (wait, I know you will ), but isn't syntax the only thing that PHP checks at "compile" time?

    This is what makes it improbable for a loose language like PHP to support true overloading... Not to mention that there is essentially only one primitive type, and in order to distinguish between this type, a check must be run inside of the method. PHP really doesn't care what kind of variable it is passing to your method.

    Again, correct me if I'm wrong.
    Ryan

  5. #80
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gybbyl
    That's how I usually do it, though I'm working on implementing a pattern that will make the operation more abstract and take less space.
    How about:

    PHP Code:

        
    public function __construct()
        {
            
    $method '__construct' func_num_args();
            
    $this->$method(func_get_args());
        } 

  6. #81
    SitePoint Addict
    Join Date
    May 2003
    Location
    Calgary, Alberta, Canada
    Posts
    275
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just wanted to note that method overriding works similar to this (Not applicable for constructors though):
    PHP Code:
    class String {
        public function 
    toString0() {
            echo 
    'this is String::toString0';
        } 
        public function 
    toString1($arg) {
            echo 
    'this is String::toString1(' $arg ')';
        } 
        public function 
    __call($method$args) {
            return 
    call_user_func_array(array(&$this$method count($args)), $args);
        } 


    $str = new String();
    $str->toString();
    $str->toString('asdasd'); 

  7. #82
    public static void brain Gybbyl's Avatar
    Join Date
    Jun 2002
    Location
    Montana, USA
    Posts
    647
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    Quote Originally Posted by Gybbyl
    That's how I usually do it, though I'm working on implementing a pattern that will make the operation more abstract and take less space.

    How about_:
    PHP Code:
    public function __construct()
    {
        
    $method '__construct' func_num_args();
        
    $this->$method(func_get_args());

    That works, but there are a few things wrong:

    1) It passes the parameters as an array, which could arguably make it more confusing (unless properly documented, but this is the real world, and not enough people do that).

    2) It assumes that there is only one method that accepts that number of arguments. This wouldn't work:

    PHP Code:
    public function myMethod0Vector $v$str );
    public function 
    myMethod1Object $v$str ); 
    It would try to call "myMethod2", so you would either have to have two levels of overloading (one for the main method that is overloaded, and then one for each method that has the same number of arguments as another method).

    It would work if you are very very careful about what you pass to your methods.
    Ryan

  8. #83
    public static void brain Gybbyl's Avatar
    Join Date
    Jun 2002
    Location
    Montana, USA
    Posts
    647
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Brendan Vickery
    Just wanted to note that method overriding works similar to this (Not applicable for constructors though):

    PHP Code:
    class String {
        public function 
    toString0() {
            echo 
    'this is String::toString0';
        }
        public function 
    toString1($arg) {
            echo 
    'this is String::toString1(' $arg ')';
        }
        public function 
    __call($method$args) {
            return 
    call_user_func_array(array(&$this$method count($args)), $args);
        }
    }

    $str = new String();
    $str->toString();
    $str->toString('asdasd'); 
    That is almost identical to McGruff's method, which, while more compact, doesn't work for classes where more than one method with the same name accepts the same number of arguments with different types.
    Ryan

  9. #84
    SitePoint Addict
    Join Date
    May 2003
    Location
    Calgary, Alberta, Canada
    Posts
    275
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gybbyl
    That is almost identical to McGruff's method, which, while more compact, doesn't work for classes where more than one method with the same name accepts the same number of arguments with different types.
    True. I was more trying to point out the use of __call() than what was inside.

  10. #85
    public static void brain Gybbyl's Avatar
    Join Date
    Jun 2002
    Location
    Montana, USA
    Posts
    647
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh, gotcha.

    I guess __call() may be a good alternative to what we are doing, if it were implemented correctly. Say, if the superclass of your hierarchy were to define a robust implementation of __call and then be able to serve up all of the overloaded methods on demand. That would be uber.

    I generally use __call() for beating PHP to the "error" punch. It's nice to be able to control where access errors are thrown.
    Ryan

  11. #86
    SitePoint Addict
    Join Date
    May 2003
    Location
    Calgary, Alberta, Canada
    Posts
    275
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just for fun how about this:
    PHP Code:
    class String {
        function 
    toString0() {
            echo 
    'this is String::toString0<br>';
        } 
        function 
    toString1User(User $user) {
            
    $user->toString();
        } 
        function 
    toString3UserThingstring(User $userThing $thing$arg3) {
            
    $user->toString();
            
    $thing->toString();
            echo 
    $arg3 '<br />';
        } 
        function 
    __call($method$args) {
            
    $method .= count($args);
            foreach(
    $args as $arg) {
                
    $type gettype($arg);
                if (
    $type == 'object') {
                    
    $method .= get_class($arg);
                } else {
                    
    $method .= $type;
                } 
            } 
            return 
    call_user_func_array(array($this$method), $args);
        } 

    class 
    User {
        function 
    toString() {
            echo 
    'User<br />';
        } 

    class 
    Thing {
        function 
    toString() {
            echo 
    'Thing<br />';
        } 

    $user = new User;
    $thing = new Thing;
    $str = new String();
    $str->toString();
    $str->toString($user);
    $str->toString($user$thing'123'); 
    Bit of a pain but it works.

  12. #87
    SitePoint Zealot Selatos's Avatar
    Join Date
    Aug 2002
    Location
    USA
    Posts
    144
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah that works...but it still doesn't feel right. I'm sure it might be just that I am used to that happening behind the scenes, but I still don't consider that overloading

    If I need any sort of "overloading" I'll use if/else or switch. IMO this looks nicer to read over. Ex.
    PHP Code:
    class User {
    function 
    User($name$pass$version 0) {
    switch (
    $version) {
    case 
    0$this->authorize(); break;
    case 
    1$this->copy($name$pass); break;
    }
    }

    Or something to that effect. Don't ask about what I named the functions because I don't really know.


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
  •