Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 17-May-2012
< Voriger Tag   Nächster Tag >

Donnerstag, 17. Mai 2012

PHP: HTML-Formular -- Felder und Regeln teilen

User- und Form-Modell sind sich ähnlich. Um die Wiederholung von Programmcode zu vermeiden sollen sie sich gemeinsame Felder und Regeln teilen und diese um eigene Felder erweitern.

User- und Form-Modell:

  • Teilen sich gleiche Felder mit demselben Inhalt
  • Besitzen gleichnamige Felder mit unterschiedlichen Inhalt
  • Besitzen Felder unabhängig voneinander
User-Modell       Form-Modell
------------------------------------
id
login             login
password // hash  password // raw
                  passwordRepeat
salt
favLanguages      favLanguages
isComputerfreak   isComputerfreak
comment           comment
lastLogin
                  preview
                  register
                  PHPSESSION

DRY - Don't repeat yourself

Gleiche Felder mit gleichen Inhalt sollten nur einmal deklariert werden und dann von beiden Modellen benutzt werden.

  • Gemeinsame Felder an zentralen Ort deklarieren
    • Ohne gleichnamige Felder mit unterschiedlichen Inhalt
    • Mit gleichnamigen Feldern mit unterschiedlichen Inhalt
  • Gemeinsame Felder übernehmen
  • Gemeinsame Felder mit unterschiedlichen Inhalt überschreiben
  • Gemeinsame Felder mit unterschiedlichen Inhalt modifizieren
  • Eigene Felder hinzufügen

Zentral

In oop_share sind die gemeinsamen Felder an einer Stelle deklariert. User- und Form-Modell übernehmen diese Felder, fügen die eigenen hinzu und überschreiben die gleichnamige Felder mit unterschiedlichen Inhalten.

Nachteil: Im Quelltext ist nur schwer erkennbar welche Felder für eine Klasse deklariert sind, insbesonders für das User-Modell ist dies vom Nachteil.

$userShare = [
//   Field              Name              Value
// ------------------------------------------------------
    ['Text',            'login',          '',
        ['displayName' => 'Login', 'size'  => 10],            // Options
        ['maxLength'   => 8,       'match' => '/^[a-z]+$/']], // Rules

    ['Password',        'password',       '',
        ['displayName' => 'Password', 'size'        => 10],
        ['minLength'   => 8]],

    ['Select',         'favLanguages',    [],
        ['displayName'     => 'Favourite languages', 'options' => $favLanguages, 'size' => 5, 'multiple' => true],
        ['sanitizeOptions' => $favLanguages]],


    ['Textarea',       'comment',         '',
        ['displayName'      => 'Comment', 'rows' => 5, 'cols' => 40],
        ['convertEndOfLine' => "n"]]
];


// Classes
class UserModel extends BaseModel {
    public function __construct() {
        parent::__construct($GLOBALS['userShare'], [
            ['Integer',        'id',              '',
                [],
                ['minValue'    => 1, 'maxValue' => 1000]],

            ['Password',       'password',        '',  // Overwrites password
                ['overwrite' => true],
                ['length'    => 32, 'match' => '/^[a-z0-9]{32}$/']],

            ['Bool',           'isComputerfreak', true,
                ['displayName' => 'Computerfreak'],
                ['bool' => [true, false]]]
        ]);
    }//__construct

User-Modell stellt Felder zur Verfügung

In oop_share_provide_fields deklariert das User-Modell alle eigenen Felder und stellt die gemeinsamen dem Form-Modell zur Verfügung.

Vorteil: Gemeinsame Felder sind nur einmal deklariert. Für die User-Klasse ist leicht ersichtlicht welche Felder sie besitzt. Änderungen am User-Modell werden automatisch ans Form-Modell weitergegeben.

Nachteil: Für das Form-Modell ist nicht direkt im Quelltext erkennbar welche Felder es besitzt.

class UserModel extends BaseModel {
    public function __construct() {
        parent::__construct([
          // Field             Name               Value
          // ------------------------------------------------------
            ['Integer',        'id',              '',
                [],                                         // Options
                ['minValue'    => 1, 'maxValue' => 1000]],  // Rules

            ['Text',            'login',          '',
                ['displayName' => 'Login', 'size'  => 10],
                ['maxLength'   => 8,       'match' => '/^[a-z]+$/']],
[...]

    /**
     * Provide fields for other Classes
     */
    public function getFields($for) {
        switch($for) {
            case 'form':
                return [clone $this->fields['login'],
                        clone $this->fields['favLanguages'],
                        clone $this->fields['comment'],
                       ];
                break;
$form = new FormModel('index.php', 'post', $user, [
    ['Password',        'password',       '',
        ['overwrite'   => true,
         'displayName' => 'Password', 'size'        => 10],
        ['minLength'   => 8,          'isEqualWith' => 'passwordRepeat']],

    ['Password' ,      'passwordRepeat',  '',
        ['displayName' => 'Password repeat', 'size' => 10],
        []],
[...]

Form-Modell holt sich Felder

In oop_share_get_fields deklariert das User-Modell wieder alle eigenen Felder. Das Form-Modell holt sich nun aber die gemeinsamen Felder selbst vom User-Modell und ergänzt die eigenen.

Vorteil: Gemeinsame Felder sind nur einmal deklariert und es ist für beide Klassen leicht im Quelltext sichtbar welche Felder sie besitzen.

Nachteil: Wenn beim User-Modell Felder hinzugefügt, entfernt oder verändert werden muss das Form-Modell von Hand ans User-Modell angepaßt werden.

class UserModel extends BaseModel {
    public function __construct() {
        parent::__construct([
          // Field             Name               Value
          // ------------------------------------------------------
            ['Integer',        'id',              '',
                [],                                         // Options
                ['minValue'    => 1, 'maxValue' => 1000]],  // Rules

            ['Text',            'login',          '',
                ['displayName' => 'Login', 'size'  => 10],
                ['maxLength'   => 8,       'match' => '/^[a-z]+$/']],

            ['Password',       'password',        '',
                [],
                ['length'    => 32, 'match' => '/^[a-z0-9]{32}$/']],

[...]
$form = new FormModel('index.php', 'post', $user, [
    // ['login', $user],
    [BaseModel::getFieldFrom('login', $user)],

    ['Password',        'password',       '',
        ['overwrite'   => true,
         'displayName' => 'Password', 'size'        => 10],
        ['minLength'   => 8,          'isEqualWith' => 'passwordRepeat']],

    ['Password' ,      'passwordRepeat',  '',
        ['displayName' => 'Password repeat', 'size' => 10],
        []],

    [BaseModel::getFieldFrom('favLanguages', $user)],

[...]

Felder von zentraler Stelle holen

In einer nicht implementierten Variante könnten sich sowohl das User- als auch Form-Modell die Felder von einer zentralen Stelle holen.

Vorteil: Eine Reihe von Klassen können sich verschiedene Felder in beliebiger Kombination teilen.

Nachteil: Abhängige Änderungen müssen in allen Klassen von Hand nachgeführt werden.

class UserModel extends BaseModel {
    public function __construct() {
        parent::__construct([
          // Field             Name               Value
          // ------------------------------------------------------
            ['Integer',        'id',              '',
                [],                                         // Options
                ['minValue'    => 1, 'maxValue' => 1000]],  // Rules

            ['login'],

            ['Password',       'password',        '',
                [],
                ['length'    => 32, 'match' => '/^[a-z0-9]{32}$/']],

            ['favLanguages'],

            [...]

            ['comment'],
[...]

Form-Modell holt und setzt Werte mit einem Accessor

oop_share_accessor ist eine Erweiterung von oop_share_provide_fields in der das User-Modell zusätzlich jeweils einen Accessor zum Lesen und Setzen der Werte bereitstellt. Das Form-Modell kann nun selbst aktiv die Werte aus dem User-Modell holen und setzen.

Der Accessor schränkt dazu den Zugriff auf die Properties des Modells ein und übernimmt auch die Konvertierung der Werte, so dass das Passwort im User-Modell als MD5-Hash und nicht im Klartext gespeichert wird.

class UserModel extends BaseModel {
    private $accessors = [];


    public function __construct() {
        [...]

        $this->accessors['form_register_read']  = new Accessor($this,
                                                               ['login', 'favLanguages', 'isComputerfreak', 'comment'], // read
                                                               []);                                              // write
        $this->accessors['form_register_write'] = new FormRegisterAccessor($this,
                                                               [],
                                                               ['login', 'password', 'favLanguages', 'isComputerfreak', 'comment']);
                                                               //['login', 'password' => function($value) {return md5($value);}, 'favLanguages', 'comment']);
    }//__construct
class FormModel extends BaseModel {
    private $action  = '';
    private $method  = 'get';
    private $model   = null;

    [...]

    public function process() {
        // Get values from model
        $model = $this->model->getAccessor('form_register_read');
        foreach($model as $key => $value) {
            $this->$key = $value;
        }

        [...]

        $this->processRules();

        // Set values in model
        if($this->isValid) {
            $model = $this->model->getAccessor('form_register_write');
            foreach($model as $key => $value) {
                $model->$key = $this->$key;
            }
        }
    }// process
class FormRegisterAccessor extends Accessor {
    public function __construct($obj, $read = [], $write = [], $readwrite = []) {
        parent::__construct($obj, $read, $write, $readwrite);
    }// __construct


    public function __set($name, $value) {
        switch($name) {
            case 'password';
                $value = md5($value);
                break;

            default:
                break;
        }

        parent::__set($name, $value);
    }// __set
}// FormRegisterAccessor

user- und devErrors[]

Statt errros[] gibt es nun userErrors[] und devErrors[]. Dadurch können die Fehlermeldungen für Entwickler den field- statt displayName und zusätzliche Informationen enthalten.

CheckboxField nur true und false

Das CheckboxField ist so geändert, dass es nur noch true und false als Wert haben kann. Dadurch kann der Wert ohne Konvertierung auf das BoolField des User-Modells abgebildet werden.

[Direktlink]

< Voriger Tag   Nächster Tag >

  RSS V0.91

<Mai 2012 >
 010203040506
07080910111213
14151617181920
21222324252627
28293031   

Home-Produkte-Testarea-Kontakt-Datenschutz-Aktualisiert: 17-May-2012
(C) 2000-2018 by Sven Drieling