Autor Zpráva
motik
Profil
zdravím,
v OOP nejsem zatím moc zdatný.. Potřebuju jednoduše pracovat s formuláři a chci si vytvořit (abych se i zdokonalil) vlastní třídu. Chtěl jsem se zeptat zkušenějších, jestli nejsem úplně mimo (chybí dost věcí udělat, ale myslím si, že je to dostatek, aby jste měli představu a případně mě nasměrovali správným směrem..
Díky za vaše názory.
<?php   
class Form
  {      
    public 
      $lasted = '',
      $rule = array(),
      $form = array(),
      $rules = array(),
      $input = array(),
      $span = array(),
      $error = array();
    
    function addValue($value)
      {
        $this->form[$this->lasted]['val'] = htmlspecialchars($value);
        
        return $this;
      }
      
    function addText($name, $label = NULL, $span = NULL, $val = NULL)
      {
        $this->form[$name] = array('type' => 'addText', 'label' => $label, 'span' => $span, 'val' => $val);
        $this->lasted = $name;
        
        return $this;
      }
    
    function addRule($fce, $mess = NULL, $arg = NULL)
      {
        $this->rules[] = array('name' => $this->lasted, 'fce' => $fce, 'mess' => $mess, 'arg' => $arg);
        
        return $this;
      } 

    function formular()
      {
        foreach ($this->form as $key => $val)
          {
            switch ($val['type'])
              {
                case 'addText':
                    print_r($val);
                    echo "<br />";
                  break;
              }
            //echo $key . " => " . $val . "<br />";
          }
      }
      
    function isValid()
      {            
        $poc = count($this->rules);
        // kůli vypsání chyb postupně
        $err_je = array();
                    
        // projde všechny pole na validaci
        for ($i = 0; $i < $poc; $i++)
          {
            $this->rule = $this->rules[$i];
            $out = FALSE;
            $err = NULL;
  
  //nahradit za vstupní proměné!!!!!!!!!
            $t_val = "5";
            $subject = $t_val;
            
            if (!isset($err_je[$this->rule['name']]))
              {
                switch ($this->rule['fce'])
                  {    
                    /**
                     * je hodnota číslo? 
                     */     
                    case 'FLOAT': 
                        if (is_numeric($t_val)) $out = TRUE;
                          else 
                            {
                              $err = $this->rule['mess'];
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     * je hodnota celočíselná?
                     *  - pozor, !MUSÍ BÝT STRING, JINKA VRACÍ FALSE!!!                 
                     */
                    case 'INTEGER':                              
                        if (ctype_digit("$t_val")) $out = TRUE;
                          else 
                            {
                              $err = $this->rule['mess'];
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     *  minimální délka
                     */                                 
                    case 'MIN_LENGHT':
                        if ($this->rule['arg'] <= strlen($t_val)) $out = TRUE;
                          else 
                            {
                              $err = sprintf($this->rule['mess'], $this->rule['arg']);
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     *  maximální délka
                     */ 
                    case 'MAX_LENGHT':
                        if ($this->rule['arg'] >= strlen($t_val)) $out = TRUE;
                          else 
                            {
                              $err = sprintf($this->rule['mess'], $this->rule['arg']);
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     * je hodnota v rozsahu?  
                     */               
                    case 'RANGE':
                        if ($this->rule['arg'][0] <= $t_val and $t_val <= $this->rule['arg'][1]) $out = TRUE;
                          else 
                            {
                              $err = sprintf($this->rule['mess'], $this->rule['arg'][0], $this->rule['arg'][1]);
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     * vyhovuje regulárnímu výrazu?
                     */                                 
                    case 'PATTERN':
                        if(preg_match($this->rule['arg'], $subject)) $out = TRUE;
                          else
                            {
                              $err = $this->rule['mess'];  
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;
                    
                    /**
                     * je email?
                     */                                 
                    case 'EMAIL':
                        $atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // znaky tvořící uživatelské jméno
                        $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // jedna komponenta domény                  
                        if (preg_match("(^$atom+(\\.$atom+)*@($domain?\\.)+$domain\$)i", $subject)) $out = TRUE;
                          else
                            {
                              $err = $this->rule['mess'];  
                              $err_je[$this->rule['name']] = 1;
                            }
                      break;      
                  }
      
      
              // dodělat
                if (!$out) 
                  {
                    echo 'nenene' ."<br />";
                    $this->error[$this->rule['name']] = $err;
                  }
                 else echo "anoanoano<br />"; 
                 
              }

          }            
        
        // odmazat                        
        echo "----------------<br />";
        echo "<pre>";
        print_r($this->error);
        echo "</pre>";
      }
  }

                                      
$form = new Form();
$form->addText('pokus1')
  ->addRule('EMAIL', 'neplatná adresa')
  ->addValue('testovací hodnota')
  ->addValue('testovací hodnota by to měla přepsat');


//*

$form->addText('pokus3');
$form->addRule('RANGE','Zadejte číslo od %d do %d', array(4,6));
$form->addText('pokus4');
$form->addRule('PATTERN','Je to regulár', "/def/");
$form->addText('pokus5');
$form->addRule('INTEGER','Je tu %d opic', '1');
  //*/
$form->formular();
$form->isValid();
?>
Johnik
Profil
V OOP nejde o to mít jednu třídu, která ti zabalí všechno, ale o to rozpadnout problém do objektů, které spolu nějakým způsobem souvisí.

V případě formulářů je nejlepší mít:

Form
- třída definující celý objekt formuláře
- umožňuje renderování celého formuláře

TextInput, HiddenInput, FileInput, ComboBox, ...
- třída, která představuje vždy jen jeden typ formulářového prvku
- dědí od nějaké základní ControlBase třídy, která zpřístupňuje metody pro přidání validačního pravidla, validování, renderování, ... Ovšem samotná implementace je již v té odvozené třídě.

Form i ControlBase jsou odvozené od nějaké třeba UIComponent, která kompozicí umožňuje renderování html nebo přímo od třídy HtmlRenderer.

Edit:
Také dobrým důvodem proč to takto udělat je, že ve tvém příkladě mi api dovolí přidat prvně pravidlo a na něj navěsit fluentem text input. Když budeš mít ve Form jen metody vytvářející formulářové kontrolky a teprve ty budou mít metodu addRule, takovou chybu mi to nedovolí.
motik
Profil
Johnik:
V OOP nejde o to mít jednu třídu, která ti zabalí všechno, ale o to rozpadnout problém do objektů, které spolu nějakým způsobem souvisí.
to sem nějak postřehl, ale jaksi jsem tomu ještě dostatečně bohužel neporozuměl

Také dobrým důvodem proč to takto udělat je, že ve tvém příkladě mi api dovolí přidat prvně pravidlo a na něj navěsit fluentem text input.
jestli můžeš, tak uveď prosím konkrétní případ (nenapadá mě využití)
Johnik
Profil
Tvůj případ dovolí:

$form = new Form();
$form->addRule(...)->addText();


Moje řešení má přesně dané api a tedy nedovolí to takto použít a ani napovídání kódu mi to nenapoví:

$form = new Form();
$form->addTextInput("name", "value")->addRule(...)->addRule(...);


Podívej se na formuláře nette jak jsou udělané když chceš přesný příklad. Já bych je sice udělal ještě trošku jinak, ale uvidíš princip, o to jde.
motik
Profil
Johnik:
Tvůj případ dovolí:
$form = new Form();
$form->addRule(...)->addText();
rekl bych, že nedovolí.. addRule se váže k poslednímu přidanému prvku
[EDIT] dovolí, ale nebude nebude se to vázat k tomu následujícímu prvku addText, ale k předchozímu

> $form->addTextInput("name", "value")->addRule(...)->addRule(...);
takto jsem to právě chtěl a měl takto mi to funguje

--------------------------------------------
špatně jsem tě pochopil a myslel jsem příklad na $form->addRule(...)->addText();, jinak u nette se snažím inspirovat, ale kód je pro mě ještě dost složitý
Johnik
Profil
<?php

class Form extends Html
{
	
	public function __construct()
	{
		parent::__construct("form", true);
	}
	
	public function addTextInput($name, $value, $label)//:TextInput
	{
		$label = new Label($name, $label);
		$control = new TextInput($name, $value);
		
		$this->addChild($label);
		$this->addChild($control);
	}
	
	public function getControlByName($name)//:ControlBase
	{
		// vraci kontrolky podle jmena
	}
	
	public function getLabelByName($name)//:Label
	{
		// vraci popisky
		// trida Label muze byt bud odovzena jen z Html
		// nebo take z ControlBase, pak by tahle metoda vracela obecnejsi ControlBase
	}
	
}

class ControlBase extends Html
{
	
	protected $rules/* Array */ = array();
	private $_isValid/* Boolean */ = true;
	
	public function addRule($rule, $value)//:ControlBase
	{
		$this->rules[] = array($rule, $value);
		
		return $this;
	}
	
	public function validate()//:Boolean
	{
		return $this->isValid;
	}
	
	public function get_isValid()//:Boolean
	{
		return $this->_isValid;
	}
	
	public function addErrorClass()//:void
	{
		$this["class"] .= " error";
	}

}

class TextInput extends ControlBase
{
	
	public function __construct()
	{
		parent::__construct("input", false);
		
		$this["type"] = "text";
	}
	
	/* override */ public function validate()//:Boolean
	{
		// overeni pravidel (treba delky, povolenych znaku, blabla)
		// Jsou pro kazdou kontrolku jine, u ComboBoxu asi neni potreba overovat povolene znaky apod.
		
		return $this->isValid;
	}
	
}

$form = new Form();
	$form->addTextInput("name", "value", "label");

// vypsani celeho formulare
$form->render();

// nebo jen vypsani polozky
$form->getControlByName("name")->render();
$form->getLabelByName("name")->render();

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0