Ik heb een formulier gemaakt volgens OOP principe. Ik wil dat de Error message in het formulier getoond wordt op de plek waar het veld fout is. Hoe kan ik dit regelen?

In het vogende stuk code (Ik weet niet hoe ik de stukken code van elkaar kan schreiden:
Code Form class:
Code Element class
Code Text Element
Code RegistratieForm
Code formulier.php


[code]
<?php


abstract class Form implements IForm {

private $elements;
private $id;
private $action;
private $method;
private $attribs;
private $isGeldig;
private $errorMessages;
private $values;

const METH_POST = 'post';
const METH_GET = 'get';

public function __construct($options) {
$this->isGeldig = true;
$this->errorMessages = array();
$this->values = array();
$this->id = isset($options['id']) ? $options['id'] : 'Formulier';
$this->action = isset($options['action']) ? $options['action'] : '#';
$this->method = isset($options['method']) ? $options['method'] : self::METH_POST;
//attribs zijn alle overige HTML-attributen die je aan een formulier zou willen toekennen: style, class etc.
$this->attribs = isset($options['attribs']) ? $options['attribs'] : '';
}

public function add(IElement $elm) {
$this->elements[$elm->getName()] = $elm;
}

public function render() {
//PHP_EOL is een ingebouwde constante in PHP die een nieuwe regel maakt (zie je in broncode van de HTML)

$html = "<form method='{$this->method}' action='{$this->action}' id='{$this->id}' {$this->attribs}>" . PHP_EOL;
foreach ($this->elements as $element) {
$html .= $element->render() . '<br />' . PHP_EOL;
}
$html .= "</form>" . PHP_EOL;
return $html;
}

public function isValid() {
$this->clean();
foreach ($this->elements as $element) {
if (!$element->isValid()) {
$this->isGeldig = false;
$this->errorMessages[$element->getName()] = $element->getMessages();
}
}

return $this->isGeldig;
}

public function getMessages() {
return $this->errorMessages;
}

public function clean() {
foreach ($this->elements as $element) {
$element->clean();
}
}

public function getValues() {
foreach ($this->elements as $key => $element) {
$this->values[$key] = $element->getValue();
}
return $this->values;
}

}
?>

code class Element
<?php

abstract class Element implements IElement {


protected $filters;
protected $validators;
protected $options;
protected $value;
protected $name;
protected $label;
protected $attribs;

protected $isGeldig;
protected $errorMessages;

public function __construct(array $options = array())
{
$this->isGeldig = true;
$this->filters = array();
$this->validators = array();
$this->value = '';
$this->setOptions($options);
}

public function setOptions(array $options)
{
$this->name = isset($options['name']) ? $options['name'] : 'standaardnaam'; //eigenlijk moet de naam worden getest; niet alle namen zijn volgens de HTML-specs toegestaan!
$this->label = isset($options['label']) ? $options['label'] : 'label';
$this->value = isset($options['value']) ? $options['value'] : '';
$this->attribs = isset($options['attribs']) ? $options['attribs'] : '';
if (isset($options['validators']) && is_array($options['validators'])) {
foreach ($options['validators'] as $validator) {
$this->addValidator($validator);
}
}
if (isset($options['filters']) && is_array($options['filters'])) {
foreach ($options['filters'] as $filter) {
$this->addFilter($filter);
}
}
}

public function addValidator(Validator $validator)
{
$this->validators[] = $validator;
}

abstract public function render();

public function addFilter(Filter $filter)
{
$this->filters[] = $filter;
}

public function isValid()
{
foreach ($this->validators as $validator) {
if (!$validator->isValid($this->value)) {
$this->isGeldig = false;
$this->errorMessages[] = $validator->getMessages();
}
}
return $this->isGeldig;
}

public function clean()
{
$localValue = $this->value;
foreach ($this->filters as $filter) {
$localValue = $filter->clean($localValue);
}
$this->value = $localValue;
}

public function getValue()
{
return $this->value;
}

public function getMessages()
{
return $this->errorMessages;
}

public function getName()
{
return $this->name;
}


}
?>
Code Text element

<?php
/**
* User: GJ
* Name: TextElement.php
* Date: 14-8-13
* Time: 12:10
*/

class TextElement extends Element {

public function render()
{
$html = '';
$html .= '<label>' . $this->label;
$html .= "<input type='text' name='{$this->name}' value='{$this->value}' $this->attribs>";
$html .= '</label>';
$html .= $this->getMessages();
return $html;
}
}
?>
Code RegistratieForm:

<?php

class RegistratieForm extends Form {

public function __construct($options) {
parent::__construct($options);

$initials = new TextElement();
// we kunnen een element aanmaken en pas daarna de opties zetten, zoals hier:
$initials->setOptions(array(
'name' => 'voorletters',
'label' => 'Uw voorlettes',
'value' => isset($_GET['voorletters']) ? $_GET['voorletters'] : '',
'validators' => array(
new InitialValidator(array() /* no options necessary */),
),
)
);

$lastname = new TextElement();
// we kunnen een element aanmaken en pas daarna de opties zetten, zoals hier:
$lastname->setOptions(array(
'name' => 'achternaam',
'label' => 'Uw achternaam',
'value' => isset($_GET['achternaam']) ? $_GET['achternaam'] : '',
'validators' => array(
new LastNameValidator(array() /* no options necessary */),
),
'filters' => array(
new FilterStripTags(),
new FilterTrim()
)
)
);
$email = new TextElement();
// we kunnen een element aanmaken en pas daarna de opties zetten, zoals hier:
$email->setOptions(array(
'name' => 'email',
'label' => 'Uw e-mailadres',
'value' => isset($_GET['email']) ? $_GET['email'] : '',
'validators' => array(
new EmailValidator(array() /* no options necessary */),
),
'filters' => array(
new FilterStripTags(),
new FilterTrim()
)
)
);

// of we maken een element en geven bij de constructie al de opties weer, zoals hier
$password = new PasswordElement(array(
'name' => 'password',
'label' => 'Uw wachtwoord',
'value' => isset($_GET['password']) ? $_GET['password'] : '',
'validators' => array(
new StringLengthValidator(array('min' => 3, 'minError' => 'Het wachtwoord is te kort', 'max' => 12, 'maxError' => 'Het wachtwoord is te lang'))
),
'filters' => array(
new FilterStripTags(),
new FilterTrim()
)
)
);
$submit = new SubmitElement(array(
'value' => 'verzenden',
'name' => 'verzenden',
)
);

//de gemaakte elementen toevoegen aan het formulier
$this->add($initials);
$this->add($lastname);
$this->add($email);
$this->add($password);
$this->add($submit);
}

}
?>
code formulier.php:

<?php

//autoloader
function __autoload($class) {
require_once $class . '.php';
}

//het formulier aanmaken
$form = new RegistratieForm(
array(
'id' => 'frmRegistratie',
'css' => 'userform',
'method' => 'get',
'action' => ''
)
);

//de elementen aanmaken:


if (isset($_GET['verzenden'])) {

$result = $form->isValid();
if ($result == TRUE) {
var_dump('correct', $form->getValues());
} else {
var_dump('', $form->getMessages());
}
die();
}

$html = $form->render();


echo $html;

?>

Hopelijk kan iemand mij helpen om de foutmeldingen in het formulier te krijgen op de plek waar de waarde niet valide is. (en de rest van het formulier ingevuld houden).

Alvast bedankt!
zonder jouw classes helemaal gelezen te hebben, hier hoe ik het doe:



<?php
class form
{
	private $errors;
	
	function validate()
	{
		if($_POST['email'] == '')
			$this->errors['email'] = 'Je hebt geen emailadres ingevuld.';
		
		// en nog meer velden die je kunt valideren
		
		if(count($this->errors))
			return false;
			
		return true;
	}
	
	function getError($id)
	{
		if(isset($this->errors[$id]))
			return $this->errors[$id];
			
		return ''; 
	}
};
?>
Het probleem is dat de foutmelding nu in plaats van het formulier komt dmv een vardump. MIsschien wil je toch naar me code kijken, om te zien waar ik hem moet aanpassen. Ik heb namelijk de class Form, zoals je hierboven beschrijft als een abstracte klasse. De elementen zelf worden via de abstracte klasse Element in de klasse Text element (en andere gerenderd). Hier moet ik volgens mij ergens die foutmelding in kunnen weergeven, maar dan moet ik nog wel wat doen met de code onderaan in formulier.php (staat onderaan mijn lap code).

De rendercode va TextElement.php is deze:

[code]
<?php


class TextElement extends Element {

public function render()
{
$html = '';
$html .= '<label>' . $this->label;
$html .= "<input type='text' name='{$this->name}' value='{$this->value}' $this->attribs>";
$html .= '</label>';
$html .= $this->getMessages();
return $html;
}
}
[code]

Hopelijk kun je me verder helpen!
de form class is verantwoordelijk voor het formulier als geheel en gebruikt hierbij verschillende objecten. een extra object kan dan een 'error' object zijn. Nu heb je in de form class een functie render(). deze laat de verschillende elementen renderen. bij het aanmaken van je elementen lees je de GET variabelen uit. dat is dan dus ook de plek om error-elementen aan te maken. wellicht is het een idee om aan de basis 'element'-class een functie toe te voegen als 'setError()' die de validatie functie aanroept als er een invoer wordt afgekeurd. Binnen deze functie moet dan een nieuw Error object aangemaakt worden zodat de classes zo abstract mogelijk blijven. als de render functie van de elementen worden aangeroepen dan moet ook de render functie van het error-object aangeroepen worden. zo kun je de visualisatie van de errors later zeer simpel aanpassen. Om het compleet te maken zou ik aan de constructor van de form en/of de elementen meegeven welk error object je wilt gebruiken zodat je het error object kunt overerven.


Toevoeging op 20/08/2013 20:22:34:

een andere tip:
de $_GET en $_POST zijn gewoon arrays. je kunt gewoon $arr = $_GET doen om de hele array in één keer te kopiëren. gebruik dan in de rest van je code gewoon $arr zodat je makkelijker kan switchen van GET naar POST en eventueel SESSION.
Ik ben echt een beginneling wat betreft oo programmeren. Ik begrijp je betoog wel, maar de juiste code weet ik zo niet. Je zou me heel erg helpen om het in mijn code uit te werken, zodat ik begrijp wat er moet gebeuren.
Ik begrijp het als dat veel gevraagd is, maar hoop toch dat je het wilt doen, ik zou er enorm mee geholpen zijn.
Morgen wil ik (misschien) wel even voor je kijken. zou handig zijn om de volledige code te hebben
Als je me een mailtje stuurt, heb ik je mailadres en zal ik de volledige code toesturen.

Reageren