SitePoint Sponsor

User Tag List

Page 1 of 4 1234 LastLast
Results 1 to 25 of 84
  1. #1
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    How to design an HTML Form class

    I'm trying to design an HTML Form class and I need some help with some concepts.

    Buttons, for example, are easy to visualize as "objects" but when I create an HTML form, all I really need is for the code (class, function, method, or whatever I wind up using) to write a bunch of HTML. The button has no properties and the only method is writing itself as HTML code.

    Does this mean that it makes more sense to write the button code as a function as opposed to a class? Or should the button instead of being an object be a method of the Form class? The same applies to all the other form objects such as select, radio buttons and check boxes.

    BTW, I'm saving the state of radio buttons and other elements in a different object such as a shopping cart.

    Thanks for your help!
    Denny Schlesinger
    web services

  2. #2
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    I would call a button a form element, much like input, label etc...

    As such, I would have a Form object which accepted Form_Element objects to compose the form.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  3. #3
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    I would call a button a form element, much like input, label etc...

    As such, I would have a Form object which accepted Form_Element objects to compose the form.
    Which makes a button an object which is where I started but then I noticed that this "object" would only have one method and no properties which is what led me to ask the question if it was worth creating a Button class, a Select class, etc.

    SilverBullet, your answer is yes, go for it! Right?
    Denny Schlesinger
    web services

  4. #4
    SitePoint Guru
    Join Date
    Jan 2005
    Location
    heaven
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by captainccs View Post
    Which makes a button an object which is where I started but then I noticed that this "object" would only have one method and no properties which is what led me to ask the question if it was worth creating a Button class, a Select class, etc.

    SilverBullet, your answer is yes, go for it! Right?
    A button has plenty of attributes -- I'm assuming these are your properties? ID, name and class for starters. I'm not sure how you've structured your classes but here's what I would do.

    PHP Code:
    class Form_Element_Abstract
    {
        protected 
    $_attributes;
        public function 
    addAttribute($name$value){}
        public function 
    setAttribute($name$value){}
        public function 
    getAttribute($name){}
        public function 
    isAttribute($name){}
        protected function 
    _buildAttributes(){}
        abstract public function 
    render();
    }

    class 
    Form_Element_Button extends Form_Element_Abstract
    {
        public function 
    render()
        {
            
    $openTag '<button';
            
    $closeTag '</button>';
            
    $xhtml $openTag
                   
    $this->_buildAttributres()
                   . 
    '/>'
                   
    $closeTag;

            return 
    $xhtml;
        }

    If it's needed you can add wrapper functions around setAttribute to create a function to set ID and name, but it's extensible so can set any attribute that a button has.
    Creativity knows no other restraint than the
    confines of a small mind.
    - Me
    Geekly Humor
    Oh baby! Check out the design patterns on that framework!

  5. #5
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the code sample. I've not structured anything yet, I write mostly procedures and I'm still trying to get my head around OOP.

    Looking at your code I think that the issue to solve is nesting a group of tags inside other tags (radio buttons inside a field set, options inside a select), and all these tags inside the form tag in addition to populating the tags with name=value pairs (attributes). The class could be a lot more general than just a form builder.

    An article I read recently suggested that the most efficient way to pass parameters to an object is to pass a single associative array and that already has the name=value pairs.

    Just thinking out loud.
    Denny Schlesinger
    web services

  6. #6
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Most of the answers you'll get in the Application Design forum will be OOP-based because that's what Application Design is about.

    Quote Originally Posted by captainccs View Post
    An article I read recently suggested that the most efficient way to pass parameters to an object is to pass a single associative array and that already has the name=value pairs.
    Not really efficient in terms of the program - Efficient for the programmer, maybe - but not by much.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  7. #7
    SitePoint Guru
    Join Date
    Jan 2005
    Location
    heaven
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    Most of the answers you'll get in the Application Design forum will be OOP-based because that's what Application Design is about.
    I'd be careful with such a broad statement.

    Quote Originally Posted by captainccs;
    An article I read recently suggested that the most efficient way to pass parameters to an object is to pass a single associative array and that already has the name=value pairs.
    That's not always true.
    Creativity knows no other restraint than the
    confines of a small mind.
    - Me
    Geekly Humor
    Oh baby! Check out the design patterns on that framework!

  8. #8
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    Most of the answers you'll get in the Application Design forum will be OOP-based ....
    That's good because I was looking for a place to discuss OOP. I recently upgraded myself to php 5 and I'm anxious to leant to use the object model. I've been playing around with OOP for a long time but I never used it for serious work until recently because I have a hard time conceptualizing programming objects as you can see from my trashing around with this form thing.

    The only production object code I have written is a File class that manages various types of files: mail attachments, uploads, downloads, file storage in MySQL.


    ...because that's what Application Design is about.
    For me, Application Design is 40% user interface, 40% data structure. You can use a multitude of tools to get there.
    Denny Schlesinger
    web services

  9. #9
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    I was thinking something more along these lines...

    PHP Code:
    <?php
    class Form
    {
        protected 
    $sAction;
        
        protected 
    $sMethod;
        
        protected 
    $aElements = array();
        
        public function 
    __construct($sAction$sMethod 'post')
        {
            
    $this->sAction $sAction;
            
    $this->sMethod $sMethod;
        }
        
        public function 
    addElement(FormElement $oElement)
        {
            
    $this->aElements[] = $oElement;
        }
        
        public function 
    render()
        {
            foreach (
    $this->aElements as $oElement)
            {
                
    $sElements .= $oElement->render() . "\r\n";
            }
            return 
    sprintf(
                
    '<form action="%s" method="%s">
                    %s
                </form>'
    ,
                
    $this->sAction,
                
    $this->sMethod,
                
    $sElements
            
    );
        }
    }

    abstract class 
    FormElement
    {
        protected 
    $aAttributes;
        
        public function 
    addAttribute($sName$mValue)
        {
            
    $this->aAttributes[$sName] = $mValue;
        }
        
        abstract public function 
    render();
    }

    class 
    TextFormElement extends FormElement
    {
        public function 
    render()
        {
            foreach (
    $this->aAttributes as $sName => $mValue)
            {
                
    $sAttributes .= sprintf('%s="%s" '$sName$mValue);
            }
            return 
    sprintf(
                
    '<input type="text" %s/>',
                
    $sAttributes
            
    );
        }
    }

    class 
    PasswordFormElement extends FormElement
    {
        public function 
    render()
        {
            foreach (
    $this->aAttributes as $sName => $mValue)
            {
                
    $sAttributes .= sprintf('%s="%s" '$sName$mValue);
            }
            return 
    sprintf(
                
    '<input type="password" %s/>',
                
    $sAttributes
            
    );
        }
    }

    class 
    SubmitFormElement extends FormElement
    {
        public function 
    render()
        {
            foreach (
    $this->aAttributes as $sName => $mValue)
            {
                
    $sAttributes .= sprintf('%s="%s" '$sName$mValue);
            }
            return 
    sprintf(
                
    '<input type="submit" %s/>',
                
    $sAttributes
            
    );
        }
    }

    $oForm = new Form('/users/login/');

    $oUsernameField = new TextFormElement();
    $oUsernameField->addAttribute('name''username');

    $oPasswordField = new PasswordFormElement();
    $oPasswordField->addAttribute('name''password');

    $oSubmitButton = new SubmitFormElement();
    $oSubmitButton->addAttribute('name''submit');
    $oSubmitButton->addAttribute('value''login');

    $oForm->addElement($oUsernameField);
    $oForm->addElement($oPasswordField);
    $oForm->addElement($oSubmitButton);
    echo 
    $oForm->render();
    /*
    <form action="/users/login/" method="post">
        <input type="text" name="username" />
        <input type="password" name="password" />
        <input type="submit" name="submit" value="login" />
    </form>
    */
    ?>
    Of course there are lots of ways this can be improved, but it should give you a rough idea.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  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 captainccs View Post
    Does this mean that it makes more sense to write the button code as a function as opposed to a class? Or should the button instead of being an object be a method of the Form class?
    It depends. Making the form element an object, rather than a method, you gain the advantage of polymorphism - Which is really just a type of decoupling. Decouplings are good if they are used in the proper places, but they add unnecessary complexity, if they are placed in the wrong places. In this case, it's pretty common to make the form elements objects, but you might want to start out with a less flexible - simpler - design, and change it when you see the need.

  11. #11
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    I was thinking something more along these lines...

    Of course there are lots of ways this can be improved, but it should give you a rough idea.
    Thank you so much for that code, it sure helps!

    I don't see the need to have a class for each form element so I simplified your code a bit. My version has a single Tag class and the constructor is passed the actual tag (input, button, etc.):

    PHP Code:
    <?php
    class Form
    {
        protected 
    $sAction;
        
        protected 
    $sMethod;
        
        protected 
    $aTags = array();
        
        public function 
    __construct($sAction$sMethod 'post')
        {
            
    $this->sAction $sAction;
            
    $this->sMethod $sMethod;
        }
        
        public function 
    addTag(Tag $oTag)
        {
            
    $this->aTags[] = $oTag;
        }
        
        public function 
    render()
        {
            foreach (
    $this->aTags as $oTag)
            {
                
    $sTags .= $oTag->render() . "\r\n";
            }
            return 
    sprintf(
                
    '<form action="%s" method="%s">
                    %s
                </form>'
    ,
                
    $this->sAction,
                
    $this->sMethod,
                
    $sTags
            
    );
        }
    }

    class 
    Tag
    {
        protected 
    $sTag;

        protected 
    $sDisplayText;

        protected 
    $aAttributes;
        
        public function 
    __construct($sTag$sDisplayText '')
        {
            
    $this->sTag $sTag;    
            
    $this->sDisplayText $sDisplayText
        }

        public function 
    addAttribute($sName$mValue)
        {
            
    $this->aAttributes[$sName] = $mValue;
        }
        
        public function 
    render()
        {
            if (
    is_array($this->aAttributes))
            {
                foreach (
    $this->aAttributes as $sName => $mValue)
                {
                    
    $sAttributes .= sprintf('%s="%s" '$sName$mValue);
                }
            }
            if (
    $this->sDisplayText == '')
            {
                return 
    sprintf(
                    
    '<%s %s/>',
                    
    $this->sTag,
                    
    $sAttributes
                
    );
            } else {
                return 
    sprintf(
                    
    '<%s %s>%s</%s>',
                    
    $this->sTag,
                    
    $sAttributes,
                    
    $this->sDisplayText,
                    
    $this->sTag
                
    );
            }
        }
    }


    $oForm = new Form('/users/login/');

    $oUsernameField = new Tag('input');
    $oUsernameField->addAttribute('type''text');
    $oUsernameField->addAttribute('name''username');

    $oBr = new Tag('br');

    $oPasswordField = new Tag('input');
    $oPasswordField->addAttribute('type''password');
    $oPasswordField->addAttribute('name''password');

    $oSubmitButton = new Tag('button''Click Me!');
    $oSubmitButton->addAttribute('type''submit');
    $oSubmitButton->addAttribute('name''submit');
    $oSubmitButton->addAttribute('value''login');

    $oForm->addTag($oUsernameField);
    $oForm->addTag($oBr);
    $oForm->addTag($oPasswordField);
    $oForm->addTag($oBr);
    $oForm->addTag($oSubmitButton);

    echo 
    $oForm->render();
    /*
    <form action="/users/login/" method="post">
        <input type="text" name="username" />
        <input type="password" name="password" />
        <button type="submit" name="submit" value="login" >Click Me!</button>
    </form>
    */
    ?>

    Would you be kind enough to explain this line of code

    PHP Code:
    public function addTag(Tag $oTag
    I don't understand the function of the class name parameter it takes.
    Denny Schlesinger
    web services

  12. #12
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  13. #13
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Mastodont View Post

    Thanks!
    Denny Schlesinger
    web services

  14. #14
    SitePoint Guru
    Join Date
    Jan 2005
    Location
    heaven
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by captainccs View Post
    I don't see the need to have a class for each form element so I simplified your code a bit.
    A class for each element because each element separate object. You don't want to over simplify the relation between objects. It will come back to bite you eventually.
    Creativity knows no other restraint than the
    confines of a small mind.
    - Me
    Geekly Humor
    Oh baby! Check out the design patterns on that framework!

  15. #15
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    With your help I've built a Tag class that can write a whole HTML page.

    PHP Code:
    <?php

    class Tag
    {
        protected 
    $sTag;
        protected 
    $sAttributes;
        protected 
    $sContent;
        
        public function 
    __construct($sTag$sContent '')
        {
            
    $this->sTag $sTag;    
            
    $this->sContent $sContent
        }

        public function 
    addAttribute($sName$mValue)
        {
            
    $this->sAttributes .= "{$sName}='{$mValue}' ";
        }
        
        public function 
    addTag(Tag $oTag)
        {
            if (
    $this->sContent == '')
            {
                
    $this->sContent "\n";
            }
            
    $this->sContent .= $oTag->render() . "\n";
        }
        
        public function 
    render()
        {
            
    $temp trim("{$this->sTag} {$this->sAttributes}");
            if (
    $this->sContent == '')
            {
                return 
    "<{$temp} />";
            }
            return 
    "<{$temp}>{$this->sContent}</{$this->sTag}>";
        }
    }

    /************* test *************/

    $oTitle = new Tag('title''Denny\'s Object Stuff');

    $oKeywords = new Tag('meta');
    $oKeywords->addAttribute('name''keywords');
    $oKeywords->addAttribute('content''OOP, PHP5');

    $oHead = new Tag('head');
    $oHead->addTag($oTitle);
    $oHead->addTag($oKeywords);

    $oBr = new Tag('br');

    $oUsernameField = new Tag('input');
    $oUsernameField->addAttribute('type''text');
    $oUsernameField->addAttribute('name''username');

    $oPasswordField = new Tag('input');
    $oPasswordField->addAttribute('type''password');
    $oPasswordField->addAttribute('name''password');

    $oSubmitButton = new Tag('button''Click Me!');
    $oSubmitButton->addAttribute('type''submit');
    $oSubmitButton->addAttribute('name''submit');
    $oSubmitButton->addAttribute('value''login');

    $oFieldset = new Tag('fieldset');
    $oFieldset->addAttribute('style''width:200px;');
    $oLegend = new Tag('legend''Log in please');
    $oFieldset->addTag($oLegend);
    $oFieldset->addTag($oUsernameField);
    $oFieldset->addTag($oBr);
    $oFieldset->addTag($oPasswordField);
    $oFieldset->addTag($oBr);
    $oFieldset->addTag($oSubmitButton);

    $oForm = new Tag('form');
    $oForm->addAttribute('action'$_SERVER['PHP_SELF']);
    $oForm->addAttribute('method''post');
    $oForm->addTag($oFieldset);

    $oBody = new Tag('body');
    $oBody->addTag($oForm);

    $oHtml = new Tag('html');
    $oHtml->addAttribute('xmlns''http://www.w3.org/1999/xhtml');
    $oHtml->addAttribute('xml:lang''en');
    $oHtml->addAttribute('lang''en');
    $oHtml->addTag($oHead);
    $oHtml->addTag($oBody);

    echo 
    $oHtml->render();

    /*
    <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
    <head>
    <title>Denny's Object Stuff</title>
    <meta name='keywords' content='OOP, PHP5' />
    </head>
    <body>
    <form action='/~denny/php_manual/xhtml.php' method='post'>
    <fieldset style='width:200px;'>
    <legend>Log in please</legend>
    <input type='text' name='username' />
    <br />
    <input type='password' name='password' />
    <br />
    <button type='submit' name='submit' value='login'>Click Me!</button>
    </fieldset>
    </form>
    </body>
    </html>
    */
    ?>
    Now I need to create new classes to build selectors and sets of radio buttons and checkboxes.

    Thanks guys!
    Denny Schlesinger
    web services

  16. #16
    SitePoint Guru
    Join Date
    Jan 2005
    Location
    heaven
    Posts
    953
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by captainccs View Post
    With your help I've built a Tag class that can write a whole HTML page.

    PHP Code:
    <?php

    class Tag
    {
        protected 
    $sTag;
        protected 
    $sAttributes;
        protected 
    $sContent;
        
        public function 
    __construct($sTag$sContent '')
        {
            
    $this->sTag $sTag;    
            
    $this->sContent $sContent
        }

        public function 
    addAttribute($sName$mValue)
        {
            
    $this->sAttributes .= "{$sName}='{$mValue}' ";
        }
        
        public function 
    addTag(Tag $oTag)
        {
            if (
    $this->sContent == '')
            {
                
    $this->sContent "\n";
            }
            
    $this->sContent .= $oTag->render() . "\n";
        }
        
        public function 
    render()
        {
            
    $temp trim("{$this->sTag} {$this->sAttributes}");
            if (
    $this->sContent == '')
            {
                return 
    "<{$temp} />";
            }
            return 
    "<{$temp}>{$this->sContent}</{$this->sTag}>";
        }
    }

    /************* test *************/

    $oTitle = new Tag('title''Denny\'s Object Stuff');

    $oKeywords = new Tag('meta');
    $oKeywords->addAttribute('name''keywords');
    $oKeywords->addAttribute('content''OOP, PHP5');

    $oHead = new Tag('head');
    $oHead->addTag($oTitle);
    $oHead->addTag($oKeywords);

    $oBr = new Tag('br');

    $oUsernameField = new Tag('input');
    $oUsernameField->addAttribute('type''text');
    $oUsernameField->addAttribute('name''username');

    $oPasswordField = new Tag('input');
    $oPasswordField->addAttribute('type''password');
    $oPasswordField->addAttribute('name''password');

    $oSubmitButton = new Tag('button''Click Me!');
    $oSubmitButton->addAttribute('type''submit');
    $oSubmitButton->addAttribute('name''submit');
    $oSubmitButton->addAttribute('value''login');

    $oFieldset = new Tag('fieldset');
    $oFieldset->addAttribute('style''width:200px;');
    $oLegend = new Tag('legend''Log in please');
    $oFieldset->addTag($oLegend);
    $oFieldset->addTag($oUsernameField);
    $oFieldset->addTag($oBr);
    $oFieldset->addTag($oPasswordField);
    $oFieldset->addTag($oBr);
    $oFieldset->addTag($oSubmitButton);

    $oForm = new Tag('form');
    $oForm->addAttribute('action'$_SERVER['PHP_SELF']);
    $oForm->addAttribute('method''post');
    $oForm->addTag($oFieldset);

    $oBody = new Tag('body');
    $oBody->addTag($oForm);

    $oHtml = new Tag('html');
    $oHtml->addAttribute('xmlns''http://www.w3.org/1999/xhtml');
    $oHtml->addAttribute('xml:lang''en');
    $oHtml->addAttribute('lang''en');
    $oHtml->addTag($oHead);
    $oHtml->addTag($oBody);

    echo 
    $oHtml->render();

    /*
    <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
    <head>
    <title>Denny's Object Stuff</title>
    <meta name='keywords' content='OOP, PHP5' />
    </head>
    <body>
    <form action='/~denny/php_manual/xhtml.php' method='post'>
    <fieldset style='width:200px;'>
    <legend>Log in please</legend>
    <input type='text' name='username' />
    <br />
    <input type='password' name='password' />
    <br />
    <button type='submit' name='submit' value='login'>Click Me!</button>
    </fieldset>
    </form>
    </body>
    </html>
    */
    ?>
    Now I need to create new classes to build selectors and sets of radio buttons and checkboxes.

    Thanks guys!
    I would apply a factory pattern and daisy chain.

    PHP Code:
    // THis
    $oUsernameField = new Tag('input');
    $oUsernameField->addAttribute('type''text');
    $oUsernameField->addAttribute('name''username');

    // Become this
    Tag::get('input')->addAttribute('type''text')->addAttribute('name''username'); 
    PHP Code:
    // add $attribs so you can add your attributes from your constructor
    public function __constructor($sTag, array $attribs null)
    {}

    // Factory pattern.
    public function get($sTag, array $attribs null)
    {
        return new 
    Tag($sTag$attribs);
    }

    public function 
    addAttribute($name$value)
    {
      
    // Keep the attributes as an array until you need it rendered
      
    $this->_attribs[$name] = $value;
      
    returh $this// daisy chained

    One more thing. Your tag class shouldn't be concerned with the over content. It's purpose is basically to handle tags, i.e. to alter and render a tag with it's attributes. If you want to render an entire set of tags then that's a different class all together. In any case I thought this was about forms? O.o
    Creativity knows no other restraint than the
    confines of a small mind.
    - Me
    Geekly Humor
    Oh baby! Check out the design patterns on that framework!

  17. #17
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by imaginethis View Post
    A class for each element because each element separate object. You don't want to over simplify the relation between objects. It will come back to bite you eventually.
    Most tags have the same structure, a tag name, zero or more attributes and optional content. I don't see why these would need separate objects. But there are specialized tags, I can think of three: select, radio, and checkbox, that do need their own classes which I plan on building.
    Denny Schlesinger
    web services

  18. #18
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    I don't see the need to have a class for each form element
    If you wanted to target a specific element as you add it to the form, a decorator say, you would not be able to do this with your proposed solution.

    Without rendering the tag, there is no way to determine which form element it represents.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  19. #19
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    If you wanted to target a specific element as you add it to the form, a decorator say, you would not be able to do this with your proposed solution.
    Anthony, sorry, but I don't understand what you are saying. Each element or tag has its name and until I render it, I can add stuff to it.

    But it does make sense to have a class that assembles the tags to build the page (or the form)

    Without rendering the tag, there is no way to determine which form element it represents.
    Again, I don't understand.
    Denny Schlesinger
    web services

  20. #20
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Maybe this clears it up a little.

    PHP Code:
    class LimitedTextFieldsForm extends Form
    {
        public function 
    addElement(FormElement $oElement)
        {
            if(
    $oElement instanceof TextFormElement)
            {
                
    $oElement->addAttribute('max-length'5);
            }
            
    $this->aElements[] = $oElement;
        }

    Or more likely

    PHP Code:
    class DisabledSubmitFieldForm extends Form
    {
        public function 
    addElement(FormElement $oElement)
        {
            if(
    $oElement instanceof SubmitFormElement)
            {
                
    $oElement->addAttribute('disabled''disabled');
            }
            
    $this->aElements[] = $oElement;
        }

    How would you do this given your solution?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  21. #21
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by imaginethis View Post
    I would apply a factory pattern and daisy chain.

    PHP Code:
    // THis
    $oUsernameField = new Tag('input');
    $oUsernameField->addAttribute('type''text');
    $oUsernameField->addAttribute('name''username');

    // Become this
    Tag::get('input')->addAttribute('type''text')->addAttribute('name''username'); 
    PHP Code:
    // add $attribs so you can add your attributes from your constructor
    public function __constructor($sTag, array $attribs null)
    {}

    // Factory pattern.
    public function get($sTag, array $attribs null)
    {
        return new 
    Tag($sTag$attribs);
    }

    public function 
    addAttribute($name$value)
    {
      
    // Keep the attributes as an array until you need it rendered
      
    $this->_attribs[$name] = $value;
      
    returh $this// daisy chained

    That sounds like a great idea!


    One more thing. Your tag class shouldn't be concerned with the over content. It's purpose is basically to handle tags, i.e. to alter and render a tag with it's attributes. If you want to render an entire set of tags then that's a different class all together.
    I see what you mean. I'll have to think about this.


    In any case I thought this was about forms? O.o
    Well, that's where I started. What do they call it? Drift?
    Denny Schlesinger
    web services

  22. #22
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    Maybe this clears it up a little.

    PHP Code:
    class LimitedTextFieldsForm extends Form
    {
        public function 
    addElement(FormElement $oElement)
        {
            if(
    $oElement instanceof TextFormElement)
            {
                
    $oElement->addAttribute('max-length'5);
            }
            
    $this->aElements[] = $oElement;
        }

    How would you do this given your solution?


    PHP Code:
    $oUsernameField->addAttribute('max-length''5'); 


    What's wrong with this? I suppose I can extend the Tag class to create special purpose classes, which is what I was thinking of doing with radio, checkbox, and select.
    Denny Schlesinger
    web services

  23. #23
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    In my opinion, once you create a generic object that replaces a natural collection of objects, you lose all the benefits of OOP.

    For example you wouldn't have a single login form object, you split it down into its base components and create an object to recompile these if necessary.

    You are already being forced into extending Tag to create the radio, select & checkbox elements, it just seems messy to me.

    I think you missed my point a little with my example, I was wondering how you would target a specific form element in a programmic manner. As far as I can see, you cannot with your solution.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  24. #24
    SitePoint Evangelist captainccs's Avatar
    Join Date
    Mar 2004
    Location
    Caracas, Venezuela
    Posts
    515
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    I think you missed my point a little with my example, I was wondering how you would target a specific form element in a programmic manner. As far as I can see, you cannot with your solution.
    I didn't miss it, I was being cheeky.

    We have a saying in Spanish: "Neither bald nor with two wigs." How many classes do you want to have? One for each tag? That seems like overkill. I started with a form builder but in fact it uses a lot of tags besides the data input tags. I find myself using div, fieldset, legend, label, br, a, and a few others in forms. According to W3C there are some 90 xhtml tags. Where do you cut off?
    Denny Schlesinger
    web services

  25. #25
    SitePoint Enthusiast
    Join Date
    Aug 2005
    Location
    Germany
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I find it easier to build my forms in HTML and implement them through templates than writing a set of classes instead. My forms (once developed) seldomly change so creating them on the fly through code seems like much work for little benefit for me. And there's always the case where the class does not cover the functionality I need. I had the case where I needed to create dependant drop down select lists - does your class also generate the javascript for managing the dependant option elements? Creating multipage forms through code was also difficult for me, wether you use sessions or "fake" multipage through javascript by hiding form elements.

    I do use code though to generate all kinds of lists in forms when the list options are dynamically created - but these classes are more like HTML widgets and do not depend on each other.

    So from my experience I never found it worth to develop a set of classes that deal with creating forms and form elements - but I still haven't seen it all so I might be complety wrong


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
  •