Dynamic forms based on VO/DTO & Type-map

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
xinnex
Forum Commoner
Posts: 33
Joined: Sun Jan 07, 2007 7:38 pm
Location: Copenhagen, Denmark

Dynamic forms based on VO/DTO & Type-map

Post by xinnex »

I'm currently in the process of redesigning a PHP5 framework which so far has been mimicking things like CakePHP or Symfony (not using Active Record!)

So far we've been using the DAO-pattern and simply passed our VO/DTO-objects directly from the controller to the view.
This lead to extremely fast development since we could do things like:

In the controller:

Code: Select all

$this->posts = $postDAO->findAll();
Int the view:

Code: Select all

foreach($posts as $post)
{
	$this->add(new Headline($post->getTitle));
}
Problems arise though, when the VO/DTO-objects change and the views subsequently has to be updated.
Obviously the views are too dependent on the VO's methods... so what to do?

"A generic model which could be iterated in the view", you say?

But what about the forms?.. We'll.. We probably all know how boring it can be to design forms.
So how about this approach?:

VO/DTO:

Code: Select all

class Customer
{
	private $id;
	private $name;

	public function setId($id)
	{
		$this->id = $id;
	}
	public function getId()
	{
		return $this->id;
	}
	public function setName($name)
	{
		$this->name = $name;
	}
	public function getName()
	{
		return $this->name;
	}
}
Type-map (maps matching getters/setters in the VO/DTO):

Code: Select all

class CustomerControlMap extends BaseControlMap
{
	private $maps;
	public function __construct()
	{
		$this->maps = array();
		$this->maps['name'] = new TextField();
		$this->maps['id'] = new HiddenField();
	}
	public function getMap($fieldName)
	{
		return $this->maps[$fieldName];
	}
}
Converts a customer to a list-object (using "get_class_methods()" in the DynamicListAdapter-class):

Code: Select all

class CustomerList extends DynamicListAdapter
{
	public function __construct(Customer $customer)
	{
		parent::__construct($customer);
	}
	public function getList()
	{
		return parent::getList();
	}
}
Imaginary form-generator call:

Code: Select all

$list = new CustomerList(new Customer());
$form = FormGenerator::generate($list->getList(), new CustomerControlMap());
$form->setAction('action.php');
$form->setMethod('post');
Resulting in a Form-object with a TextField and HiddenField as its children, which could be outputted like:

Code: Select all

<form method="post" action="action.php">
 <input type="hidden" name="id" />
 ...
</form>
This way the view (with the formgenerator-call) is only coupled with the type-map.
So when the VO/DTO changes, you would only have to update the Type-map.

Thoughts, critics (and "HERESY!"-claims) appreciated, and sorry for the long post.
User avatar
xinnex
Forum Commoner
Posts: 33
Joined: Sun Jan 07, 2007 7:38 pm
Location: Copenhagen, Denmark

Post by xinnex »

Maybe people are intimidated by the long post, so I'll rephrase it a bit:

How would you deal with dynamic form-generation, preferably in an OO-fashion?
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

You'd use my form's library, OsisForms :D

Alpha will be out within a week. Source code is available for viewing now on sourceforge. After that there's a possibly it'll become part of the Zend Framework. Till then there's a form component in the Zebra PHP framework and Cake. I looked at Zebra in some depth. You write form templates and define your own 'error blocks' you then attach validations to widgets.

Dedicated libraries are patForms (quite powerful, design ok, complex) and QuickForm (moderate power, not well designed, good community backing). None of the above are robust enough for web application level form requirements but if you have less rigorous requirements they might be enough.

My library is different in that it is a flexibly, powerful, oo api that can be easily extended. The fundamentals of the library aren't even tied to HTML / HTTP POST as you can write your own renderers and retrievers. Validation system is extendible and loosely coupled from the rest of the library. I could go on.
User avatar
xinnex
Forum Commoner
Posts: 33
Joined: Sun Jan 07, 2007 7:38 pm
Location: Copenhagen, Denmark

Post by xinnex »

ole wrote: My library is different in that it is a flexibly, powerful, oo api that can be easily extended. The fundamentals of the library aren't even tied to HTML / HTTP POST as you can write your own renderers and retrievers. Validation system is extendible and loosely coupled from the rest of the library. I could go on.
Looks very interesting. Could you point me to a "getting started"- or a "crash course"-like resource for it?
I browsed through the documentation in svn, but it was somewhat.. erh.. not-there-like? Pretty UML though :wink:
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Umm yeah... :oops:

I wrote a whole load of docs for it and then I changed so much that it no longer applied so you're gonna have to wait I'm afraid.
User avatar
xinnex
Forum Commoner
Posts: 33
Joined: Sun Jan 07, 2007 7:38 pm
Location: Copenhagen, Denmark

Post by xinnex »

A quick example would probably be sufficient... (maybe something you've posted around here?.. I'll look around)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I think the next step from you scheme is to build an actual form controller. The your control maps can be on a field by field by field basis and you can attach as many fields as needed and define them as you do it. So you might end up with somthing like:

Code: Select all

$customerform->addMap('name', new TextField());
$customerform->addMap('id', new HiddenField());
(#10850)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Sadly no. I don't have a factory class yet either so I can't show you anything. Sorry, you will have to wait that full week.
User avatar
xinnex
Forum Commoner
Posts: 33
Joined: Sun Jan 07, 2007 7:38 pm
Location: Copenhagen, Denmark

Post by xinnex »

arborint wrote:I think the next step from you scheme is to build an actual form controller. The your control maps can be on a field by field by field basis and you can attach as many fields as needed and define them as you do it. So you might end up with somthing like:

Code: Select all

$customerform->addMap('name', new TextField());
$customerform->addMap('id', new HiddenField());
Any resources on such a formcontroller, or just a quick mockup? Much appreciated input..

EDIT: I'm trying to come up with an approach that requires a minimum of effort to maintain/update.
Post Reply