[OOP] Eerste script

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Michael -

Michael -

18/10/2013 08:51:11
Quote Anchor link
Hoi,

Ik probeer de overgang van PHP Procedural naar PHP OOP te maken.
Om te begrijpen hoe OOP werkt en op welke manier het nuttiger kan zijn dan procedural wil ik graag jullie mening, opmerkingen, kritiek, etc horen over mijn eerste OOP script.

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<?php
function printr($a){
    echo '<pre>';print_r($a);echo'</pre>';
}


class Form {
    public function __construct($fName){
        $this->fName = '<form method="POST" name="' . $fName . '">'.PHP_EOL;
    }

    
    public function getForm(){
        return $this->fName;
    }

    
    public function endForm(){
        return '</form>'.PHP_EOL;
    }
}


class Input {
    public function __construct($iName){
        $this->iName = $iName;
    }

    
    public function addType($iType){
        $this->allowedTypes = Array('text','password','date','email','submit','checkbox','radio');
        
        if(in_array($iType,$this->allowedTypes))
        {

            $this->iType = $iType;
        }

        else
        {
            throw new Exception('Input Type not allowed');
        }
    }

    
    public function checked($iChecked){
        if(($this->iType == 'checkbox' || $this->iType == 'radio') && $iChecked == TRUE)
        {

            $this->iChecked = TRUE;
        }

        else
        {
            $this->iChecked = FALSE;
        }
    }

    
    public function group($iGroup){
        if($iGroup == TRUE)
        {

            $this->iGroup = TRUE;
        }
    }

    
    public function addValue($iValue){
        $this->iValue = $iValue;
    }

    
    public function addPlaceholder($iPlaceholder){
        $this->iPlaceholder = $iPlaceholder;
    }

    
    public function getInput(){
        $input = '<input';
        if(isset($this->iType))
        {

            $input .= ' type="' . $this->iType . '"';
        }

        if(isset($this->iName))
        {

            if(isset($this->iType) && ($this->iType == 'checkbox' || $this->iType == 'radio'))
            {

                $input .= ' name="' . $this->iName. '[]"';
            }

            else
            {
                $input .= ' name="' . $this->iName . '"';
            }

            $input .= ' id="' . $this->iName . '"';
        }

        if(isset($this->iValue))
        {

            $input .= ' value="' . $this->iValue . '"';
        }

        if(isset($this->iPlaceholder))
        {

            $input .= ' placeholder="' . $this->iPlaceholder .'"';
        }

        if(isset($this->iChecked) && $this->iChecked == TRUE)
        {

            $input .= ' checked="checked"';
        }

        $input .= ' /><br />'.PHP_EOL;
        
        return $input;
    }
}


class Select {
    public function __construct($sName){
        $this->sName = $sName;
    }

    
    public function addOption($sOptionValue,$sOption){
        $this->sOption[][$sOptionValue] = $sOption;
    }

    
    public function getSelect(){
        $selectbox = '<select name="' . $this->sName . '">'.PHP_EOL;
        foreach($this->sOption AS $optionArray)
        {

            foreach($optionArray AS $value=>$option)
            {

                $selectbox .= '<option value="' . $value . '">' . $option . '</option>'.PHP_EOL;
            }
        }

        $selectbox .= '</select><br />'.PHP_EOL;
        return $selectbox;
    }
}


class Box {
    public function __construct($bName){
        $this->bName = $bName;
    }

    
    public function addValue($bValue){
        $this->bValue = $bValue;
    }

    
    public function addPlaceholder($bPlaceholder){
        $this->bPlaceholder = $bPlaceholder;
    }

    
    public function getBox(){
        $box = '<textarea name="' . $this->bName . '"';
        if(isset($this->bPlaceholder)) { $box .= ' placeholder="' . $this->bPlaceholder . '"'; }
        $box .= '>';
        if(isset($this->bValue)) { $box .= $this->bValue; }
        $box .= '</textarea><br />'.PHP_EOL;
        return $box;
    }
}


class Button {
    public function __construct($bValue){
        $this->bValue = $bValue;
    }

    
    public function getButton(){
        return '<button>' . $this->bValue . '</button><br />'.PHP_EOL;
    }
}


if(strtolower($_SERVER['REQUEST_METHOD']) == 'post')
{

    printr($_POST);
}


$form = new Form('test');
echo $form->getForm();

$select = new Select('aanhef');
$select->addOption('','Maak een keuze');
$select->addOption('Meneer','Mr.');
$select->addOption('De heer','Dhr.');
$select->addOption('Mevrouw','Mw.');
$select->addOption('Dokter','Dr.');
$select->addOption('Anders','Anders');
echo $select->getSelect();

$input = new Input('name');
$input->addType('text');
$input->addValue('Jan');
$input->addPlaceholder('Naam van persoon');
echo $input->getInput();

$input = new Input('age');
$input->addType('text');
$input->addValue('36');
$input->addPlaceholder('Leeftijd van persoon');
echo $input->getInput();

$input = new Input('pass');
$input->addType('password');
$input->addValue('secret');
$input->addPlaceholder('Wachtwoord');
echo $input->getInput();

$input = new Input('optie');
$input->addType('checkbox');
$input->addValue('check optie 1');
$input->checked(TRUE);
echo $input->getInput();

$input = new Input('optie');
$input->addType('checkbox');
$input->addValue('check optie 2');
$input->checked(FALSE);
echo $input->getInput();

$input = new Input('optie');
$input->addType('radio');
$input->addValue('radio optie 1');
$input->checked(TRUE);
echo $input->getInput();

$input = new Input('optie');
$input->addType('radio');
$input->addValue('radio optie 2');
$input->checked(FALSE);
echo $input->getInput();

$box = new Box('message');
$box->addValue('');
$box->addPlaceholder('Typ hier je bericht');
echo $box->getBox();

$button = new Button('Opslaan');
echo $button->getButton();

echo $form->endForm();

?>
Gewijzigd op 18/10/2013 10:23:25 door Michael -
 
PHP hulp

PHP hulp

18/12/2024 14:03:49
 
Jeroen Kwakkel

Jeroen Kwakkel

18/10/2013 09:42:31
Quote Anchor link
Wat je doet ziet er goed uit. Ik zou zelf het iets anders hebben gedaan. Zo zou ik een input classen hebben gemaakt en dan de types laten overerven.

bijvoorbeeld

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
class Tekst extends Input{
    public function __construct($iName, $placeholder, $val = null){
        $this->iName = $iName;
        $this->addPlaceholder($placeholder);
        $this->addType("text");
        $this->addValue($val);
    }
}


nu kan ik een tekst veld maken zonder dat die controle die jij hebt nodig is. Nu kun je de tekst veld aanroepen met

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
$tekst = new Tekst('text', 'Leeftijd van persoon');
echo $tekst->getInput();


Je kunt wel of geen value meegeven, dus "$tekst = new Tekst('text', 'Leeftijd van persoon', 36);" werkt ook gewoon. Als je de constructor naar private set van input maak je het gelijk onmogelijk om die direct aan te roepen. Dus dan moet wel de $tekst etc gebruikt worden.

Nogmaals ik zie niks verkeerd van wat je doet, maar gewoon twee nieuwe OOP concepten (overerven en standaard waardes geven aan attributen in een functie) die jou formulier generator kunnen verbeteren.

Je zou zelf het volgende kunnen doen

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
echo $tekst = (new Tekst('text', 'Leeftijd van persoon'))->getInput();



Toevoeging op 18/10/2013 09:42:45:
Gewijzigd op 18/10/2013 09:44:07 door Jeroen Kwakkel
 
Michael -

Michael -

18/10/2013 10:13:34
Quote Anchor link
Jeroen,

Bedankt voor je reactie.
Ik had niet verwacht dat het er gelijk al goed uit zou zien, maar fijn om te horen.
Jou voorbeeld neem ik zeker mee. Op dit moment gebruik ik nog geen 'extends', maar wil dit zeker wel gebruiken.

Ik had verwacht dat ik waarschijnlijk onnodig vaak 'value','placeholder',e.d. had aangemaakt. Dit zou ik kunnen voorkomen met 'extends' begrijp ik.

Edit:

Jeroen, jou laatste voorbeeld geeft een 'unexpected T_OBJECT_OPERATOR'.
Gewijzigd op 18/10/2013 11:40:54 door Michael -
 
Donny Wie weet

Donny Wie weet

18/10/2013 12:17:35
Quote Anchor link
@jeroen: ik had een vraag in combinatie met het script dat je voor mij had beoordeeld. Is dat van mij niet handiger en sneller? Het is dan enkelt

$this->newField('veld_naam', 'label_naam', 'omschrijving')

bij de manier van michael moet je alles apart toewijzen:

$input = new Input('pass');
$input->addType('password');
$input->addValue('secret');
$input->addPlaceholder('Wachtwoord');
echo $input->getInput();


Tis gewoon een vraag, ziet er namelijk verder nice uit :)
 
Michael -

Michael -

18/10/2013 12:25:02
Quote Anchor link
Donny Wie weet op 18/10/2013 12:17:35:
@jeroen: ik had een vraag in combinatie met het script dat je voor mij had beoordeeld. Is dat van mij niet handiger en sneller? Het is dan enkelt

$this->newField('veld_naam', 'label_naam', 'omschrijving')

bij de manier van michael moet je alles apart toewijzen:

$input = new Input('pass');
$input->addType('password');
$input->addValue('secret');
$input->addPlaceholder('Wachtwoord');
echo $input->getInput();


Tis gewoon een vraag, ziet er namelijk verder nice uit :)

Wil je een stukje van dat script laten zien of heb je een link naar een topic waar het in staat?

Het kan inderdaad wel sneller met 1 regel zoals Jeroen ook in zijn voorbeeld aangeeft. Hierop heb ik het script ook aangepast.

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
<?php
class Input {
    public function __construct($iName, $iLabel = null,  $iPlaceholder = null, $iValue = null){
        $this->iName = $iName;
        $this->addPlaceholder($iPlaceholder);
        $this->addType('text');
        $this->addValue($iValue);
        $this->addLabel($iLabel);
    }

    
    public function addType($iType){
        $this->allowedTypes = Array('text','password','date','email','submit','checkbox','radio');
        
        if(in_array(strtolower($iType),$this->allowedTypes))
        {

            $this->iType = $iType;
        }

        else
        {
            throw new Exception('Input Type not allowed');
        }
    }

    
    public function checked($iChecked){
        if(($this->iType == 'checkbox' || $this->iType == 'radio') && $iChecked == TRUE)
        {

            $this->iChecked = TRUE;
        }

        else
        {
            $this->iChecked = FALSE;
        }
    }

    
    public function addValue($iValue){
        $this->iValue = $iValue;
    }

    
    public function addPlaceholder($iPlaceholder){
        $this->iPlaceholder = $iPlaceholder;
    }

    
    public function addLabel($iLabel){
        $this->iLabel = $iLabel;
    }

    
    public function getInput(){
        $input = '<label';
        if(isset($this->iName))
        {

            $input .= ' for="' . $this->iName . '"';
        }

        $input .= '>';
        if(isset($this->iLabel))
        {

            $input .= $this->iLabel;
        }

        $input .= '</label><input';
        if(isset($this->iType))
        {

            $input .= ' type="' . $this->iType . '"';
        }

        if(isset($this->iName))
        {

            if(isset($this->iType) && ($this->iType == 'checkbox' || $this->iType == 'radio'))
            {

                $input .= ' name="' . $this->iName. '[]"';
            }

            else
            {
                $input .= ' name="' . $this->iName . '"';
            }

            $input .= ' id="' . $this->iName . '"';
        }

        if(isset($this->iValue))
        {

            $input .= ' value="' . $this->iValue . '"';
        }

        if(isset($this->iPlaceholder))
        {

            $input .= ' placeholder="' . $this->iPlaceholder .'"';
        }

        if(isset($this->iChecked) && $this->iChecked == TRUE)
        {

            $input .= ' checked="checked"';
        }

        $input .= ' /><br />'.PHP_EOL;
        
        return $input;
    }
}

?>

Hier heb ik het nou zo gedaan dat er bepaalde standaard waardes (text) en snel waardes zijn (label, placeholder, value) en je extra opties kan toevoegen indien je dit wel (type veranderen in password,date,email,etc, voor checkbox checked toevoegen)
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
<?php
$input
= new Input('name','Naam','Naam','Jan');
echo $input->getInput();

$input = new Input('email','E-mailadres','E-mailadres','[email protected]');
$input->addType('email');
echo $input->getInput();

$input = new Input('birthday','Geboortedatum');
$input->addType('date');
echo $input->getInput();

$input = new Input('pass','Wachtwoord','Wachtwoord','secret');
$input->addType('password');
echo $input->getInput();

$input = new Input('optie','Optie 1','','check optie 1');
$input->addType('checkbox');
$input->checked(TRUE);
echo $input->getInput();
?>
 
Donny Wie weet

Donny Wie weet

18/10/2013 12:29:51
Quote Anchor link
Ja zo heb ik het ook ongeveer gedaan. Heb alleen nog geen checkboxes en textareas en overige.

http://www.phphulp.nl/php/forum/topic/form-creator/92627/last/

Deze heb ik gemaakt
 
Michael -

Michael -

18/10/2013 13:19:47
Quote Anchor link
Donny Wie weet op 18/10/2013 12:29:51:
Ja zo heb ik het ook ongeveer gedaan. Heb alleen nog geen checkboxes en textareas en overige.

http://www.phphulp.nl/php/forum/topic/form-creator/92627/last/

Deze heb ik gemaakt

Jij bent dus ook OOP aan het leren. Jou 'form-creator' ook toegepast of alleen om te leren? Je zou jou script nog kunnen uitbreiden met verschillende types, en voor bepaalde types zoals date heb je weer andere attributen, en zo kan je er veel van leren. Ben benieuwd wat je er van maakt :-)
 
Stephan Dorst

Stephan Dorst

18/10/2013 13:28:22
Quote Anchor link
x
Gewijzigd op 18/10/2013 13:28:59 door Stephan Dorst
 
Donny Wie weet

Donny Wie weet

18/10/2013 15:53:13
Quote Anchor link
Michael - op 18/10/2013 13:19:47:
Donny Wie weet op 18/10/2013 12:29:51:
Ja zo heb ik het ook ongeveer gedaan. Heb alleen nog geen checkboxes en textareas en overige.

http://www.phphulp.nl/php/forum/topic/form-creator/92627/last/

Deze heb ik gemaakt

Jij bent dus ook OOP aan het leren. Jou 'form-creator' ook toegepast of alleen om te leren? Je zou jou script nog kunnen uitbreiden met verschillende types, en voor bepaalde types zoals date heb je weer andere attributen, en zo kan je er veel van leren. Ben benieuwd wat je er van maakt :-)



Voor mij is het om te leren. En als ie goed gekeurd is dan ga ik em ook gebruiken tenzij ik met een MVC werk, dan is het niet nodig
 
- Raoul -

- Raoul -

18/10/2013 21:01:52
Quote Anchor link
Inheritance is zééééér belangrijk voor je form elementen! Zoek die term eens op in de oop tutorial van phptuts.nl.
 
Reshad F

Reshad F

18/10/2013 21:46:51
Quote Anchor link
Hoezo is OO niet nodig wanneer je met MVC werkt? je weet dat MVC slechts een Design pattern is?
 
Local Dev

Local Dev

18/10/2013 22:56:55
Quote Anchor link
En het MVC pattern is oo :)
Gewijzigd op 18/10/2013 22:57:57 door Local Dev
 
Frank Nietbelangrijk

Frank Nietbelangrijk

19/10/2013 09:20:49
Quote Anchor link
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
<?php
class Form {
    public function __construct($fName){
        $this->fName = '<form method="POST" name="' . $fName . '">'.PHP_EOL;
    }

    
    public function getForm(){
        return $this->fName;
    }

    
    public function endForm(){
        return '</form>'.PHP_EOL;
    }
}

?>


Hartstikke mooi hoor zo een class en het ziet er verzorgd uit maar toch voor mij een cijfer vier. De reden? er is werkelijk niets flexibel aan deze class behalve de naam die je in de constructor meegeeft en zelfs die kun je later niet meer wijzigen.
De method kan ik niet opgeven of wijzigen en de action wordt al helemaal niet over gesproken.
Het renderen van de html doe je in mijn opzicht wanneer er om gevraagd wordt en niet in de constructor.
Ook zou ik de functies getForm wijzigen in startForm om de simpele reden een get.. functie daar verwacht ik een variabele uit terug en geen html.

Verder als dit heb ik het niet doorgelezen. genoeg Feedback denk ik.
Gewijzigd op 19/10/2013 09:34:13 door Frank Nietbelangrijk
 
Erwin H

Erwin H

19/10/2013 11:16:49
Quote Anchor link
Het begin is niet slecht, maar ik moet wel zeggen dat ik nog enigszins de echte 'OOP spirit' mis. Wat voor mij het belangrijke idee achter OOP is, is dat je een collectie aan classes krijgt die ieder hun eigen ding kunnen doen. Daarbij zijn ze zelfstandig en elke class zal dus zelf ervoor moeten zorgen dat de juiste output kan worden gegenereerd, zonder dat een andere class kennis nodig heeft van hoe iets gedaan wordt.
Als ik nu naar je form class kijk dan zie ik dat je twee methodes aanmaakt om het form te genereren 'getForm()' en 'endForm()'. Dat betekent dus dat de aanroepende class moet weten dat er een begin en eind is en dat de aanroepende class moet weten wanneer beide moeten worden aangeroepen. Dat vergt dus kennis in die aanroepende class die eigenlijk in je form class zou moeten. Vergeet de aanroepende class de tweede methode aan te roepen dan krijg je foutieve html, iets dat je nu juist simpel kan voorkomen als je in OOP werkt.

Als je kijkt naar html elementen dan zie in grove lijnen altijd de volgende structuur:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<opening tag - attributen>
  content
<sluit tag>

De attributen, content en sluit tag zijn optioneel, die kunnen dus leeg zijn.
Deze structuur kan je overnemen in je html classes door een soort boom te bouwen, waarbij je elke html tag als een node ziet die 1 ouder heeft en eventueel meerdere kinderen. Als je dan de html code wilt produceren shrijf je eerst de opening tag weg, dan de attributen, dan de content (de kinderen) en uiteindelijk de sluit tag. Door middel van een heel simpele interface kan je afdwingen dat elke html class in staat is om zich als een kind en als een ouder te gedragen in de boom.

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
<?php
interface Html_Tag_Interface{
  public function addChild( Html_Tag_Interface $child );
  public function writeTag();
}


class Form_Class implements Html_Tag_Interface{
  private $children = array();
  
  public function addChild( Html_Tag_Interface $child ) {
    $this->children[] = $child;
  }

  
  public function writeTag() {
    $str = '<form>';
    foreach( $this->children as $child ){
      $str .= $child->writeTag();
    }

    $str .= '</form>';
    
    return $str;
  }
}


class Input_Class implements Html_Tag_Interface{
  
  public function addChild( Html_Tag_Interface $child ) {
    //inputs hebben geen kids, geen actie dus
  }
  
  public function writeTag() {
    return '<input>';
  }
}


//je form bouwen en schrijven kan nu als volgt:
$form = new Form_Class();
$form->addChild( new Input_Class() );
echo $form->writeTag();
?>

In deze structuur kan je alle html tags hangen en je kan dus de hele boom (beginnende bij de html root tag zelf) met 1 echo naar het scherm schrijven.

Wat nog wel ontbreekt zijn de attributen. Als ik in beide scripts kijk (van TS en van Donny) dan zie ik hardcoded attributen. Dit is dus niet echt OOP, want het is niet flexibel. Ik kan in beide bijvoorbeeld geen class meegeven aan het form. Laat staan custom attributen.
Ten eerste wil je dus flexibeler zijn, ten tweede moet je je ook bedenken dat alle html tags attributen kunnen hebben (op een paar uitzonderingen na) en dat als je de attributen afhandeling dus in de classes zelf zet, dat je dan continu hetzelfde aan het doen bent. Dit schreeuwt dus om zijn eigen class:
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
<?php
class Attributes_Class{
  private $attributes = array();
  
  public function setAttribute( $key, $value ){
    $this->attributes[$key] = $value;
  }

  
  public function writeAttributes(){
    $str = '';
    foreach( $this->attributes as $key => $value ){
      $str .= ' '.$key.'="'.$value.'"';
    }

    return $str;
  }
}


//nieuw input class
class Input_Class implements Html_Tag_Interface{
  private $attributes;
  
  public function __construct( $type, $id, $name ){
    $this->attributes = new Attributes_Class();
    $this->attributes->setAttribute( 'type', $type );
    $this->attributes->setAttribute( 'id', $id );
    $this->attributes->setAttribute( 'name', $name );
  }

  
  public function addChild( Html_Tag_Interface $child ) {
    //inputs hebben geen kids, geen actie dus
  }
  
  public function writeTag() {
    return '<input'.$this->attributes->writeAttributes().'>';
  }
}


//form met 1 text input:
$form = new Form_Class();
$form->addChild( new Input_Class( 'text', 'edUsername', 'username' ) );
echo $form->writeTag();
?>

Uiteraard is dit een zeer eenvoudig implementatie, maar met deze structuur kan je het zo ver uitbouwen als je wilt.

Verder nog een paar kleine opmerkingen die wellicht kunnen helpen:
- ik zie in beide scripts dat er ofwel een PHP_EOL, ofwel een break tag achter de html gegeven wordt. Enerzijds is dat niet nodig, anderzijds ook niet gewensd. Het is niet aan een simpele class om te bepalen wat er aan output komt na de eigen output. Een class doet wat hij moet doen, maar je wil niet dat een class over zijn graf regeert en dus gaat bepalen wat er buiten de class gebeurt.
- ik zie ook dat je variabelen in je class gebruikt die je niet hebt gedefinieerd. Dat kan, maar is niet echt netjes. Dit maakt het zeer lastig om op een later moment nog te kunnen zien welke variabelen beschikbaar zijn in de class.
 
Michael -

Michael -

21/10/2013 08:13:58
Quote Anchor link
Ik reageer even algemeen op iedereen. Heel erg bedankt voor de goede en duidelijke feedback! Het klopt inderdaad dat het niet flexibel is en veel attributen dubbel zijn. Zelf vond ik dat 'endform' ook niet handig, maar wist dit nog niet anders te doen.
Ik ga met deze feedback aan de slag en zal later nog eens wat posten.

Toevoeging op 21/10/2013 10:40:00:

Zou iemand mij in jip en janneke taal kunnen uitleggen wat 'interface' nou doet?
Ik lees dat dit lijkt op abstract die een functie verplicht maakt, maar dit is toch niet wat interface doet? Of begrijp ik abstract nou ook verkeerd.

Terug komend op de reactie van Erwin heb ik nou het volgende script waarin ik de Interface (nog) niet gebruik. Wat is nou de meerwaarde van 'interface' zoals in het script van Erwin, terwijl het script hieronder vrijwel het zelfde is?

Wat is nou de 'goede' manier om je output te 'stylen'? Ik begrijp van de berichten hierboven dat je niet teveel HTML in je class/function wilt, want dan is het niet meer flexibel. Maar nou wil ik bijv achter de input text een break, maar achter een checkbox of radio weer niet. Doe ik dit dan in de class/function of bij de output?
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
<?php
interface Html_Tag_Interface{
}


class Form{
    private $children = Array();
    private $formAttributes = Array();
    
    function
__construct($method = null, $action = null){
        if(isset($method))
        {

            if(strtolower($method) == 'post' || strtolower($method) == 'get')
            {

                $this->formAttributes['method'] = $method;
            }

            else
            {
                throw new Exception('Method not allowed');
            }
        }

        if(isset($action)){
            $this->formAttributes['action'] = $action;
        }
        
    }

    
    public function addChild($child){
     $this->children[] = $child;
    }

    
    public function writeTag(){
        $str = '<form';
        
        if(isset($this->formAttributes))
        {

            foreach($this->formAttributes AS $key=>$value)
            {

                $str .= ' '. $key .'="'. $value .'"';
            }
        }

        
        $str .= '>';
        
        foreach($this->children AS $child)
        {

            $str .= $child->writeTag();
        }

        $str .= '</form>';
        
        return $str;
    }
}


class Attributes{
    
    private $attributes = Array();
    
    public function setAttribute($key,$value){
        $this->attributes[$key] = $value;
    }

    
    public function writeAttributes(){
        $str = '';
        foreach( $this->attributes AS $key=>$value )
        {

            $str .= ' '. $key .'="'. $value.'"';
        }

        return $str;
    }
}


class Input{

    private $attributes;
    private $allowedTypes = Array('text','password','submit','checkbox','radio','color','date','datetime','email','month','number','range','search','tel','time','url','week');
  
    public function __construct( $type, $id, $name ){
    
        if(!in_array(strtolower($type),$this->allowedTypes))
        {

            throw new Exception('Input Type not allowed');
        }

        $this->attributes = new Attributes;
        $this->attributes->setAttribute('type',$type);
        $this->attributes->setAttribute('id',$id);
        $this->attributes->setAttribute('name',$name);
    }

        
     public function writeTag() {
        return '<input'.$this->attributes->writeAttributes().' />';
    }
}


$form = new Form('post');
$form->addChild( new Input( 'text' , 'test' , 'blabla' ) );
$form->addChild( new Input( 'submit' , 'test' , 'blabla' ) );
echo $form->writeTag();
?>

Output:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<form method="post"><input type="text" id="test" name="blabla" /><input type="submit" id="test" name="blabla" /></form>


Edit:
Script geupdate met method en action en controle op type
Gewijzigd op 21/10/2013 11:48:50 door Michael -
 
Reshad F

Reshad F

21/10/2013 15:17:18
Quote Anchor link
Wil je echt goed OO code schrijven dan moet je een beetje weet hebben van DESIGN PATTERNS wat Erwin uit heeft gelegd is de Strategy Pattern.

http://nl.wikibooks.org/wiki/Programmeren_in_Java/Design_Patterns/Strategy_Pattern

Een interface kan je zien als een contract tussen jou en je programma. je interface zegt je moet deze methoden gebruiken en hoe jij die methodes invult dat zoek je zelf maar uit

vb ( code is gewoon van php.net geplukt )

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

interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}


?>


Je code zou dan ingevuld kunnen worden in een klasse die je aanmaakt waarvan deze de iTemplate implementeert

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
<?php

class Template implements iTemplate
{
    private $vars = array();
  
    public function setVariable($name, $var)
    {

        $this->vars[$name] = $var;
    }

  
    public function getHtml($template)
    {

        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }

 
        return $template;
    }
}


?>




Je programmeert hierbij naar een interface toe en niet naar een implementatie ( wat dus goed is en aanbevolen. )

Wil je nu bijvoorbeeld ook methoden verplicht maken maar wil je een methode voor elke klasse hetzelfde hebben dan maak je een abstracte klasse

vb ( van php.net )

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
<?php

abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // Common method
    public function printOut() {
        print $this->getValue() . "\n";
    }
}


?>


Zo zie je dat een abstracte klasse de methodes getValue() en prefixValue() als abstract declareerd en de printOut(); functie niet. tevens krijgt deze methode ook logica in zich.

dat wil zeggen als jij een klasse aanmaakt.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php
class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }


    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

?>


zie je dat je extends doet ( overerving ) inheritance in het engels.

Nu heeft deze klasse de twee abstracte methodes overgeërfd. Wat je niet ziet in de klasse is de methode printOut(). Heel simpel omdat deze door de parentklasse al ingevuld is.

Verder is het verschil dat je meerdere interfaces kan implementeren en maar 1 klasse kan extenden.

vb:

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

class a extends b implements c, d, e {

}


?>


Je kan dus niet doen


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

class a extends b, c, d implements e, f, g {

}


?>
Gewijzigd op 21/10/2013 15:19:13 door Reshad F
 
Erwin H

Erwin H

21/10/2013 16:47:02
Quote Anchor link
Reshad F op 21/10/2013 15:17:18:
Wil je echt goed OO code schrijven dan moet je een beetje weet hebben van DESIGN PATTERNS wat Erwin uit heeft gelegd is de Strategy Pattern.

http://nl.wikibooks.org/wiki/Programmeren_in_Java/Design_Patterns/Strategy_Pattern

Uh, nee, het is eerder het Composite pattern: http://en.wikipedia.org/wiki/Composite_pattern
Zeker geen strategy pattern, want in een strategy pattern laat je in feite een deel van de implementatie van een class afhangen van de implementatie van een ander (geinjecteerd) object. Dat is in dit geval niet aan de orde. Je zou met veel fantasie de attributen class een implementatie van het strategy pattern kunnen noemen, maar dat vind ik persoonlijk een beetje vergezocht. Die class heeft namelijk niet de intentie om uitgewisseld te kunnen worden (om te zorgen voor een andere implementatie), het is simpel bedoeld om algemene functionaliteit uit de html classes te halen.

Een interface is simpel gezegd een blauwdruk voor je class. De interface stelt van te voren vast wat een class moet kunnen. Hierdoor kan een andere class dus al weten wat bepaalde class doet en welke methodes in elk geval beschikbaar zijn.

Neem het voorbeeld van het form. De form class kan kinderen hebben die ook allemaal html moeten kunnen uitspugen. Maar wat voor html, hoe het eruitziet en hoe die kinderen dat doen maakt die form class geen moer uit. Als die de methode 'writeTag' maar kan aanroepen. Dat is in feite wat de interface afdwingt. Je ziet ook dat ik in de addChild methode als type hint de interface heb gezet. Dat betekent dat ik alleen een object mee kan geven van een class die die interface implementeert. Geef ik iets anders mee dan krijg ik een fatale foutmelding.

Met die structuur kan ik dus op elk moment een nieuwe class schrijven die de html interface implementeert. Mijn form class kan onveranderd blijven en toch al die nieuwe classes gebruiken als onderdeel van de html boom.

Wat betreft de extra breaks aan het einde van een object, dat moet je nooit willen doen. Het is namelijk niet aan een form of input object om te bepalen wat er na komt. Wat als je morgen toch een input wilt hebben in een text, zonder break? Dan kan je je class opeens niet meer gebruiken. Breaks zijn in feite gewoon hun eigen object. Eventueel kan je in je form class die breaks na een input wel zetten, omdat de form class wel kan bepalen wat er binnen de form tags komt, maar zelfs dan kan je nog in bovenstaande situatie komen.
Gewijzigd op 21/10/2013 16:48:53 door Erwin H
 
Reshad F

Reshad F

21/10/2013 16:51:22
Quote Anchor link
@Erwin je hebt helemaal gelijk :) ik heb je code niet goed bekeken.
 
Michael -

Michael -

22/10/2013 09:03:17
Quote Anchor link
Bedankt voor de uitleg! Ik ga mijn best doen om het allemaal te begrijpen.
Het is een hoop informatie die even de tijd nodig heeft.

Wat ik nog niet goed begrijp is het HTML gedeelte. Meerdere mensen vinden dat HTML niet in OOP hoort, maar in dit form-voorbeeld zou dat betekenen dat het grootste gedeelte buiten de OOP zou moeten plaats vinden en form misschien een slecht voorbeeld is.

Terugkomend op het script van Erwin heeft hij een functie writeTag() die alles in één keer output. Hierin kan ik dus buiten OOP geen HTML, zoals breaks, labels, aan toevoegen. Hoe lost men dit op?
 
Erwin H

Erwin H

22/10/2013 09:40:41
Quote Anchor link
Ik denk dat je HTML in OOP verwart met het niet direct echoen van HTML uit een functie. Uiteindelijk moet een php script ergens de HTML uitspugen dus je ontkomt er niet aan dat ergens de HTML opgebouwd moet worden. Uiteraard kan dat via includes (welke je ook vrij simpel in deze structuur in kan voegen), maar helemaal met includes lijkt me vrij lastig.
Wat veel mensen echter wel vinden is dat je vanuit een functie niet direct output naar de browser moet sturen en dat gebeurt hier ook niet. Geen van de classes echoen zelf, ze geven alleen maar de string terug die dan geechoed kan worden.

Wat betreft de OOP concepten (als interfaces, design patterns etc), maar je daar niet al te druk over. Dat kost tijd en je zal vast nog wel wat classes gaan schrijven voor je alles helemaal door hebt. Die tijd heeft iedereen nodig.

De writeTag methode is misschien wat misleidend. Die methode schrijft in principe zelf namelijk niets naar de browser en in feite zou ik dus geen 'write' moeten gebruiken in de naam. Daarmee zou je vraag ook al bijna beantwoord moeten zijn, want buiten de classes die in die writeTag methode de HTML opbouwen, kan je dus nog vanalles met die string doen, inclusief er iets aan hangen, bijvoorbeeld een break. Maar net als de labels die je noemt zijn dat ook gewoon HTML tags en ook die kan je dus gewoon als een object erin plakken:
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
class Label_Class implements Html_Tag_Interface{
  private $attributes;
  private $children;
  
  public function __construct( $for ){
    $this->attributes = new Attributes_Class();
    $this->attributes->setAttribute( 'for', $for );
  }

  
  public function addChild( Html_Tag_Interface $child ) {
    $this->children[] = $child;
  }

  
  public function writeTag() {
    $str = '<label'.$this->attributes->writeAttributes().'>';
    foreach( $children as $child ){
      $str .= $child;
    }

    $str .= '</label>';
    return $str;
  }
}


$form = new Form_Class();
$label = new Label_Class( 'edUsername' );
$label->addChild( new Input_Class( 'text', 'edUsername', 'username' ) );
$form->addChild( $label );
echo $form->writeTag();
?>

Etcetera, etcetera.

Maar nu wel even een waarschuwing, ga uiteindelijk niet voor elke tag een eigen class schrijven. Hoewel het kan, zal het niet verstandig zijn. Dan ga je namelijk honderden classes per pagina gebruiken en uiteindelijk is dat niet bevorderlijk voor de performance. Bovenstaande is het concept, maar in praktijk bouw ik classes die een heel deel van een pagina opmaken. Bijvoorbeeld een form class die uiteindelijk het hele form kan bouwen, inclusief de labels en inputs, maar ook nog willekeurig welk ander object kan meenemen als kind. Door die addChild methode kan alles erin gevoegd worden. Hetzelfde voor tabellen. Daarvoor heb ik een object dat extra methodes heeft om de headers door te geven, kolommen, rijen etc. In writeTag() zal die class dan de hele tabel opbouwen en er zijn dus geen aparte classes voor de row en cell tags.
Uiteindelijk kom je dan grotendeels wel weer terug bij de class waar je het topic mee begon, maar hopelijk wel met een wat andere implementatie.
Gewijzigd op 22/10/2013 09:41:58 door Erwin H
 
Reshad F

Reshad F

22/10/2013 09:42:50
Quote Anchor link
Je kan toch ook deze net als de input box meegeven?

dus weer een nieuwe class aanmaken

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

class Label_Class implements Html_Tag_Interface
?>
 

Pagina: 1 2 volgende »



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.