htmlform

raspi 03.02.05 16:50

Luokka HTML-formien tekemiseen, koska se on niin työlästä tehdä käsin.

 Tekstiversio  Arvo: 9 (13 ääntä)  Äänestä: +  -
<?php
/*
Versionhallinta:
$Id: form.php 60 2005-02-03 15:02:36Z raspi $
$Rev: 60 $
$LastChangedRevision: 60 $
$LastChangedDate: 2005-02-03 17:02:36 +0200 (Thu, 03 Feb 2005) $
$LastChangedBy: raspi $
$Date: 2005-02-03 17:02:36 +0200 (Thu, 03 Feb 2005) $
$Author: raspi $
*/


require_once('fckeditor.php'); // FCKeditor (<textarea>)

/**
 * htmlform
 * Luokka XHTML-formien luomiseen.
 *
 * <code>
 * <?php
 * $f = new htmlform($_SERVER['PHP_SELF'], 'add');
 * $f->fhidden("page", $_GET['page']); // piilotettu kenttä
 * $f->flegend("Lisää uusi valmistaja"); // legend-teksti
 * $f->ftext('Nimi', 'name'); //
 * $f->fsubmit('', 'Lisää');
 * echo $f->printform();
 * ?>
 * </code>
 *
 * Huom: GPL:ää
 *
 * @access public
 * @author Pekka Järvinen
 * @copyright Pekka Järvinen 2004
 */

class htmlform {

 /**
  * fields
  * @var string sisältää kaikki kentät (input type=jotain, textarea jne)
  * @access public
  */

  var $fields = null;

 /**
  * legend
  * @var string legend-teksti, max: vain 1 kpl
  * @access public
  */

  var $legend = null;

 /**
  * enctype
  * @var string Formin enctype. esim. multipart. Määritellään enctype-metodilla.
  * @access private
  */

  var $enctype = null;

 /**
  * pad
  * @var integer tämän verran välilyöntejä lisätään jokaiselle riville
  * @access public
  */

  var $pad = 4;

 /**
  * Konstruktori
  * $break määrittelee lyödäänkö br-tagia kenttien perään, joita syötetään
  * funktioilla fsubmit, ftext, fpass, fbool, ftextarea, ftextarea2.
  *
  * @param string $action
  * @param string $what
  * @param bool   $break
  * @param string $method
  */

  function htmlform ($action, $what, $break = 1, $method = 'post') {
    // constructor
    $this->action = $action;
    $this->method = $method;
    $this->fhidden('what', $what);
    if($break) $this->br = "<br />"; else $this->br = null;
  } // /function


 /**
  * fhidden-metodi
  * Piilotettu kenttä.
  *
  * @param string $name
  * @param string $value
  */

  function fhidden ($name, $value) {
    $this->fields .= sprintf("%s    <input type=\"hidden\" name=\"%s\" value=\"%s\" />\n", str_pad(' ', $this->pad), $name, $value);
  } // /function

 /**
  * fsubmit
  * Submit-nappula. Voi olla vain yksi kappale.
  *
  * @param string $comment
  * @param string $value
  */

  function fsubmit ($comment, $value) {
    $this->fields .= sprintf("%s    <label for=\"submit\">%s</label><input class=\"fsubmit\" type=\"submit\" name=\"submit\" value=\"%s\" />%s\n", str_pad(' ', $this->pad), $comment, $value, $this->br);
  } // /function

 /**
  * ftext
  * Tekstikenttä
  *
  * @param string $comment
  * @param string $name
  * @param string $value
  */

  function ftext ($comment, $name, $value = '') {
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><input class=\"ftext\" type=\"text\" name=\"%s\" value=\"%s\" />%s\n", str_pad(' ', $this->pad), $name, $comment, $name, h($value), $this->br);
  } // /function

 /**
  * fpass-metodi
  * Salasanakenttä
  *
  * @param string $comment
  * @param string $name
  */

  function fpass ($comment, $name) {
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><input class=\"fpass\" type=\"password\" name=\"%s\" />%s\n", str_pad(' ', $this->pad), $name, $comment, $name, $this->br);
  } // /function

 /**
  * @param string $comment
  * @param string $name
  * @param bool   $checked
  */

  function fbool ($comment, $name, $checked = 0) {
    // boolean field
    $c = ($checked == 1 ? ' checked="checked"' : null);
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><input class=\"fbool\" type=\"checkbox\" name=\"%s\" value=\"1\"%s />%s\n", str_pad(' ', $this->pad), $name, $comment, $name, $c, $this->br);
  } // /function

 /**
  * ftextarea2 - FCKeditor
  * katso FCKeditorin dokumentaatio.
  *
  * @param string $comment
  * @param string $name
  * @param string $value
  * @param string [$toolbarset] vakiona 'Basic'
  */

  function ftextarea2 ($comment, $name, $value = '', $toolbarset = 'Basic') {
    $this->fields .= "    <label for=\"$name\">$comment</label><br />\n";
    $fck = new FCKeditor($name);
    $fck->ToolbarSet = $toolbarset;
    $fck->BasePath = dirname($_SERVER['PHP_SELF']) . '/';
    $fck->Value = $value;
    $this->fields .= $fck->CreateHtml();
  } // /function

 /**
  * ftextarea-metodi
  * Textarea ja mahdollinen sisältö = $value
  *
  * @param string $comment
  * @param string $name
  * @param string [$value]
  */

  function ftextarea ($comment, $name, $value = '') {
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><textarea class=\"ftextarea\" name=\"%s\" rows=\"20\" cols=\"80\">%s</textarea>%s\n", str_pad(' ', $this->pad), $name, $comment, $name, $value, $this->br);
  } // /function

 /**
  * fselect
  * $comment Esim: "valitse kategoria". Voi olla myös tyhjä.
  * $name Esim: "kategoria"
  * $array on taulukko jossa on kentät "value" ja "text"
  * value annetaan value=jotain arvona ja text on taas ko. valuen tekstiarvo.
  * esim value=1 text="Kategoria numero 1".
  * Helpoin tapa hyödyntää tätä on käyttää SQLhandler-luokan Select-metodia esim. näin:
  * <code>
  * <?php
  * $q = "SELECT id AS value, kategorian_nimi AS text FROM KATEGORIAT;";
  * // nyt id on value ja kategorian_nimi text
  * $kategoriat = $db->select($q, "Haetaan kategoriat");
  * if(is_array($kategoriat)) {
  *   $f = new htmlform($_SERVER['PHP_SELF'], 'foobar');
  *   $f->fselect('Valitse kategoria:', 'kategoria', array('Valitse kategoria' => $kategoriat));
  *   $f->fsubmit('', 'OK');
  *   echo $f->printform(); // näytetään formi
  * }
  * ?>
  * </code>
  *
  * $kategoriat näyttää esimerkiksi tältä:
  * $kategoriat[] = array('text' => "foo", 'value' => 'bar');
  * $kategoriat[] = array('text' => "xyz", 'value' => 'quux');
  *
  * $selected on joku $arrayn id (value)
  *
  * @param string $comment
  * @param string $name
  * @param array  $array
  * @param integer [$selected]
  */

  function fselect ($comment, $name, $array, $selected = '') {
    // select + optgroup
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><select class=\"fselect\" name=\"%s\">\n", str_pad(' ', $this->pad), $name, $comment, $name);

    foreach(array_keys($array) AS $optname) {
      $this->fields .= sprintf("%s        <optgroup label=\"%s\">\n", str_pad(' ', $this->pad), $optname);
      for($i=0; $i < count($array[$optname]); $i++) {
        $s = ($selected == $array[$optname][$i]['value'] ? ' selected="selected" class="fselected"' : null);
        $this->fields .= sprintf("%s          <option value=\"%s\"%s>%s</option>\n", str_pad(' ', $this->pad), $array[$optname][$i]['value'], $s, $array[$optname][$i]['text']);
      } // /for
      $this->fields .= sprintf("%s        </optgroup>\n", str_pad(' ', $this->pad));
    } // /foreach
   
    $this->fields .= sprintf("%s    </select>%s\n", str_pad(' ', $this->pad), $this->br);
  } // /function

 /**
  * ffile
  * Kenttä tiedoston lähetykseen
  * @param string $comment
  * @param string $name
  */

  function ffile ($comment, $name) {
    $this->fields .= sprintf("%s    <label for=\"%s\">%s</label><input name=\"%s\" type=\"file\" />%s\n", str_pad(' ', $this->pad), $name, $comment, $name, $this->br);
  } // /function

 /**
  * flegend
  * Formin legend-teksti.
  * Tämän voi määrittää vain kerran.
  * @param string $str
  */

  function flegend ($str) {
    $this->legend = $str;
  } // /function


 /**
  * enctype-metodi
  * Tällä formin enctypen voi muuttaa.
  * ei pakollinen.
  *
  * @param string $s
  * @access public
  */

  function enctype ($s) {
    $this->enctype = $s;
  } // /function

 /**
  * printform-metodi
  * Tällä tulostetaan formi aikaisemmin annettujen parametrien perusteella.
  * Kutsu tätä viimeiseksi.
  *
  * @access public
  */

  function printform () {
    $o = null;
    $e = !empty($this->enctype) ? " enctype={$this->enctype}" : null;
    $o .= sprintf("%s<form method=\"%s\" action=\"%s\"%s>\n", str_pad(' ', $this->pad), $this->method, $this->action, $e);
    $o .= sprintf("%s  <fieldset>\n", str_pad(' ', $this->pad));

    if(isset($this->legend) && !empty($this->legend))
      $o .= sprintf("%s    <legend>%s</legend>\n", str_pad(' ', $this->pad), $this->legend);

    $o .= $this->fields;
    $o .= sprintf("%s  </fieldset>\n", str_pad(' ', $this->pad));
    $o .= sprintf("%s</form>\n", str_pad(' ', $this->pad));

    return (string) $o;
  } // /function

} // /class
?>

Akiro 10:43 4.2.05 
require_once('fckeditor.php'); <-- eikä sit näy missään, saako tuonkin jostain?
neon 11:31 4.2.05 
Akiro kirjoitti:
require_once('fckeditor.php'); <-- eikä sit näy missään, saako tuonkin jostain?


http://www.fckeditor.net/
editoitu: 04:45 8.2.05
theril 04:14 8.2.05 
Mukavaa nähdä kerrankin oikein rakennettu PHP-pätkä, tällaista on mukava käyttää omissa projekteissakin.

Toinen, ehkä olio-opillisesti parempi, tapa olisi rakentaa "olio-hierarkia", jossa formin kentät olisivat omia luokkiaan. Täten skriptiä olisi kätevä laajentaa uusilla luokilla. Eli siis tyyliin:
<?php
class Form
{
  private $controls = array();
  private $action;

  public function __construct($action)
  {
      $this->action = $action;
  }

  public function addControl(FormControl $control)
  {
      $this->controls[] = $control;
  }

  public function getHtml()
  {
      $ret = "<form action=\"{$this->action}\">\n";
      foreach($this->controls as $control)
      {
           $ret .= $control->getHtml();
      }
      $ret .= "</form>";
      return $ret;
  }
}

interface FormControl
{
    public function getHtml();
}

class SubmitButton implements FormControl
{
    protected $name;
    protected $value;
    public function __construct($name, $value)
    {
           $this->name = $name;
           $this->value = $value;
    }

    public function getHtml()
    {
           return "<input type=\"submit\" name=\"{$this->name}\" value=\"{$this->value}\" />\n";
    }
}
?>


Ja käyttö tapahtuisi seuraavasti:
<?php
$form = new Form('index.php');
$form->addControl(new SubmitButton('submit', _('Save')));
echo $form->getHtml();
?>



Yksi ihmetyksen aihe on alituinen sprintf-funktion käyttö. Yhdistämisoperaattorin (.) lienee huomattavasti tehokkaampaa ja IMHO myös luettavampaa.