[PHP/OOP] Problem mit extends und string return

strolch00

redraft.de
ID: 155297
L
21 April 2006
1.684
72
Hi @all,

ich habe folgende Klassen jetzt mal zum test geschrieben um mir mal das mit extends näher zu bringen. Jetzt habe ich aber folgende Probleme:

- Return ist ein Object ==> warum?
- Ist der Code so richtig? Kommt mir alles ziehmlich verworren vor.

Klassen:
PHP:
<?php

/**
 * Class 'html_form'
 *
 * @category HTML Form creator
 * @autor Daniel Schumann <[email protected]>
 * @version 1.0
 * @copyright Copyright (c) 2007, Daniel Schumann
 */

 define('SEPARATOR', "\n");

class html_form {
   /**
    * @var
    */
    static $_out_object;

    function __construct()
    {
       $this->_out_object = array();
    }

    function html_select($_name = NULL, $_value = NULL, $_label = NULL, $_size = 1, $_multiple = FALSE, $_selected = NULL) {
       $_tmp = new select($_name, $_value, $_label, $_size, $_multiple, $_selected);
       $this->_out_object[$_name] = @implode('', $_tmp->_string);
       unset($_tmp);
    }

    function show()
    {
       echo @implode('', $this->_out_object);
       $this->del;
    }

    function del()
    {
       unset($this);
    }
}

class select extends html_form
{
   var $_value;
   var $_label;
   var $_multiple;
   var $_selected;

   function __construct($_name = NULL, $_value = NULL, $_label = NULL, $_size = 1, $_multiple = FALSE, $_selected = NULL)
   {
      $this->_string = array();

      /**
       * NAME == NULL ==> Abbruch
       */
      if($_name == NULL || $_value == NULL || $_label == NULL)
         return;

      $this->_value = is_array($_value) ? $_value : array($_value);
      $this->_label = is_array($_label) ? $_label : array($_label);
      $this->_multiple = (bool)$_multiple;
      $this->_selected = is_array($_selected) ? $_selected : array($_selected);

      /*
       * selectfield anfangen mit bauen
       */
      $_tmp = "<select name=\"".$_name."\" size=\"".$_size."\"";
      if($this->_multiple)
         $_tmp .= " multiple=\"multiple\"";

      $_tmp .= ">";
      $this->_string[] = $_tmp;
      unset($_tmp);

      // array von Value durchgehen und options bauen
      for($_x = 0; $_x < count($_value); $_x++)
         $this->add_option($_value[$_x], $_label[$_x], in_array($_x + 1, $this->_selected));

      $this->_string[] = SEPARATOR . "</select>";
      if(is_array($this->_string))
         return $this->_string;
      else
         return SEPARATOR . "select error" . SEPARATOR;
   }

   function add_option($_value, $_label = NULL, $_selected = FALSE)
   {
      $res = SEPARATOR . "  <option value=\"".$_value."\"";
      if($_selected)
         $res .= " selected=\"selected\"";

      $res .= ">";

      if($_label != NULL)
         $res .= $_label;
      else
         $res .= $_value;

      $res .= "</option>";

      $this->_string[] = $res;
   }

   function __destruct()
   {
      unset($this);
   }
}

 $a = new html_form();
 $a->html_select('test', array(1
                             , 2
                             , 3
                             , 4
                             , 5
                             , 6
                             , 7
                             , 8
                             , 9), array('hallo'
                                       , 'hallo2'
                                       , 'hallo3'
                                       , 'hallo4'), 5, TRUE, 2);
 $a->show();

?>
Ausgabe:
html_form Object
(
[_out_object] => Array
(
[0] => select Object
(
[_name] => test
[_value] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
)

[_label] => Array
(
[0] => hallo
[1] => hallo2
[2] => hallo3
[3] => hallo4
)

[_size] => 5
[_multiple] => 1
[_selected] => Array
(
[0] => 2
)

[_string] => Array
(
[0] =>
)

)

)

)

Kann man was verbessern oder muss man gar was ganz anders machen?

Thx @all
*edit code nochmal geändert
 
Zuletzt bearbeitet:
[...]
- Return ist ein Object ==> warum?

Datenkapselung und der Kontext wird beibehalten (zumindest sehe ich das so, wie das die Lehrer der OOP sehen weiß ich nicht).

- Ist der Code so richtig? Kommt mir alles ziehmlich verworren vor.
Wer 'nähmlich' mit h schreibt ...
Ich verstehe nicht, warum du von der Basisklasse auf die erweiterte Klasse zugreifst bzw. warum select überhaupt von html_form abgeleitet ist - das $this->string liefert ja keinen Grund dafür, da jetzt groß was abzuleiten.
 
Woher kommt bitte die Ausgabe? Aber generel ist der Aufbau so Müll... du nutzt damit nicht die vorteile von OOP. (und was willst du bitte mit STATIC!?)

Aus der kalten würd ich das ganze eher so machen:

PHP:
<?
class form {
	private $objects = array();
	
	public function setMethod() {...}
	public function setAction() {...}
	
	
	public function addElement(form_element $element) {
		$this->objects[] = $element;	
	}
	
	public function show() {
		foreach($this->objects AS $obj) {
			echo $obj->getLabel();
			echo ': ';
			$obj->show();
			echo '<br />';
		}
	}
}

abstract class form_element {
	private $label = '',
		$name = '';
	
	public function setName() {...}
	public function getName() {...}
	
	public function setLabel() {...}
	public function getLabel() {...}
	
	abstract public function show();  
}

class form_element_text extends form_element {
	public function show() {
		echo '<input type="text" name="'.$this->getName().'" />';	
	}
	
	//weitere funktionen wie
	//	maxLength
	//	value
	//	formatierung?
}

class form_element_select extends form_element {
	private $options = array();
	
	public function show() {
		echo '<select name="'.$this->getName().'">';
			foreach($this->options AS $option) {
				echo '<option>'.$option,'</option>';	
			}
		echo '</select>';
	}
	
	public function addOption($option) {
		$this->options = $option;
	}
	
	//weitere funktionen wie
	//	selected
	//	multiselecxt
}

$form = new form;
$form->setAction('index.php');
$form->setMethod('post');

	$text = new form_element_text;
	$text->setName('text1');
	$text->setLabel('Textfeld 1');
	
	$form->addElement($text);
	
	$select = new form_element_select;
	$select->setLabel('SELECT Feld');
	$select->setName('select1');
	
	$select->addOption('Option 1');
	$select->addOption('Option 2');
	$select->addOption('Option 3');
	
	$form->addElement($select);
	
$form->show();

?>
 
Also erstmal danke an ZeroCCC ich habe mir dein Beispiel mal zu Gemüte geführt und angefangen mich richtig in die OOP von PHP5 einzulesen.

Jetzt habe ich ein tut gefunden und hoffte eigentlich alles verstanden zu haben aber mit der Umsetzung hapert es doch noch a weng.

Hier mal mein Code:
form.php
PHP:
<?php

/**
 * Class 'html_form'
 *
 * @category HTML Form creator
 * @autor Daniel Schumann <[email protected]>
 * @version 1.0
 * @copyright Copyright (c) 2007, Daniel Schumann
 */

abstract class html_form {
   /**
    * @var
    */
    protected $_out_object = array();
    const _SEPARATOR_ = "\n";

    function __construct() {
    }

    abstract function select_construct(select $_data_array);
/*
    abstract function html_radio(radio $_name = NULL
                                         , $_data = NULL
                                         , $_br = NULL);
*/
    function show() {
       echo @implode('', $this->_out_object);
       $this->del;
    }

    function __destruct() {
       unset($this);
    }
}

require_once("class_form_select.php");
//require_once("class_form_radio.php");

 $a = new html_form;
 $a->select_construct(array('name' => 'test'
                          , 'value' => array(1
                                           , 2
                                           , 3
                                           , 4
                                           , 5
                                           , 6
                                           , 7
                                           , 8
                                           , 9)
                         , 'label' => array('hallo'
                                          , 'hallo2'
                                          , 'hallo3'
                                          , 'hallo4')
                         , 'size' => 5
                         , 'mutiple' => TRUE
                         , 'selected' => 2));
// $a->html_radio('test_radio', array('hallo', 1,2,3,4 => TRUE, 5, 6, 'foo', 'bar'), 3);
 $a->show();

?>
form_select.php
PHP:
<?php

class select extends html_form
{
   function select_construct($_data_array = NULL) {
      $this->_string = array();

      /**
       * NAME == NULL ==> Abbruch
       */
      if($_name == NULL || $_value == NULL || $_label == NULL)
         return;

      $this->_value = is_array($_value) ? $_value : array($_value);
      $this->_label = is_array($_label) ? $_label : array($_label);
      $this->_multiple = (bool)$_multiple;
      $this->_selected = is_array($_selected) ? $_selected : array($_selected);

      /*
       * selectfield anfangen mit bauen
       */
      $_tmp = "<select name=\"".$_name."\" size=\"".$_size."\"";
      if($this->_multiple)
         $_tmp .= " multiple=\"multiple\"";

      $_tmp .= ">";
      $this->_string[] = $_tmp;
      unset($_tmp);

      // array von Value durchgehen und options bauen
      for($_x = 0; $_x < count($_value); $_x++)
         $this->add_option($_value[$_x], $_label[$_x], in_array($_x + 1, $this->_selected));

      $this->_string[] = SEPARATOR . "</select>";
      if(is_array($this->_string))
         return $this->_string;
      else
         return SEPARATOR . "select error" . SEPARATOR;
   }

   function add_option($_value, $_label = NULL, $_selected = FALSE)
   {
      $res = SEPARATOR . "  <option value=\"".$_value."\"";
      if($_selected)
         $res .= " selected=\"selected\"";

      $res .= ">";

      if($_label != NULL)
         $res .= $_label;
      else
         $res .= $_value;

      $res .= "</option>";

      $this->_string[] = $res;
   }

   function __destruct()
   {
      unset($this);
   }
}
Dazu folgende Ferhlermeldung:
Fatal error: Declaration of select::select_construct() must be compatible with that of html_form::select_construct() in /srv/www/web0/html/sawmill/core/class_form_select.php on line 63

Was will der denn genau von mir die Methoden sind doch identisch/kompatibel oder nicht?
 
Hmm ok ich dachte das mit demInstancencheck "select" war richtig aber daran lag es wohl.

Ich habe den Code nun wie folgt geändert?
form.php
PHP:
//[...]
    abstract function select_construct($_data_array = NULL);
//[...]
form_select.php
PHP:
//[...]
   function select_construct($_data_array = NULL) { 
//[...]
Dazu folgende Ferhlermeldung:
Fatal error: Cannot instantiate abstract class html_form in /srv/www/web0/html/sawmill/core/class_form.php on line 43

Der Code in den Zeilen ist dieser hier (1. Zeile ist die 43):
PHP:
 $a = new html_form;
 $a->select_construct(array('name' => 'test'
                          , 'value' => array(1
                                           , 2
                                           , 3
                                           , 4
                                           , 5
                                           , 6
                                           , 7
                                           , 8
                                           , 9)
                         , 'label' => array('hallo'
                                          , 'hallo2'
                                          , 'hallo3'
                                          , 'hallo4')
                         , 'size' => 5
                         , 'mutiple' => TRUE
                         , 'selected' => 2));
// $a->html_radio('test_radio', array('hallo', 1,2,3,4 => TRUE, 5, 6, 'foo', 'bar'), 3);
 $a->show();
 
Dir ist scheinbar nicht ganz klar was abstract bedeutet. Du kannst von einer abstrakten Klasse keine Instanz erzeugen da die Klasse unvollständig ist. Die Abstrakten funktionen musst du in einer vererbten Klasse implementieren. Was du auch getan hast, aber du versuchst von der falschen Klasse eine Instanz zu erzeugen.

In deinem fall müsste das "$a = new select;" heißen und nicht "$a = new html_form;".
 
Dazu folgende Ferhlermeldung:[...]

Abstrakte Klassen können nicht instanziert werden, da sie nur als "Bauanleitung" für bestimmte Methoden dienen.

Halte dich an Zero´s Beispiel, dann bist du auf der sicheren Seite ;)

Zu deinem Denkfehler: Ein Formularelement erweitert zwar ein Formular in gewisser Weise, ist aber kein spezielles Formular.

Ein (hoffentlich anschauliches) Beispiel:
Eine Klimaanlage erweitert ein Auto um die Fähigkeit des Kühlens. Allerdings kann keine Klimaanlage ansich fahren - sprich ihr wurde die Methode des Fahrens vom Auto/Motor/Getriebe nicht vererbt.
 
Ahh alles klar nach langem googlen und dem lesen hier habe ich das jetzt verstanden. Ich mache die zwei Klassen noch fertig und dann würde ich jemanden nochmal bitten einen Blick drauf zu werfen.

Also kann ich dann in der html_form noch eine puplic static function show() hinzufügen um das ganze dann auszugeben lassen, richtig?

Vielleicht kann mirja nochmal einervon euch nenkleinen tipp geben wie ich das am besten erledige wegen fileupload usw. wäre sehr nice.

Thx @all.