abonnement Unibet Coolblue Bitvavo
  Moderator / Redactie Sport / Devops vrijdag 21 februari 2014 @ 10:26:31 #91
176766 zoem
zoemt
pi_136965052
quote:
0s.gif Op donderdag 20 februari 2014 12:51 schreef slacker_nl het volgende:
Wat je hebt gedaan is goed.
Als je de code gepost door Sitethief bedoelt: die (constructor) is fout, maar hij heeft het daarna op de juiste manier gecorrigeerd. Het tussendoor opvangen van exceptions en het daarna gelijk rethrowen is natuurlijk onzinnig. Niet alleen vanwege het feit dat het overbodige code is, maar het kan ook de call stack trace beïnvloeden. Ik ben het dan ook geheel eens met Light over het gebruik van exceptions.
quote:
Wat ik vaak doe is dat ik ga kijken of de situatie goed is om iets te doen, meestal assert ik dan de opties en ga ik ook dood als het fout gaat.
Hoe vaak ben je al 'doodgegaan' als ik vragen mag? Ik vind het zo'n gekke bewoording :P
  vrijdag 21 februari 2014 @ 10:42:14 #92
187069 slacker_nl
Sicko pur sang
pi_136965489
quote:
14s.gif Op vrijdag 21 februari 2014 10:26 schreef zoem het volgende:

[..]

Als je de code gepost door Sitethief bedoelt: die (constructor) is fout, maar hij heeft het daarna op de juiste manier gecorrigeerd. Het tussendoor opvangen van exceptions en het daarna gelijk rethrowen is natuurlijk onzinnig. Niet alleen vanwege het feit dat het overbodige code is, maar het kan ook de call stack trace beïnvloeden. Ik ben het dan ook geheel eens met Light over het gebruik van exceptions.

[..]

Hoe vaak ben je al 'doodgegaan' als ik vragen mag? Ik vind het zo'n gekke bewoording :P
Ik ben al heel vaak doodgegaan. En m'n code nog meer!

En ik doelde op de correctie ja ;)

[ Bericht 5% gewijzigd door slacker_nl op 21-02-2014 10:54:21 ]
In theory there is no difference between theory and practice. In practice there is.
  vrijdag 21 februari 2014 @ 10:50:55 #93
187069 slacker_nl
Sicko pur sang
pi_136965739
quote:
0s.gif Op donderdag 20 februari 2014 23:04 schreef Light het volgende:

Dus als je bijvoorbeeld user input aan het controleren bent, moet je geen excepties gooien. Het is (in mijn ogen) verwacht gedrag dat die input niet voldoet aan de eisen die je eraan stelt.
Je frontend code moet dat goed afvangen, je backend code moet doodgaan op het moment dat de input incorrect is. Ipv Exceptions zou je ook nog trigger_error kunnen gebruiken.
In theory there is no difference between theory and practice. In practice there is.
  vrijdag 21 februari 2014 @ 10:53:57 #94
187069 slacker_nl
Sicko pur sang
pi_136965848
quote:
0s.gif Op donderdag 20 februari 2014 23:08 schreef Light het volgende:

[..]

Asserts hebben het nadeel dat ze uitgezet kunnen worden. Ik kan dus instellen dat ze bij mij niet afgaan, waardoor ik niet gewaarschuwd wordt voor ongeldige waardes. Om die reden vind ik asserts eigenlijk geen geschikte optie voor public API, en wel voor private en protected functies.
Dat is waar, maar ik maak asserts publiek, zodat als je ze wilt gebruiken het wel kan, en als je het niet doet, doe ik het alsnog voor je, alleen kan je vooraf al zien of een call zou gaan werken of niet. Het is een beetje defensief programeren.
In theory there is no difference between theory and practice. In practice there is.
pi_136970313
quote:
0s.gif Op vrijdag 21 februari 2014 10:53 schreef slacker_nl het volgende:

[..]

Dat is waar, maar ik maak asserts publiek, zodat als je ze wilt gebruiken het wel kan, en als je het niet doet, doe ik het alsnog voor je, alleen kan je vooraf al zien of een call zou gaan werken of niet. Het is een beetje defensief programeren.
Ik heb zelf dit in mijn code:
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
<?php
namespace System\Core;

use \
System\Core\Container;
use 
System\Core\Traits\ArrayAccessor;
use 
System\Core\Traits\ArrayIterate;

/**
 * Class Base
 * @package System\Core
 */
class Base implements \ArrayAccess, \Iterator {

    use 
ArrayAccessorArrayIterate;

    
/**
     * @param callable $closure
     */
    
public function __construct(\Closure $closure null) {
        if(
is_callable($closure)) {
            return 
$closure($this);
        }
        return 
$this;
    }

    
/**
     * @param Container\Settings $settings
     */
    
public function setSettings(Container\Settings $settings null) {
        if(
is_object($settings)) {
            foreach(
$settings as $k => $v) {
                
$this->{$k} = $v;
            }
        }
    }

    
/**
     * @param Container\Settings $settings
     */
    
public function setDependencies(Container\Settings $settings null) {
        
$this->setSettings($settings);
    }

    
/**
     * @param $name
     * @param array $args
     * @return bool
     */
    
public function __call($name, Array $args = []) {
        
$type substr($name03);
        
$var strtolower(substr($name3));
        switch(
$type) {
            case 
'set':
                
$this->$var $args[0];
            break;
            case 
'get':
                return isset(
$this->$var)?$this->var:false;
            break;
        }
    }
}

Elke class die dus base extend, heeft toegang tot automagische get en set calls.
Nu heb ik geen foutafhandeling er nog inzitten, meer omdat er niet echt wat fout kan gaan :P
pi_136975571
quote:
0s.gif Op vrijdag 21 februari 2014 10:50 schreef slacker_nl het volgende:

[..]

Je frontend code moet dat goed afvangen, je backend code moet doodgaan op het moment dat de input incorrect is. Ipv Exceptions zou je ook nog trigger_error kunnen gebruiken.
Ik heb ook code gezien die gebruikt werd om te bepalen of iets wel of niet geldig is en die een exceptie gooide in het geval de input niet geldig was. Als de input wel geldig was, werd gewoon netjes true teruggegeven.

Afhankelijk van de situatie kan het valide zijn om inputcontrole bij een setter te plaatsen, en dan een exceptie te gooien als de input niet geldig is. Je kunt er ook voor kiezen dat niet te doen en in de class een method validate() oid te implementeren die dan gewoon true of false teruggeeft afhankelijk van de waardes van de verschillende velden. En daar zijn ook combinaties van mogelijk.
pi_136976535
quote:
0s.gif Op vrijdag 21 februari 2014 15:06 schreef Light het volgende:

[..]

Ik heb ook code gezien die gebruikt werd om te bepalen of iets wel of niet geldig is en die een exceptie gooide in het geval de input niet geldig was. Als de input wel geldig was, werd gewoon netjes true teruggegeven.

Afhankelijk van de situatie kan het valide zijn om inputcontrole bij een setter te plaatsen, en dan een exceptie te gooien als de input niet geldig is. Je kunt er ook voor kiezen dat niet te doen en in de class een method validate() oid te implementeren die dan gewoon true of false teruggeeft afhankelijk van de waardes van de verschillende velden. En daar zijn ook combinaties van mogelijk.
Ja bij sommige frameworks zie je inderdaad een InvalidInputException o.i.d.

Wat ik zelf doe is de validatie op de validate() manier
Dit is bijvoorbeeld mijn logincontroller
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
<?php
namespace Controller;

use 
Model\User;
use 
System\Core\Controller;
use 
System\Core\Form\Element;
use 
System\Core\Form\Input;
use 
System\Helpers\Html;

/**
 * Class Login
 * @package Controller
 */
class Login extends Controller {
    public function 
index() {
        
$this->form->addElement(new Element\Fieldset([
            
'elements' => [
                new 
Input\Text([
                    
'name' => 'username',
                    
'required' => true,
                    
'baseValue' => 'Username',
                    
'validator' => ['Length' => ['min' => 3]]
                ]),
                new 
Input\Password([
                    
'name' => 'password',
                    
'baseValue' => 'Password',
                    
'validator' => ['Length' => ['min' => 5]]
                ]),
                new 
Element\Submit([
                    
'name' => 'login',
                    
'value' => 'Login'
                
])
            ]
        ]));
        if(
$this->request->isPost()) {
            if(
$this->form->validate()) {
                
$user User::find_by_username($this->request->post('username'));
                if(isset(
$user->id)) {
                    if(
password_verify($this->request->post('password'),$user->password)) {
                        
$_SESSION['user'] = ['id' => $user->id];
                        
$user->login_attempts 0;
                        
$this->url->redirect($this->url->createUrl());
                    } else {
                        
$user->login_attempts += 1;
                    }
                    
$user->save();
                }
            }
        }
        
$this->template->load('login', ['form' => $this->form]);
        echo 
$this->template;
    }

Form class:
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
<?php
namespace System\Core;

/**
 * Class Form
 * @package System\Core
 */
class Form extends Base {
    private 
$elements = array();

    public 
$method 'post';

    public 
$name '';

    public 
$valid true;

    public 
$enctype 'application/x-www-form-urlencoded';

    
/**
     * @param $element
     */
    
public function addElement($element) {
        
$this->elements[$element->name] = $element;
    }

    public function 
show() {
        foreach(
$this->elements as $e) {
            echo 
$e;
        }
    }

    
/**
     * @return bool
     */
    
public function validate() {
        foreach(
$this->elements as $e) {
            if(
false === $e->validate()){
                
$this->valid false;
            }
        }
        return 
$this->valid;
    }

    
/**
     * @return array
     */
    
public function __sleep() {
        return 
$this->elements;
    }

    
/**
     * @return string
     */
    
public function __toString() {
        
$output '<form method="' $this->method '" name="' $this->name '" enctype="'.$this->enctype.'">';
        foreach(
$this->elements as $e) {
            
$output .= $e;
        }
        
$output .= '</form>';
        return 
$output;
    }
}

Input class:
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
<?php
namespace System\Core\Form;

use \
System\Core;

use \
System\Core\Form\Validator;

/**
 * Class Input
 * @package System\Core\Form
 */
class Input extends Element {
    public 
$required false;
    public 
$baseValue '';
    public 
$checked false;
    public 
$validator;
    public 
$description;
    public 
$options = array();
    public 
$value '';
    public 
$min;
    public 
$max;
    public 
$step;
    public 
$validMessage '';
    public 
$valid;
    protected 
$settings;

    use 
Core\Traits\getObjVars;

    
/**
     * @param array $data
     */
    
public function __construct(array $data) {
        foreach(
$data as $k => $v) {
          
$this->$k $v;
        }

        if(
$this->request->isPost()) {
            if(
false !== $this->request->post($this->name)) {
                
$this->value $this->request->post($this->name);
            }
        }
    }

    
/**
     * @return string
     */
    
public function getClass() {
        return isset(
$this->class)?' class="'.$this->class.'"':'';
    }

    
/**
     * @return string
     */
    
public function getRequired() {
        return 
false === $this->required?'':' required aria-required="true"';
    }

    
/**
     * @return string
     */
    
public function getMinMaxStep() {
        return 
' min="'.$this->min.'" max="'.$this->max.'" step="'.$this->step.'" ';
    }

    
/**
     * @return string
     */
    
public function getValue() {
        return 
' value="'.$this->value.'"';
    }

    
/**
     * @return string
     */
    
public function getLabel() {
        return isset(
$this->label)?'<label for="'.$this->name.'">'.$this->label.'</label>':'';
    }

    
/**
     * @return string
     */
    
public function getDescribed() {
        return isset(
$this->description)?'aria-describedby="'.$this->name.'-format"':'';
    }

    
/**
     * @return string
     */
    
public function getDescription() {
        return isset(
$this->description)?'<span id="'.$this->name.'-format" class="help">'.$this->description.'</span>':'';
    }

    
/**
     * @param $value
     */
    
public function setValue($value) {
        
$this->value $value;
    }
}
pi_136993866
quote:
0s.gif Op vrijdag 21 februari 2014 15:27 schreef totalvamp het volgende:

[..]

Ja bij sommige frameworks zie je inderdaad een InvalidInputException o.i.d.

Wat ik zelf doe is de validatie op de validate() manier
Dit is bijvoorbeeld mijn logincontroller
[ code verwijderd ]

Form class:
[ code verwijderd ]

Input class:
[ code verwijderd ]

Ik zou in die Form class geen field $valid maken maar het resultaat gewoon binnen de functie houden. Verder kun je die validate() functie nog wat optimaliseren door te stoppen met valideren zodra je een element gevonden hebt dat niet valid is (maar dat kan uiteraard niet als validate() meer doet dan alleen valideren).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
    
/**
     * @return bool
     */
    
public function validate() {
        
$valid true;
        foreach(
$this->elements as $e) {
            if(
false === $e->validate()){
                
$valid false;
                break;
            }
        }
        return 
$valid;
    }
?>
pi_136996046
quote:
_O- _O- _O_
pi_137000915
quote:
0s.gif Op vrijdag 21 februari 2014 21:54 schreef Light het volgende:

[..]

Ik zou in die Form class geen field $valid maken maar het resultaat gewoon binnen de functie houden. Verder kun je die validate() functie nog wat optimaliseren door te stoppen met valideren zodra je een element gevonden hebt dat niet valid is (maar dat kan uiteraard niet als validate() meer doet dan alleen valideren).
[ code verwijderd ]

Dit is meer voor eventueel een extra optie zodat je later in de code ook kan kijken of je form geldig was.
Dit werkt niet lekker, aangezien je niet meerdere elementen een error mee kan geven dan.

Ik heb ook niet alle code laten zien aangezien alles op elkaar aansluit.

Het is een behoorlijk class heavy form class.

Als je hem volledig wilt zien (nog niet af)
http://sourceforge.net/p/totalfw/code/ci/master/tree/

[ Bericht 4% gewijzigd door #ANONIEM op 22-02-2014 00:24:25 ]
  zaterdag 22 februari 2014 @ 17:08:27 #101
187069 slacker_nl
Sicko pur sang
pi_137019271
quote:
0s.gif Op vrijdag 21 februari 2014 15:06 schreef Light het volgende:

[..]

Ik heb ook code gezien die gebruikt werd om te bepalen of iets wel of niet geldig is en die een exceptie gooide in het geval de input niet geldig was. Als de input wel geldig was, werd gewoon netjes true teruggegeven.

Afhankelijk van de situatie kan het valide zijn om inputcontrole bij een setter te plaatsen, en dan een exceptie te gooien als de input niet geldig is. Je kunt er ook voor kiezen dat niet te doen en in de class een method validate() oid te implementeren die dan gewoon true of false teruggeeft afhankelijk van de waardes van de verschillende velden. En daar zijn ook combinaties van mogelijk.
In Perl, mijn dagelijkse brood, heb je Moose en verschillende parameter check modules, Params::Check, Params::Validate en Data::FormValidator. Bij Moose kan je gewoon zeggen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package My::Fok;

use Moose;

has 'fok' => (
  is => 'rw',
  isa => 'Int', # Str, ArrayRef, etc etc 'Class::Name' 
  required => 0,
  default => sub { return 1},
);

1;

## Elders in je code base
use My::Fok;
my $fok = My::Fok->new(fok => 100);

En dan kan het alleen van dat type zijn.

Params::Check en consorten kan je gebruiken voor functies. Dat maakt een heel hoop code, die bij sommige hier zo verweven zit in je code overbodig.

Dan krijg je zulke dingen:

1
2
3
4
5
6
sub my_func {
    my $args = check({foo => { required => 1, isa => "My::Fok" }}, {@_});
}

my $fok = My::Fok->new(fok => 100);
my_func(foo => $fok);

Als je iets anders erin stopt gaat de validator mekkeren en ga je dood of niet. En dat is zo handig! Zo kan je heel fine grained bepalen of input voldoet aan de eisen die je stelt en anders: b0rk.
In theory there is no difference between theory and practice. In practice there is.
pi_137092426
quote:
0s.gif Op zaterdag 22 februari 2014 17:08 schreef slacker_nl het volgende:

[..]

In Perl, mijn dagelijkse brood, heb je Moose en verschillende parameter check modules,
Werk je toevallig bij Booking.com dat je nog in Perl werkt ;) ?
🕰️₿🕰️₿🕰️₿🕰️₿🕰️₿🕰️ TikTok next Block
  maandag 24 februari 2014 @ 16:14:45 #103
187069 slacker_nl
Sicko pur sang
pi_137093995
quote:
0s.gif Op maandag 24 februari 2014 15:30 schreef raptorix het volgende:

[..]

Werk je toevallig bij Booking.com dat je nog in Perl werkt ;) ?
Nope.
In theory there is no difference between theory and practice. In practice there is.
pi_137210185
Hoe werken functions in PHP? Ik gebruik een los PHP bestand om data in een database te manipuleren maar ik kan daarbij geen gebruik maken van functions. Bijvoorbeeld onderstaande code werkt niet, maar als ik dezelfde mysqli_query buiten de function zet werkt het prima. Werkt een php functie alleen als er een echo of return in zit?

test();

function test(){
mysqli_query(blalba);
}
  Moderator / Redactie Sport / Devops donderdag 27 februari 2014 @ 19:34:57 #105
176766 zoem
zoemt
pi_137210501
De functies zullen eerst gedeclareerd moeten worden alvorens ze aangeroepen kunnen worden. In je voorbeeld moet de call naar test() dus onder de include staan. Dat is hoe php werkt.

[ Bericht 3% gewijzigd door zoem op 27-02-2014 21:33:12 ]
pi_137217114
quote:
0s.gif Op donderdag 27 februari 2014 19:34 schreef zoem het volgende:
De functies zullen eerst gedeclareerd moeten worden alvorens ze aangeroepen kunnen worden. In je voorbeeld moet de call naar test() er dus onder staan. Dat is hoe php werkt.
Nee, dat is niet hoe php werkt. Je kunt prima een functie aanroepen en daarna declareren. Je kunt ook twee functies maken die elkaar aanroepen zonder dat je daar spannende extra dingen voor hoeft te doen.
pi_137217353
quote:
0s.gif Op donderdag 27 februari 2014 19:28 schreef terdege het volgende:
Hoe werken functions in PHP? Ik gebruik een los PHP bestand om data in een database te manipuleren maar ik kan daarbij geen gebruik maken van functions. Bijvoorbeeld onderstaande code werkt niet, maar als ik dezelfde mysqli_query buiten de function zet werkt het prima. Werkt een php functie alleen als er een echo of return in zit?

test();

function test(){
mysqli_query(blalba);
}
Dat zou gewoon moeten werken. Maar het is wat lastig om je te helpen zolang niet duidelijk is wat er gebeurt als je de code in functies hebt staan.

Tip: plaats php code tussen [php] en [/php] voor leuke kleurtjes en regelnummers enzo.
  Moderator / Redactie Sport / Devops donderdag 27 februari 2014 @ 21:34:42 #108
176766 zoem
zoemt
pi_137217441
quote:
0s.gif Op donderdag 27 februari 2014 21:29 schreef Light het volgende:

[..]

Nee, dat is niet hoe php werkt. Je kunt prima een functie aanroepen en daarna declareren. Je kunt ook twee functies maken die elkaar aanroepen zonder dat je daar spannende extra dingen voor hoeft te doen.
Dat werkt alleen als het binnen hetzelfde bestand staat. Hij heeft een losse file met functies die waarschijnlijk later pas geinclude wordt. En dan gaat je verhaal niet op. Heb even m'n reactie aangepast zodat het duidelijker is.
pi_137217888
quote:
0s.gif Op donderdag 27 februari 2014 21:34 schreef zoem het volgende:

[..]

Dat werkt alleen als het binnen hetzelfde bestand staat. Hij heeft een losse file met functies die waarschijnlijk later pas geinclude wordt. En dan gaat je verhaal niet op. Heb even m'n reactie aangepast zodat het duidelijker is.
Ja ok :) Je moet een file eerst includen voordat je de code daarin kunt aanspreken.
pi_137218347
quote:
0s.gif Op donderdag 27 februari 2014 21:42 schreef Light het volgende:

[..]

Ja ok :) Je moet een file eerst includen voordat je de code daarin kunt aanspreken.
Wat een stom principe zeg
In theory there is no difference between theory and practice. In practice there is.
pi_137218689
quote:
10s.gif Op donderdag 27 februari 2014 21:50 schreef slacker_nl het volgende:
Wat een stom principe zeg
Autoloaders _O_

[ Bericht 7% gewijzigd door #ANONIEM op 27-02-2014 21:57:47 ]
pi_137218961
quote:
Die werken voor classes, niet voor bestanden met losse functies.
pi_137219162
quote:
0s.gif Op donderdag 27 februari 2014 22:00 schreef Light het volgende:

[..]

Die werken voor classes, niet voor bestanden met losse functies.
Welke dinosaurus werkt er dan ook nog zonder classes :')

[ Bericht 7% gewijzigd door #ANONIEM op 27-02-2014 22:05:12 ]
pi_137220197
quote:
1s.gif Op donderdag 27 februari 2014 22:04 schreef CrashO het volgende:

[..]

Welke dinosaurus werkt er dan ook nog zonder classes :')
Terdege misschien?
pi_137220426
Dan zijn wij hier om hem te vertellen. Get to class(es) :+

[ Bericht 0% gewijzigd door #ANONIEM op 27-02-2014 22:26:11 ]
pi_137221390
quote:
1s.gif Op donderdag 27 februari 2014 22:04 schreef CrashO het volgende:

[..]

Welke dinosaurus werkt er dan ook nog zonder classes :')
niet alles hoeft OO te zijn he
In theory there is no difference between theory and practice. In practice there is.
  vrijdag 28 februari 2014 @ 09:15:38 #117
25889 Sitethief
Fulltime Flapdrol
pi_137229471
quote:
1s.gif Op donderdag 27 februari 2014 22:04 schreef CrashO het volgende:

[..]

Welke dinosaurus werkt er dan ook nog zonder classes :')
Niet alle functies wil je in een class hebben.
Stroek: Sitethief, die is heel groot en sterk :Y.
Faat: *zucht* zoals gewoonlijk hoor Sitethief weer in de bocht &gt;:)
pi_137232663
quote:
0s.gif Op vrijdag 28 februari 2014 09:15 schreef Sitethief het volgende:

[..]

Niet alle functies wil je in een class hebben.
Behalve de autoload functie, over wat voor functies heb jij het?
  vrijdag 28 februari 2014 @ 11:38:17 #119
187069 slacker_nl
Sicko pur sang
pi_137233006
quote:
1s.gif Op vrijdag 28 februari 2014 11:26 schreef totalvamp het volgende:

[..]

Behalve de autoload functie, over wat voor functies heb jij het?
Een bunch aan helper functies? Waarom zou je dat in een class willen frotten?
In theory there is no difference between theory and practice. In practice there is.
pi_137233499
quote:
0s.gif Op vrijdag 28 februari 2014 11:38 schreef slacker_nl het volgende:

[..]

Een bunch aan helper functies? Waarom zou je dat in een class willen frotten?
Zodat je alle die functies op 1 centrale overzichtelijke plek hebt.
Daarnaast heb je verschillende soorten helpers, miss wil je het wel opdelen.

Html helpers
Url helpers
Helper helpers
Parse helpers

Met classes blijf je overzichtelijk en is het duidelijk waar een functie vandaan komt.

En je kunt functienamen normaal houden, zodat je niet met dezelfde functienamen eindigt voor verschillende dingen.
abonnement Unibet Coolblue Bitvavo
Forum Opties
Forumhop:
Hop naar:
(afkorting, bv 'KLB')