Vlastní FormControl – Vlastní formát čísla – Jak na to?
- jasir
- Člen | 746
Ahoj, snažím se vytvořit si vlastní FormControl pro prezentování
peněžní hodnoty.
Jedná se vlastně o text input, ve kterém má uživatel možnost zapsat
číselnou hodnotu.
Ta může být zapsáná:
- s oddělovačem tisíců 100.000,00 (sto tisíc)
- i bez oddělovačů tisíců jako float, tj 100000,00
Chtěl bych, aby setValue(), getValue() vracelo číselnou hodnotu (bez oddělovačů).
<?php
$money = new MoneyInput(..)
$money->setValue(100000); /* Formulář bude zobrazovat 100,000.00 */
$val = $money->getValue(); /* Vrátí hodnotu bez oddělovačů */
?>
Nějak na to nemůžu přijít, zatím mám jenom:
<?php
class MoneyInput extends TextInput
{
public function __construct ($label = NULL, $message = NULL, $cols = NULL, $maxLength = NULL)
{
parent::__construct($label,$cols,$maxLength);
if ($message===NULL) {
$message = 'Musí být číselná hodnota, jako oddělovač tisíců lze použít tečku.';
}
$this->addRule(array($this, 'validateMoney'), $message);
}
/**
* Validates money value.
* Allows format 100.000,00 (cents are optional) or
* without thousands separators 1000000.
*
* @param MoneyInput $control
* @param mixed $arg
*/
public function validateMoney(MoneyInput $control, $arg)
{
$value = $control->getValue();
if (preg_match('/\\A\\b[0-9]{1,3}(?:.?[0-9]{3})*(?:\\,[0-9]{2})?\\b\\z/', $value)) {
return TRUE;
}
return $this->validateFloat($control);
}
}
?>
Napadlo mě přepsat setValue()
(nastavení zobrazení) a
getValue()
(odstranění/konverze oddělovačů),
ale validator si volá getValue()
.
Zatím to řeším že při vytváření formu do setValue()
,
setDefaults()
pošlu číslo v požadovaném formátu a po
$form->getValues
provedu konverzi, ale chtěl bych, aby to
umělo samo.
EDIT: Mohu použít proměnnou tmpValue
? To by mi to asi vyřešilo, validoval bych podle tmpValue
, a
setValue()
a getValue()
by pak mohli provádět
konverze číselného formátu.
Editoval jasir (5. 5. 2009 13:49)
- PetrP
- Člen | 587
insider napsal(a):
Zdravim,
co prepsat nejak takhle
<?php public function getValue($number = true){ if($number) return str_replace(array(',','.'),array('',''),$this->value); else return $this->value; } ?>
Nevim, jak presne vypada original metody getValue
Tím bych ale ze vstupu (string) 100.000,00
(100 tisíc) dostal
(string) 10000000
(tedy 10 miliónů. ;])
- jasir
- Člen | 746
Nakonec jsem to vyřešil nějak takhle. Funguje to :-) Ale mám
takové tušení, že to nemusí být úplně ono :)
Třeba to někomu pomůže, tvorba vlastních Inputů tu moc řešená
zatím nebyla.
<?php
/**
* NumericTextInput.
*
* @package Base
* @subpackage Controls
**/
class NumericTextInput extends TextInput
{
protected $decimals = 2;
protected $thousandsSeparator = ".";
protected $decimalSeparator = ",";
/**
* Constructs Text Input and sets Rules.
*
* @param name $label
* @param int $decimals
* @param string $message
* @param string $thousandSeparator
* @param string $decimalSeparator
* @param int $cols
* @param int $maxLength
* @return NumericTextInput
*/
public function __construct ($label = NULL, $decimals = 0, $message = NULL,
$thousandSeparator = ".", $decimalSeparator = ",", $cols = NULL, $maxLength = NULL) {
parent::__construct($label, $cols, $maxLength);
$this->decimalSeparator = $decimalSeparator;
$this->thousandsSeparator = $thousandSeparator;
$this->decimals = $decimals;
if ($message === NULL) {
$message = "Číslo musí mít formát %s.";
}
$message = sprintf($message, $this->getSampleFormatText());
$this->addRule(array($this, 'validateNumericText'), $message);
$this->getControlPrototype()->class = 'right-aligned';
}
//---------------------------------------------------------------------------
/**
* Gets value.
*
* @param bool $transform Used for internal call from validator
* @return mixed
*/
public function getValue($transform = TRUE) {
$value = parent::getValue();
if ($transform === TRUE) {
$value = str_replace(array($this->thousandsSeparator,$this->decimalSeparator), array('','.'), $value);
}
return $value;
}
//---------------------------------------------------------------------------
/**
* Creates HTML control.
* Changes value to numeric format.
*/
public function getControl() {
$control = parent::getControl();
$form = $this->getForm(FALSE);
if ($form === FALSE || $form->isSubmitted() === FALSE) {
$control->value
= number_format($this->value, $this->decimals, $this->decimalSeparator, $this->thousandsSeparator);
}
return $control;
}
//---------------------------------------------------------------------------
/**
* Validates numeric format.
* Allows format 100.000,00 (cents are optional) or
* without thousands separators 1000000.
*
* @param mixed $item
* @param mixed $arg
*/
public function validateNumericText($control) {
$value = $control->getValue(FALSE);
if (preg_match(
"/\\A[-]{0,1}[0-9]{1,3}+(?:\\{$this->thousandsSeparator}?[0-9]{3})*(?:\\"
.$this->decimalSeparator
."[0-9]{"
.$this->decimals
."})?\\z/", $value)
) {
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
/**
* Formats help string describing numeric format.
* @returns string
*/
protected function getSampleFormatText() {
$s = "999{$this->thousandsSeparator}999{$this->thousandsSeparator}999";
if ($this->decimals > 0) {
$s .= $this->decimalSeparator . str_repeat('9', $this->decimals);
}
return $s;
}
}
?>
Editoval jasir (22. 7. 2009 12:00)
- kravčo
- Člen | 721
PetrP napsal(a):
Tím bych ale ze vstupu
(string) 100.000,00
(100 tisíc) dostal(string) 10000000
(tedy 10 miliónů. ;])
Toto už smeruješ do problémov s locale, totiž v našich končinách sa čísla píšu s desatinnou čiarkou a tisíce sa oddeľujú medzerou… Napríklad v Británii je to zase inak. Pokiaľ aplikácia nestojí len na jednom locale, číslo „100.000“ napísané slovákom/čechom a angličanom by malo byť chápané rôzne (sto resp. stotisíc). To, či je človek slovák alebo angličan samozrejme z prostredia PHP dá len ťažko zistiť ;) ale má asi zmysel uvažovať jazykové nastavenie…
- PetrP
- Člen | 587
kravco napsal(a):
Toto už smeruješ do problémov s locale, totiž v našich končinách sa čísla píšu s desatinnou čiarkou a tisíce sa oddeľujú medzerou… Napríklad v Británii je to zase inak. Pokiaľ aplikácia nestojí len na jednom locale, číslo „100.000“ napísané slovákom/čechom a angličanom by malo byť chápané rôzne (sto resp. stotisíc). To, či je človek slovák alebo angličan samozrejme z prostredia PHP dá len ťažko zistiť ;) ale má asi zmysel uvažovať jazykové nastavenie…
Reagoval jsem jenom na tuto konstrukci:
return str_replace(array(',','.'),array('',''),$this->value);
která jak čárku tak tečku zahodí, nezávisle na čemkoli ;].
Celá problematika převodu (string) na (float) je hodně složitá a nebyla tématem mého příspěvku.