beste manier om classes in te delen
Voor het afhandelen van het formulier moet de input worden opgehaald, gevalideerd en daarna moet een mail gestuurd worden. Het leek mij logisch om aparte classes to maken voor de validatie en de afhandeling, maar voor beide heb ik de post variabelen nodig.
Zodoende heb ik een parent class gemaakt die alle post variabelen ophaalt en dan twee child classes voor de validatie en de afhandeling, die dus beide toegang hebben tot alle variabelen.
Is dat een logische methode? Of had ik beter alles in 1 class kunnen zetten? Of het misschien nog op een heel andere manier moeten doen.
Gewijzigd op 06/01/2017 15:01:39 door Marlies Maalderink
Indien je dit enkel wilt opbouwen uit herbruikbare componenten (en wanneer dit enige meerwaarde heeft, bijvoorbeeld omdat je dit vaak doet, zodat deze handeling zich na een eenmalige investering snel terugverdient) zou je eens kunnen kijken naar wat er nu eigenlijk gebeurt:
- het tonen van een formulier
- het verwerken van een formulier
- eventueel met terugkoppeling tijdens invullen (terugkoppeling over fouten) of na verzenden (bedankpagina)
Je bent voornamelijk met formulieren bezig, dus als je herbruikbare code hebt waarmee je formulieren snel kunt opbouwen en formulierinvoer kunt valideren dan kun je daar veel tijdswinst mee pakken. Maar dit wordt pas interessant zodra je dit soort functionaliteit (formulieren + afhandeling) vaker bouwt.
Mogelijke indeling voor classes:
Form
FormField (abstract)
concrete FormField typen (text, checkbox, select, of zelfs custom, samengestelde formulierelementen)
FormFields hang je op aan het formulier. Wanneer je het formulier valideert doorloop je de velden en roep je validatieregels van de specifieke velden aan.
Door alle bouwstenen voor te bakken kun je formulieren snel in elkaar zetten. Daarna zou je eens na kunnen gaan denken over een gebruiksvriendelijke interface zodat je formulieren (letterlijk) in elkaar kunt klikken (en dus zelfs geen code meer hoeft te schrijven, of een minimale hoeveelheid). En dit is volgens mij precies wat sommige plugins (al) doen.
Gewijzigd op 06/01/2017 15:52:00 door Thomas van den Heuvel
Bedankt voor je reactie.
Ik besef nu dat mijn formulier classes echt compleet niet reusable zijn en ik dus eigenlijk de hele middag bezig ben geweest en nu een contactformuliertje heb (wat ik al had maar dan niet OOP) en wat ik niet opnieuw kan gebruiken. Nou ja, van je fouten leer je zeggen ze.
Wat jij zegt zou dan eigenlijk zoiets worden?
Code (php)
waarbij je als volgt tekstfields aan kunt maken:
$form = new Formfields();
$form->create_text_field( $adres );
? (en dan moet er natuurlijk nog een validatie in maar dit heb ik nu even snel getypt)
Gewijzigd op 06/01/2017 17:37:53 door Marlies Maalderink
Waar je het formulier opbouwt krijg je dan zoiets als:
In de praktijk zou je nog meer variabelen kunnen meegeven, bijvoorbeeld de max. lengte van de invoer (maxlength).
Gewijzigd op 06/01/2017 17:49:48 door Ozzie PHP
Maar hoe doe je dat dan bij deze regel?
Code (php)
De eerste echo kan gewoon een return worden maar wat dan met die echo's in de html?
Gewijzigd op 06/01/2017 23:52:36 door Marlies Maalderink
Even een verkort voorbeeldje voor het idee.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$field = '<input name="' . $this->text_name . '" type="text">';
return $field;
?>
$field = '<input name="' . $this->text_name . '" type="text">';
return $field;
?>
Omdat het hier om 'patronen' gaat, zou je ook met sprintf kunnen werken.
__toString() is bedoeld voor de afhandeling van een object als een string. Je zou het daarmee bijvoorbeeld zo kunnen aanpakken:
Met deze basisopzet kun je elk type formulierinput maken, bijvoorbeeld:
De magische methode Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
abstract class AbstractInput
{
/**
* @var string $Type
* The type of form input control. The default type is `text`.
*/
protected $Type = 'text';
/**
* @var array $Attributes
* Other form control attributes.
*/
protected $Attributes = array();
/**
* @param string|null $name
* @param string|null $value
* @return self
*/
public function __construct($name = null, $value = null)
{
if ($name !== null) {
$this->setName($name);
}
if ($value !== null) {
$this->setValue($value);
}
}
/**
* @param void
* @return string
*/
public function __toString()
{
$str = '<input type="' . $this->Type . '"';
foreach ($this->Attributes as $attribute => $value) {
$str .= ' ' . $attribute . '="' . htmlspecialchars($value) . '"';
}
$str .= '>';
return $str;
}
/**
* @param string $name
* @return void
* @throws \InvalidArgumentException
*/
public function setName($name)
{
if (!is_string($name) || empty($name)) {
throw new \InvalidArgumentException();
}
$this->Attributes['name'] = $name;
}
/**
* @param mixed $value
* @return void
*/
public function setValue($value)
{
$this->Attributes['value'] = $value;
}
}
?>
abstract class AbstractInput
{
/**
* @var string $Type
* The type of form input control. The default type is `text`.
*/
protected $Type = 'text';
/**
* @var array $Attributes
* Other form control attributes.
*/
protected $Attributes = array();
/**
* @param string|null $name
* @param string|null $value
* @return self
*/
public function __construct($name = null, $value = null)
{
if ($name !== null) {
$this->setName($name);
}
if ($value !== null) {
$this->setValue($value);
}
}
/**
* @param void
* @return string
*/
public function __toString()
{
$str = '<input type="' . $this->Type . '"';
foreach ($this->Attributes as $attribute => $value) {
$str .= ' ' . $attribute . '="' . htmlspecialchars($value) . '"';
}
$str .= '>';
return $str;
}
/**
* @param string $name
* @return void
* @throws \InvalidArgumentException
*/
public function setName($name)
{
if (!is_string($name) || empty($name)) {
throw new \InvalidArgumentException();
}
$this->Attributes['name'] = $name;
}
/**
* @param mixed $value
* @return void
*/
public function setValue($value)
{
$this->Attributes['value'] = $value;
}
}
?>
Met deze basisopzet kun je elk type formulierinput maken, bijvoorbeeld:
Ik ga er mee aan de slag, als ik er niet uit kom mag ik dan hier weer komen vragen? :)
Toevoeging op 07/01/2017 14:23:36:
Als aanvulling op hierboven, hiermee kan alleen geen textarea gemaakt worden omdat die anders in elkaar zit.
Als ik een class Textarea extends AbstractInput maak waar ook weer de method __toString in gebruikt wordt met variabele $str, en ik maak die zo dat hij geschikt is voor een textarea, gebruikt hij deze dan als ik een instance van Textarea aanmaak, terwijl hij de method uit de abstract class blijft gebruiken bij alle andere classes?
En (uit nieuwsgierigheid) waarom heb je hier gekozen voor een abstract class en niet een parent class? Wat ik ervan begrijp is dat een abstract class altijd minstens één abstract method moet bevatten, wat hier niet het geval is.
Dat veld toevoegen aan het formulier verloopt via iets als:
Code (php)
1
2
3
4
2
3
4
<?php
// addField(<field type>, <field name>, <options>)
$form->addField('moveselect', 'rights', array('label' => 'rights', 'options' => $this->getRights()));
?>
// addField(<field type>, <field name>, <options>)
$form->addField('moveselect', 'rights', array('label' => 'rights', 'options' => $this->getRights()));
?>
Je zou zelfs een formulier-element kunnen maken voor het opbouwen van een rechten-boom.
Ik merk iig dat mijn vraag 'wat is de beste manier om classes in te delen' misschien niet zo makkelijk is als ik dacht, omdat het van veel dingen af hangt en dan nog er meerdere manier zijn.
We kunnen in ieder geval stellen dat mijn aanvankelijke class helemaal fout was, en dat ik bij deze twee betere manier heb om mee aan het werk te kunnen!
Voor de grap dan hier nog even mijn originele 2 classes. Behalve dus dat ze niet reusable zijn en helemaal verkeerd ingedeeld, heb ik hier nog meer dingen gedaan die niet goed zijn/niet zouden moeten of iets dergelijks? (voor de duidelijkheid helemaal onderaan nog de partial met de html
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
class Topsecreet_Contactformulier_Verwerk {
private $naam;
private $email;
private $telefoon;
private $bericht;
private $verzonden;
public function __construct() {
$this->naam = $_POST['naam'];
$this->email = $_POST['email'];
$this->telefoon = $_POST['telefoon'];
$this->bericht = $_POST['bericht'];
$this->verzonden = $_GET['verzonden'];
}
//de method om de variabele waar de naam in is gepost op te vragen
public function get_naam() {
return $this->naam;
}
//de method om de variabele waar het emailadres in is gepost op te vragen
public function get_email() {
return $this->email;
}
//de method om de variabele waar het telefoonnummer in is gepost op te vragen
public function get_telefoon() {
return $this->telefoon;
}
//de method om de variabele waar het bericht in is gepost op te vragen
public function get_bericht() {
return $this->bericht;
}
//de method om te contoleren of het formulier verzonden is of niet
public function get_verzonden() {
return $this->verzonden;
}
}
class Topsecreet_Contactformulier_Validate extends Topsecreet_Contactformulier_Verwerk {
//hier slaan we de foutmeldingen in op
private $errors;
public function __construct() {
parent::__construct();
$this->errors = $errors;
}
//valideer invoerveld naam en sanitize uitvoer
public function validate_naam() {
if( $this->get_naam() == "" ){
return $this->errors = 1;
} else {
return $this->naam = filter_var( $this->get_naam(), FILTER_SANITIZE_STRING );
}
}
//valideer invoerveld email en sanitize uitvoer
public function validate_email() {
if( $this->get_email() == "" || filter_var( $this->get_email(), FILTER_VALIDATE_EMAIL ) === false ) {
return $this->errors = 1;
} else {
return $this->email = filter_var( $this->get_email(), FILTER_SANITIZE_EMAIL );
}
}
//sanitize telefoon uitvoer
public function sanitize_telefoon() {
return $this->telefoon = filter_var( $this->get_telefoon(), FILTER_SANITIZE_STRING );
}
//valideer invoerveld bericht en sanitze uitvoer
public function validate_bericht() {
if( $this->get_bericht() == "" ){
return $this->errors = 1;
} else {
return $this->bericht = filter_var($this->get_bericht(), FILTER_SANITIZE_STRING);
}
}
//controleer of er fouten zijn en zo ja, geef de 1 terug. Dit is nodig om te bepalen of het formulier getoond moet worden of
//dat we verder gaan met het aanmaken en verzenden van de email
public function check_errors() {
$this->validate_bericht();
$this->validate_email();
$this->validate_naam();
return $this->errors;
}
}
?>
class Topsecreet_Contactformulier_Verwerk {
private $naam;
private $email;
private $telefoon;
private $bericht;
private $verzonden;
public function __construct() {
$this->naam = $_POST['naam'];
$this->email = $_POST['email'];
$this->telefoon = $_POST['telefoon'];
$this->bericht = $_POST['bericht'];
$this->verzonden = $_GET['verzonden'];
}
//de method om de variabele waar de naam in is gepost op te vragen
public function get_naam() {
return $this->naam;
}
//de method om de variabele waar het emailadres in is gepost op te vragen
public function get_email() {
return $this->email;
}
//de method om de variabele waar het telefoonnummer in is gepost op te vragen
public function get_telefoon() {
return $this->telefoon;
}
//de method om de variabele waar het bericht in is gepost op te vragen
public function get_bericht() {
return $this->bericht;
}
//de method om te contoleren of het formulier verzonden is of niet
public function get_verzonden() {
return $this->verzonden;
}
}
class Topsecreet_Contactformulier_Validate extends Topsecreet_Contactformulier_Verwerk {
//hier slaan we de foutmeldingen in op
private $errors;
public function __construct() {
parent::__construct();
$this->errors = $errors;
}
//valideer invoerveld naam en sanitize uitvoer
public function validate_naam() {
if( $this->get_naam() == "" ){
return $this->errors = 1;
} else {
return $this->naam = filter_var( $this->get_naam(), FILTER_SANITIZE_STRING );
}
}
//valideer invoerveld email en sanitize uitvoer
public function validate_email() {
if( $this->get_email() == "" || filter_var( $this->get_email(), FILTER_VALIDATE_EMAIL ) === false ) {
return $this->errors = 1;
} else {
return $this->email = filter_var( $this->get_email(), FILTER_SANITIZE_EMAIL );
}
}
//sanitize telefoon uitvoer
public function sanitize_telefoon() {
return $this->telefoon = filter_var( $this->get_telefoon(), FILTER_SANITIZE_STRING );
}
//valideer invoerveld bericht en sanitze uitvoer
public function validate_bericht() {
if( $this->get_bericht() == "" ){
return $this->errors = 1;
} else {
return $this->bericht = filter_var($this->get_bericht(), FILTER_SANITIZE_STRING);
}
}
//controleer of er fouten zijn en zo ja, geef de 1 terug. Dit is nodig om te bepalen of het formulier getoond moet worden of
//dat we verder gaan met het aanmaken en verzenden van de email
public function check_errors() {
$this->validate_bericht();
$this->validate_email();
$this->validate_naam();
return $this->errors;
}
}
?>
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
if( "ja" == $this->validate_form->get_verzonden() && 1 === $this->validate_form->check_errors() ) {
echo "er zijn fouten gevonden in het formulier";
} elseif ( "ja" != $this->validate_form->get_verzonden() ) { ?>
<form id="form1" name="form1" method="post" action="<?php echo esc_url( $_SERVER['SELF'] ) . '?verzonden=ja'; ?>">
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_naam() ){ echo "<i>* Naam:</i>"; } else { echo "<b>Naam:</b>"; } ?><br />
<input name="naam" type="text" class="formulier" id="naam" size="40" value="<?php echo $this->validate_form->get_naam(); ?>" /><br /><br />
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_email() ) { echo "<i>* Email:</i>"; } else { echo "<b>Email:</b>"; } ?><br />
<input name="email" type="text" class="formulier" id="email" size="40" value="<?php echo $this->validate_form->get_email(); ?>" /><br /><br />
<b>Telefoon:</b><br />
<input name="telefoon" type="text" class="formulier" id="telefoon" size="40" value="<?php echo $this->validate_form->get_telefoon(); ?>" /><br /><br />
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_bericht() ){ echo "<i>* Bericht:</i>"; } else { echo "<b>Bericht:</b>"; } ?><br />
<textarea name="bericht" cols="40" rows="10" class="formulier" id="bericht"><?php echo $this->validate_form->get_bericht(); ?></textarea><br /><br />
<input type="image" name="verzeden" src="afbeeldingen/verzenden.jpg" />
<?php } else {
//verstuur de email
}?>
if( "ja" == $this->validate_form->get_verzonden() && 1 === $this->validate_form->check_errors() ) {
echo "er zijn fouten gevonden in het formulier";
} elseif ( "ja" != $this->validate_form->get_verzonden() ) { ?>
<form id="form1" name="form1" method="post" action="<?php echo esc_url( $_SERVER['SELF'] ) . '?verzonden=ja'; ?>">
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_naam() ){ echo "<i>* Naam:</i>"; } else { echo "<b>Naam:</b>"; } ?><br />
<input name="naam" type="text" class="formulier" id="naam" size="40" value="<?php echo $this->validate_form->get_naam(); ?>" /><br /><br />
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_email() ) { echo "<i>* Email:</i>"; } else { echo "<b>Email:</b>"; } ?><br />
<input name="email" type="text" class="formulier" id="email" size="40" value="<?php echo $this->validate_form->get_email(); ?>" /><br /><br />
<b>Telefoon:</b><br />
<input name="telefoon" type="text" class="formulier" id="telefoon" size="40" value="<?php echo $this->validate_form->get_telefoon(); ?>" /><br /><br />
<?php if( "ja" == $this->validate_form->get_verzonden() && 0 === $this->validate_form->validate_bericht() ){ echo "<i>* Bericht:</i>"; } else { echo "<b>Bericht:</b>"; } ?><br />
<textarea name="bericht" cols="40" rows="10" class="formulier" id="bericht"><?php echo $this->validate_form->get_bericht(); ?></textarea><br /><br />
<input type="image" name="verzeden" src="afbeeldingen/verzenden.jpg" />
<?php } else {
//verstuur de email
}?>
Toevoeging op 07/01/2017 18:05:00:
oh, ik zie net de de html niet klopt, omdat ik dit uit 2 bestanden heb samengevoegd voordat ik het hier plakte. Als er fouten zijn moet het formulier natuurlijk ook getoond worden! ;)
Gewijzigd op 07/01/2017 18:03:42 door Marlies Maalderink