Go Back   SitePoint Forums > Forum Index > Program Your Site > PHP > PHP Application Design
Newsletter FAQ Members List Calendar Mark Forums Read

New to SitePoint Forums? Register here for free!

SitePoint Sponsor
 
Reply
 
Thread Tools Display Modes
Old Feb 28, 2009, 10:27   #1
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Feb 28, 2009, 10:51   #2
AnthonySterling
Twitter: @AnthonySterling
 
AnthonySterling's Avatar
 
Join Date: Apr 2008
Location: North-East, UK.
Posts: 3,910
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: Full-time IT Manager, part-time Freelance PHP Ninja.
Also future, drunk, attendee of the PHPNW10 Conference - come say hello!
AnthonySterling is online now   Reply With Quote
Old Feb 28, 2009, 11:34   #3
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Feb 28, 2009, 14:33   #4
imaginethis
SitePoint Guru
 
Join Date: Jan 2005
Location: heaven
Posts: 948
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!
imaginethis is offline   Reply With Quote
Old Feb 28, 2009, 20:01   #5
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 01:33   #6
Jake Arkinstall
Programming Team Member
bronze trophy
 
Jake Arkinstall's Avatar
 
Join Date: May 2006
Location: Powys, Mid Wales
Posts: 6,734
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 || Rest in peace Dan Schulz

< Need a Custom PHP Script? - PM me >
Jake Arkinstall is offline   Reply With Quote
Old Mar 1, 2009, 02:37   #7
imaginethis
SitePoint Guru
 
Join Date: Jan 2005
Location: heaven
Posts: 948
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!
imaginethis is offline   Reply With Quote
Old Mar 1, 2009, 04:51   #8
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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.


Quote:
...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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 05:27   #9
AnthonySterling
Twitter: @AnthonySterling
 
AnthonySterling's Avatar
 
Join Date: Apr 2008
Location: North-East, UK.
Posts: 3,910
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: Full-time IT Manager, part-time Freelance PHP Ninja.
Also future, drunk, attendee of the PHPNW10 Conference - come say hello!
AnthonySterling is online now   Reply With Quote
Old Mar 1, 2009, 06:36   #10
kyberfabrikken
Community Advisor
silver trophy
 
kyberfabrikken's Avatar
 
Join Date: Jun 2004
Location: Copenhagen, Denmark
Posts: 6,048
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.
kyberfabrikken is offline   Reply With Quote
Old Mar 1, 2009, 08:22   #11
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 08:39   #12
Mastodont
SitePoint Addict
 
Mastodont's Avatar
 
Join Date: Mar 2007
Location: Czech Republic
Posts: 358
It is type hint:
http://www.php.net/manual/en/languag...ypehinting.php
Mastodont is offline   Reply With Quote
Old Mar 1, 2009, 08:48   #13
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
Quote:
Originally Posted by Mastodont View Post

Thanks!
__________________
Denny Schlesinger
web services
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 13:46   #14
imaginethis
SitePoint Guru
 
Join Date: Jan 2005
Location: heaven
Posts: 948
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!
imaginethis is offline   Reply With Quote
Old Mar 1, 2009, 14:19   #15
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 14:35   #16
imaginethis
SitePoint Guru
 
Join Date: Jan 2005
Location: heaven
Posts: 948
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!
imaginethis is offline   Reply With Quote
Old Mar 1, 2009, 14:41   #17
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 14:45   #18
AnthonySterling
Twitter: @AnthonySterling
 
AnthonySterling's Avatar
 
Join Date: Apr 2008
Location: North-East, UK.
Posts: 3,910
Quote:
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: Full-time IT Manager, part-time Freelance PHP Ninja.
Also future, drunk, attendee of the PHPNW10 Conference - come say hello!
AnthonySterling is online now   Reply With Quote
Old Mar 1, 2009, 15:00   #19
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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)

Quote:
Without rendering the tag, there is no way to determine which form element it represents.
Again, I don't understand.
__________________
Denny Schlesinger
web services
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 15:02   #20
AnthonySterling
Twitter: @AnthonySterling
 
AnthonySterling's Avatar
 
Join Date: Apr 2008
Location: North-East, UK.
Posts: 3,910
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: Full-time IT Manager, part-time Freelance PHP Ninja.
Also future, drunk, attendee of the PHPNW10 Conference - come say hello!
AnthonySterling is online now   Reply With Quote
Old Mar 1, 2009, 15:10   #21
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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!


Quote:
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.


Quote:
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 15:29   #22
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 1, 2009, 15:44   #23
AnthonySterling
Twitter: @AnthonySterling
 
AnthonySterling's Avatar
 
Join Date: Apr 2008
Location: North-East, UK.
Posts: 3,910
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: Full-time IT Manager, part-time Freelance PHP Ninja.
Also future, drunk, attendee of the PHPNW10 Conference - come say hello!
AnthonySterling is online now   Reply With Quote
Old Mar 1, 2009, 15:57   #24
captainccs
SitePoint Zealot
 
captainccs's Avatar
 
Join Date: Mar 2004
Location: www.Caracas.ve
Posts: 172
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
captainccs is offline   Reply With Quote
Old Mar 2, 2009, 03:01   #25
frabron
SitePoint Enthusiast
 
Join Date: Aug 2005
Location: Germany
Posts: 25
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
frabron is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread | Next Thread »

Thread Tools
Display Modes

 
Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

 
Forum Jump


All times are GMT -7. The time now is 05:40.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 1998-2009, SitePoint Pty Ltd. All Rights Reserved