beste manier om classes in te delen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Marlies Maalderink

Marlies Maalderink

06/01/2017 14:51:26
Quote Anchor link
Ik ben bezig met een wordpress plugin voor een simpel contactformulier. Aangezien ik graag wat meer ervaring op wil doen met OOP probeer ik deze helemaal in 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
 
PHP hulp

PHP hulp

22/12/2024 22:22:16
 
Thomas van den Heuvel

Thomas van den Heuvel

06/01/2017 15:33:27
Quote Anchor link
Dit voert misschien wat ver voor een "simpel" contactformulier?

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
 
Marlies Maalderink

Marlies Maalderink

06/01/2017 17:36:17
Quote Anchor link
Hoi Thomas,

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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    
<?php

public function create_text_field( $name ) {
        
        $this->text_name = $name;
        
        $this->text_value = $_POST[ $name ];
        
        echo ?>
<input name="<?php echo $this->text_name; ?>" type="text" id="<?php echo $this->text_name; ?>" value="<?php echo $this->value; ?>" /><?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
 
Ozzie PHP

Ozzie PHP

06/01/2017 17:43:34
Quote Anchor link
Je moet altijd goed onthouden dat je binnen een functie NIKS weergeeft. Je gebruikt dus niet 'echo' binnen de functie maar in plaats daarvan 'return'.

Waar je het formulier opbouwt krijg je dan zoiets als:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

$form
= new Form();
echo $form->addTextField('name');

?>

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
 
Marlies Maalderink

Marlies Maalderink

06/01/2017 23:49:57
Quote Anchor link
Goed dat je het zegt! Ik had dat al wel eens gelezen maar het zit er nog niet helemaal in...

Maar hoe doe je dat dan bij deze regel?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
  <?php
echo ?>
<input name="<?php echo $this->text_name; ?>" type="text" id="<?php echo $this->text_name; ?>" value="<?php echo $this->value; ?>" /><?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
 
Ozzie PHP

Ozzie PHP

07/01/2017 01:22:55
Quote Anchor link
Dat worden dan geen echo's.

Even een verkort voorbeeldje voor het idee.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php

$field
= '<input name="' . $this->text_name .  '" type="text">';
return $field;

?>

Omdat het hier om 'patronen' gaat, zou je ook met sprintf kunnen werken.
 
Ward van der Put
Moderator

Ward van der Put

07/01/2017 08:59:19
Quote Anchor link
De magische methode __toString() is bedoeld voor de afhandeling van een object als een string. Je zou het daarmee bijvoorbeeld zo kunnen aanpakken:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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;
    }
}

?>


Met deze basisopzet kun je elk type formulierinput maken, bijvoorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class Checkbox extends AbstractInput
{
    /**
     * @inheritDoc
     */

    public function __construct($name = null, $value = null)
    {

        parent::__construct($name, $value);
        $this->Type = 'checkbox';
    }
}

?>
 
Marlies Maalderink

Marlies Maalderink

07/01/2017 14:11:04
Quote Anchor link
Wauw Ward, die is mooi! Dank je wel voor deze uitleg, en bovendien kende ik die magic method nog niet, is ook wel handig om die te gebruiken!!

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.
 
Thomas van den Heuvel

Thomas van den Heuvel

07/01/2017 15:55:47
Quote Anchor link
Hm. In mijn opzet heb je een abstracte class "Formfield", wat eigenlijk van alles kan zijn. Elke class afgeleid van een FormField vormt een logische eenheid in het formulier. Zo'n eenheid kan best opgebouwd zijn uit meerdere elementaire formulier elementen (selects, inputs en buttons) die samen een nieuw formulier element vormt (met functionaliteit die verder voert dan de delen waar ze uit opgebouwd zijn), bijvoorbeeld zoiets:
Afbeelding

Dat veld toevoegen aan het formulier verloopt via iets als:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
// 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.
 
Marlies Maalderink

Marlies Maalderink

07/01/2017 18:02:40
Quote Anchor link
Thomas, ik had de class zoals jij voorstelde inmiddels al deels uitgewerkt (alleen de formfields zelf, nog geen validatie erbij) en dat werkt ook prachtig.

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)
PHP script in nieuw venster Selecteer het PHP script
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
<?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;
        
    }    
}

?>



Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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
        
}?>



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
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.