Minimales Modul

Das Forum soll der Ablage von Lösungen für immer wieder auftauchende Problemstellungen dienen. // This forum contains solutions to problems that frequently occur.
Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 15.08.2008, 13:19:20

Hallo Doc,

ich habe mir mal den Quellcode aus Tools/validator/Myvalidator.php angesehen. Wenn man in Zeile 208 die
php Funktion is_numeric() verwenden würde, dann würde er auch reale Zahlen erkennen.

Es gibt ja auch is_float is_int etc.

Viele Grüße und ein schönes Wochenende
Michl

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 15.08.2008, 13:33:23

Hallo fliegermichl,
Hmm, wenn ich die <form:placeholder> aus dem Template durch <form:genericval> ersetze, werden die Eingabefelder nicht mehr rot. Aber auch dann nicht, wenn der Anwender was falsches eingegeben hat.
Das ist korrekt, denn der <formgenericval />-Tag validiert zwar den Wert eines Elements, greift auf dieses jedoch nicht zu und verändert dieses nicht. Es führt lediglich die Aktion des Tags selbst (=Ausgabe des Tag-Inhalts) aus. Wenn du beides möchtest, kannst du auch beides einsetzen.
Kann ich innerhalb von transformContent auf die Fehlertexte zugreifen um z.B. die Fehlermeldung anzupassen wenn
der Anwender versucht durch Null zu teilen?
Ja. Da der Text erst bei der Transformierung ausgegeben wird, kannst du im Controller per

Code: Alles auswählen

$Form = &$this->__getForm('MyForm');
$GenericVal = &$Form->getFormElementByID('operand1val');
$GenericVal->set('Content','...');
den Inhalt des Validators manipulieren. Wichtig dabei ist, dass der Text nur dann auch per Controller manipuliert wird, wenn er ausgegeben werden soll. Der genericval-Tag prüft (im Moment) nämlich beim Transformieren nicht mehr, ob die Ausgabe auch erzeugt werden soll. Im Klartext: du musst im Controller wissen, ob der Validator anspringen soll.
Der Validator "Number" läßt nur die Eingabe ganzer positiver Zahlen zu. Gibt es auch einen für reale Zahlen?
Du hast Recht, da hatte ich deinen letzten Post überlesen. Siehe hierzu mein nächster Post...

Ich hab mir auch nochmal die Implementierung des <form:genericval />-Tags angesehen und werde folgendes im nächsten Release einbauen:
  • <form:genericval />-Tag erhält die Möglichkeit per beliebigem regulären Ausdruck zu validieren.
  • Der Tag speichert die in der Methode onAfterAppend() erlangte Information über die Gültigkeit des Wertes in einer Variablen. Damit kann der Inhalt per set('Content','...') immer manipuliert werden (z.B. um sprachabhängige Texte einzupflegen).
Damit sollte diese Hürde lösbar sein.

Ein schönes Wochenende!
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 15.08.2008, 16:51:10

Hallo fliegermichl,

sorry, das hatte ich ganz überlesen:
ich habe mir mal den Quellcode aus Tools/validator/Myvalidator.php angesehen. Wenn man in Zeile 208 die
php Funktion is_numeric() verwenden würde, dann würde er auch reale Zahlen erkennen.
Habe ich so eingepflegt. Die geänderten Dateien kannst du per SVN (Revision 17) aus dem trunk auschecken.
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Minimales Modul

Beitrag von MrNiceGuy » 11.05.2009, 12:52:35

Ersteinmal: Danke für dieses gute Tutorial, das hilft mir enorm weiter und ich werde auch so schnell es geht versuchen ein Modul für die Sprach-Weiche zu erstellen, das dann universell einsetzbar sein wird. Im entsprechenden Thread werde ich dann mein Ergebnis präsentieren :)

Aber ein paar Fragen habe ich doch noch:
dr.e. hat geschrieben:[...]
Kann ich innerhalb von transformContent auf die Fehlertexte zugreifen um z.B. die Fehlermeldung anzupassen wenn
der Anwender versucht durch Null zu teilen?
Ja. Da der Text erst bei der Transformierung ausgegeben wird, kannst du im Controller per

Code: Alles auswählen

$Form = &$this->__getForm('MyForm');
$GenericVal = &$Form->getFormElementByID('operand1val');
$GenericVal->set('Content','...');
den Inhalt des Validators manipulieren. Wichtig dabei ist, dass der Text nur dann auch per Controller manipuliert wird, wenn er ausgegeben werden soll. Der genericval-Tag prüft (im Moment) nämlich beim Transformieren nicht mehr, ob die Ausgabe auch erzeugt werden soll. Im Klartext: du musst im Controller wissen, ob der Validator anspringen soll.
Bedeutet das, dass der Text - so er denn per set() gesetzt wurde - immer ausgegeben wurde, selbst wenn die Prüfung eigentlich nicht dafür gesorgt hätte? Und das ist jetzt behoben? Ich kann also den Inhalt des form:genericval manipulieren und die Prüfung ist davon nicht beeinflusst?

Außerdem ist mir beim Testen aufgefallen, dass die Berechnung nur mit Ganzzahlen getätigt wurde. Durch das Ändern von (int) auf (float) an den entsprechenden Stelle im Controller konnte dieses "Problem" zwar behoben werden, aber bei der Eingabe von Kommazahlen besteht weiterhin das Problem, dass ich sie in englischer Form eingeben muss ("." statt ","). Gibt es eine Möglichkeit, dies zu manipulieren? Wenn man mal ein Formular braucht, bei dem die Benutzer Kommazahlen eingeben müssen möchte ich sie nicht zwingen den Punkt zu benutzen, das macht die Verwendung des Num-Blocks nämlich fast zu Nichte...

Mittels PHP-Bordmitteln kann man zwar mit "set_locale(LC_ALL, 'de_DE@euro', 'de_DE', 'de', 'ge')" von:

Code: Alles auswählen

Array
(
    [decimal_point] => .
    [thousands_sep] => 
    [int_curr_symbol] => 
    [currency_symbol] => 
    [mon_decimal_point] => 
    [mon_thousands_sep] => 
    [positive_sign] => 
    [negative_sign] => 
    [int_frac_digits] => 127
    [frac_digits] => 127
    [p_cs_precedes] => 127
    [p_sep_by_space] => 127
    [n_cs_precedes] => 127
    [n_sep_by_space] => 127
    [p_sign_posn] => 127
    [n_sign_posn] => 127
    [grouping] => Array
        (
        )

    [mon_grouping] => Array
        (
        )

)
("localeconv();") auf:

Code: Alles auswählen

Array
(
    [decimal_point] => ,
    [thousands_sep] => .
    [int_curr_symbol] => EUR
    [currency_symbol] => €
    [mon_decimal_point] => ,
    [mon_thousands_sep] => .
    [positive_sign] => 
    [negative_sign] => -
    [int_frac_digits] => 2
    [frac_digits] => 2
    [p_cs_precedes] => 0
    [p_sep_by_space] => 1
    [n_cs_precedes] => 0
    [n_sep_by_space] => 1
    [p_sign_posn] => 1
    [n_sign_posn] => 1
    [grouping] => Array
        (
            [0] => 3
        )

    [mon_grouping] => Array
        (
            [0] => 3
        )

)
kommen, jedoch hat das leider keinen Einfluss auf die Berechnungen bzw. die per POST übergebenen Zahlen-Werte!?
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 11.05.2009, 23:16:36

Hallo Lutz,
Bedeutet das, dass der Text - so er denn per set() gesetzt wurde - immer ausgegeben wurde, selbst wenn die Prüfung eigentlich nicht dafür gesorgt hätte? Und das ist jetzt behoben? Ich kann also den Inhalt des form:genericval manipulieren und die Prüfung ist davon nicht beeinflusst?
Den Inhalt des
<form:genericval />
-Tags kannst du in einem Controller beliebig manipulieren. Erst bei der Transformation wird entschieden, ob der von dir gesetzte Inhalt auch ausgegeben wird. In der onAfterAppend()-Methode der Klasse form_taglib_genericval wird lediglich geprüft, ob das zu validierende Form-Objekt valide ist oder nicht.
Außerdem ist mir beim Testen aufgefallen, dass die Berechnung nur mit Ganzzahlen getätigt wurde. Durch das Ändern von (int) auf (float) an den entsprechenden Stelle im Controller konnte dieses "Problem" zwar behoben werden, aber bei der Eingabe von Kommazahlen besteht weiterhin das Problem, dass ich sie in englischer Form eingeben muss ("." statt ","). Gibt es eine Möglichkeit, dies zu manipulieren? Wenn man mal ein Formular braucht, bei dem die Benutzer Kommazahlen eingeben müssen möchte ich sie nicht zwingen den Punkt zu benutzen, das macht die Verwendung des Num-Blocks nämlich fast zu Nichte...
In der aktuellen Implementierung ist das leider nur durch einen eigenen Validator oder eigene Validierungslogik im Controller möglich, die Klasse myValidator unterstützt das nicht. In der Version 1.10 ist jedoch das Refactoring der Validierung der Form-TagLibs angesagt. Zukünftig wirst du dann die Möglichkeit haben sehr einfach eigene Validatoren einzuhängen, die ein Feld auf deine aktuell benötigte Syntax prüfen.
[..] jedoch hat das leider keinen Einfluss auf die Berechnungen bzw. die per POST übergebenen Zahlen-Werte!?
Das APF ist an dieser Stelle eigentlich transparent und kennt keinen LOCALES. Wo genau geht denn die Berechnung schief?

Viele Grüße,
Christian
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Minimales Modul

Beitrag von MrNiceGuy » 12.05.2009, 07:24:04

Das Problem ist weniger die Validierung, da diese ja egal ob bei "5.4" oder "5,4" korrekt ist (PHP interpretiert "Strings" mit einer Zahl am Anfang automatisch als Zahl, wenn danach "gefragt" wird wie z.B. bei is_numeric() - so meine ich mich jedenfalls zu erinnern). Das Problem besteht eigentlich erst dann, wenn man versucht mit den Variablen zu arbeiten. Zum Einen musste ich halt das "(int)" in "(float)" ändern, damit nicht ohnehin schon der Nachkomma-Teil abgetrennt wird, zum Anderen besteht aber trotzdem das Problem, dass PHP - egal, ob die Locales geändert wurden oder nicht - mit dem Komma nichts anfangen kann und einen Punkt als Trenner haben will... Es wäre super, wenn es dafür einen Fix gäbe, um nicht jedes Mal selber die Manipulation der Zahlenwerte ändern müsste, bevor diese für Berechnungen verwendet werden. Ich meine: Klar kann ich das in der bootstrap oder sonstwo selber einbauen, nur wäre es schon im FW drin, gäbe das von mir nochmal einen Punkt als Kompatibilitätsbonus ;)
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 12.05.2009, 12:35:14

Hallo Lutz,

kannst du mit deinem Code mal einen proof-of-concept erstellen und hier posten? Ich bin immer noch nicht ganz sicher, so PHP da Schmerzen hat. Vielen Dank!

Christian
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Minimales Modul

Beitrag von MrNiceGuy » 12.05.2009, 13:01:04

Ich denke mal, dass du damit ein Beispiel-Script zum Ausprobieren meinst!?

http://scheiss-spam.de/testCalc.php

Da kannst du mal versuchen Kommazahlen mit einem normalen Komma einzutragen und danach kannst du das mal mit einem Punkt versuchen. Egal ob mit oder ohne setlocale(), das Ergebnis ist leider immer gleich. Allerdings kannst du anhand des "hardcoded"-Beispiels sehr gut sehen, was mit der Ausgabe eines Float passiert, nachdem die Locale gesetzt wurden.

Leider hat es halt keinen Einfluss auf die Übernahme der Daten aus $_POST, was dazu führt, dass man entweder manuell vorher mit str_replace aus den ',' einen '.' macht oder anderweitig die Daten manipuliert - Hier wäre eine Vereinheitlichung durch das Form genial und würde einem eine Menge Arbeit ersparen! Natürlich sollte die Einstellung von der verwendeten Sprache abhängen, dann ist es die eierlegende Woll-Milch-Sau :)
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 12.05.2009, 22:49:55

Hallo Lutz,
Ich denke mal, dass du damit ein Beispiel-Script zum Ausprobieren meinst!?
Exakt, denn mit dem Thema Lokalisierung habe ich mich - zugegeben - nicht in aller Tiefe beschäftigt.

Ich denke an dieser Stelle gibt es zwei Lösungsansätze:
  • Der allgemeine Input-Filter prüft Inhalte nach einem definierten RegExp und wandelt das Semikolon in einen Punkt um.
  • Das Framework besitzt einen eigenen Filter, der einem die Arbeit abnimmt.
Die zweite Alternative erscheint mir sinnvoller, da dieser Filter-Task dann begrenzt auf Formulare angewendet werden kann und nicht globale Benutzer-Eingaben, die vielleicht nicht modifiziert werden sollten (z.B. ein Suchfeld), betroffen sind.

Code-technisch sollte das also mit der Implementierung einer eigenen Filter-Klasse gemäß http://adventure-php-framework.org/Seit ... lar-Filter machbar sein. Ein Formular-Feld würde dann wie folgt aussehen:

Code: Alles auswählen

<html:form name="get_phone_number">  
  <form:text 
    name="number1"
    filter="resolveFloats"
    filterclass="my::filter::namespace|FloatFilter"
  />,
  <form:text 
    name="number2"
    filter="resolveFloats"
    filterclass="my::filter::namespace|FloatFilter"
  />
  <form:button name="send" value="send" />  
</html:form>
So kann die Filter-Klasse bei Bedarf wieder verwendet werden. Ist das für dich eine praktikable Lösung?

Viele Grüße,
Christian
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Minimales Modul

Beitrag von MrNiceGuy » 13.05.2009, 07:37:22

OK, habe jetzt einen Filter erstellt nund werde ihn demnächst mal testen:

Code: Alles auswählen

<?php
/**
*  @namespace tools::form::filter
*  @class resolveFloat
*
*  Implementiert einen Filter für Text-Eingabeelemente von denen eine Komma-Zahl erwartet wird.
*
*  @author Lutz Mahlstedt
*  @version
*  Version 0.1, 13.05.2009<br />
*/
class resolveFloat extends AbstractFilter
{
  /**
  *  @public
  *
  *  Implementiert die filter()-Methode.
  *
  *  @param string $stringInstruction die Filter-Instruktion
  *  @param string $stringInput der zu filternde Wert
  *  @return float $output die Ausgabe
  *
  *  @author Lutz Mahlstedt
  *  @version
  *  Version 0.1, 13.05.2009<br />
  */
  public function filter ($stringInstruction,
                          $stringInput
                          )
  {
    return floatval (str_replace (',',
                                  '.',
                                  $stringInput
                                  )
                     );
  }
}
?>
Pfad: tools/form/filter/FloatFilter.php - Liegt zwar jetzt mitten im Framework, aber ... naja, was solls :) Vielleicht übernimmst du das ja in einem späteren Release als Standard-Filter, fände ich jedenfalls praktisch für Formulare im Bereich Buchhaltung, Währung, etc. :)
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 13.05.2009, 21:33:37

Hallo Lutz,

die Implementierung kann ich gerne in das Release aufnehmen. Es macht auf jeden Fall Sinn, solche wiederverwendbare Funktionen nicht jedes mal neu implementieren zu müssen.

Sofern du möchtest, kannst du die Funktion auch selbst hinzufügen (siehe PN).

Viele Grüße,
Christian
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Minimales Modul

Beitrag von MrNiceGuy » 13.05.2009, 21:58:59

Kann ich wohl tun, obwohl ich dann wahrscheinlich eher auf die Implementierung direkt in die FormFilter setzen würde - sofern dir das recht wäre!?
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 13.05.2009, 22:09:15

Hi,

gerne. Wo das eingebracht wird ist zunächst egal, wichtig ist, dass es in der Dokumentation auftaucht.

Viele Grüße,
Christian
Viele Grüße,
Christian

phpdummi
Beiträge: 18
Registriert: 23.11.2007, 16:15:15

Re: Minimales Modul

Beitrag von phpdummi » 20.05.2009, 15:13:14

Hi,

ich habe das Tutorial durchgearbeitet und es funktioniert auch alles.
Möchte ich nun aber die <form:text /> Felder durch ein <form:genericval /> austauschen wird
das entsprechende Formularfeld nicht angezeigt. Ich habe dazu folgenden Code benutzt:

Code: Alles auswählen

<form:genericval field="operand1" button="docalc" validator="Number">Bitte eine Zahl eingeben!</form:genericval>
Was mache ich falsch? (Es wird auch keine Fehlermeldung ausgegeben ..)

PS: Das Tutorial ist für Einsteiger einfach genial, danke!

Benutzeravatar
dr.e.
Administrator
Beiträge: 4606
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 20.05.2009, 15:39:26

Hi,

Tauschen funktioniert an dieser Stelle nicht, da die beiden Tags unterschiedliche Aufgaben erfüllen. <form:text /> rendert ein Eingabe-Feld und <form:genericval /> kann zur Ausgabe von Validator-Meldungen innerhalb eines Formulars genutzt werden.

Was genau möchtest du denn erreichen?
Viele Grüße,
Christian

Antworten