PHP mehrere Klassen für Produkte erstellen

baserider

Well-known member
ID: 174417
L
10 März 2007
682
23
Hi,

ich möchte für unterschiedliche Produkte (Handy, Netbook, Surfstick) eine Klasse erstellen.

Was wäre der beste Weg um das zu realisieren? Für jede Produktart eine eigene Klasse oder eine Oberklasse anlegen und dann über Vererbung? Jedes Produkt hat ja Eigenschaften, die in allen Produktarten vorkommen (Titel, Preis, Beschreibung, Bild usw.).

Was ich mir ebenfalls überlegt habe:
Es gibt ja eigentlich auch nur spezielle Produkte. Würde dann eine abstrakte Klasse ausreichen? Diese enthält dann die Methoden, die überall vorhanden sein müssen.
 
So wie du das schilderst, gibt es nur eine Klasse Produkt, die Titel, Preis & Co hat.

Spannend is dann nur die Frage, ob es spezielle Produkte gibt, die weitere Informationen hat, z.B. ein PC hat einen Prozessor, während ein Handy Mobilfunkstandards hat.
In diesem Fall wird von Produkt abgeleitet und erweitert.

Abstrakt machen würd ich die Klasse Produkt nicht. Außer, du bist dir wirklich sicher, dass du keine normalen Produkte hast.
 
Hi,

jedes dieser 3 Produkte hat spezielle Eigenschaften, die die anderen Produkte nicht haben.

Wie meinst du das mit den normalen Produkten?
 
Hi,

ok, danke für die Info.
Da jedes Produkt spezielle Eigenschaften hat, würde ich jeweils eine spezielle Klasse anlegen.

Natürlich kann es auch Fälle geben, wo man nur den Titel oder die Beschreibung eines Produktes wissen will.

PHP:
// Handy
$handy->getBeschreibung;

// Netbook
$netbook->getBeschreibung();

Wäre in diesem Fall der Aufruf von
PHP:
$produkt->getBeschreibung();

falsch oder? (Falls die Produktklasse nicht abstrakt ist, sonst geht es eh nicht)
 
das das ist doch gerade das "schöne" an Vererbung das ich eben so etwas schreiben kann wie

PHP:
$products = array_merge($netbooks, $handys, $surfsticks);
foreach($products as $product){
  echo "<div><h2>".$product->getTitel()."</h2>
  <p>".$product->getBeschreibung."</p>
  <p><b>".$product->getPreis()."</b></p></div>";
}

Da kann es mir egal sein welche Art von Product ich habe den ich weiß ja alle 3 Arten haben auf jeden Fall getTitel getBeschreibung und getPreis

Aradiv
 
Ich wüsste auch nicht welche weiteren Vorteile es haben könnte, wenn jedes Produkt eine eigene Klasse hat. Ggf. würde sogar eine einzige Klasse Produkt ausreichen.

Wie wäre es die speziellen Produkteigenschaften (z.B. Abmessungen [Möbel], Stromverbrauch [Elektronik], ..) in einem großen Array innerhalb der Klasse zu speichern? Jede Eigenschaft, die irgendein Produkt haben kann, hat einen systemweiten Key. So lassen sich dann später auch gut Produktvergleiche machen.

Um die Eigenschaften "einfach" auszulesen, bietet sich __get() an:
PHP:
class Produkt{
  private $_vars = array();
  // ...
  public function __get($var){
    if (in_array($var, array_keys($this->_vars))){
      return $this->_vars[$var];
    } else {
      return NULL;
    }
  }
  // ...
}
 
Ich wüsste auch nicht welche weiteren Vorteile es haben könnte, wenn jedes Produkt eine eigene Klasse hat. Ggf. würde sogar eine einzige Klasse Produkt ausreichen.

Wie wäre es die speziellen Produkteigenschaften (z.B. Abmessungen [Möbel], Stromverbrauch [Elektronik], ..) in einem großen Array innerhalb der Klasse zu speichern? Jede Eigenschaft, die irgendein Produkt haben kann, hat einen systemweiten Key. So lassen sich dann später auch gut Produktvergleiche machen.

Ich will ja nicht jedes Produkt in eine eigene Klasse packen, da hab ich mich vielleicht schlecht ausgedrückt. Es geht eher um Produktgruppen.
Möbel und Elektronikgeräte in eine Klasse zu packen erscheint mir nun nicht so sinnvoll. Ausserdem müsste ich doch auch für jede Gruppe eigene Methoden einbauen, um die Daten zu beschaffen (findeMoebel(), findeElektronikartikel() usw.)
 
Ausserdem müsste ich doch auch für jede Gruppe eigene Methoden einbauen, um die Daten zu beschaffen (findeMoebel(), findeElektronikartikel() usw.)
:?:

Ein Objekt wird keine finde()-Methode haben, um weitere Objekte desselben Typs zu finden. Das is sinnlos.

Stell dir vor :)ugly:), du wärst ein Möbelstück in einem Shop. Wüsstest du dann, welche Elektronikartikel mit USB-Anschluss es gibt? Nein.

Du, als Möbelstück :)ugly:), weißt aber, wie lang, wie breit und wie schwer du bist.
Und wenn du den DVD-Spieler fragst, der kann dir sagen, ob er einen USB-Anschluss besitzt.
 
:?:
Stell dir vor :)ugly:), du wärst ein Möbelstück in einem Shop. Wüsstest du dann, welche Elektronikartikel mit USB-Anschluss es gibt? Nein.

Du, als Möbelstück :)ugly:), weißt aber, wie lang, wie breit und wie schwer du bist.
Und wenn du den DVD-Spieler fragst, der kann dir sagen, ob er einen USB-Anschluss besitzt.

Genau aus diesem Grund habe ich mich gefragt, warum man alles in einer Klasse unterbringen soll.

Das Objekt hat keine find-Methode, aber die jeweilige Klasse. Dort bekomme ich dann ein bestimmtes Objekt zurück:
PHP:
class Moebel{
  public static find($id){
    //code...
    return new self();
  }
}

$moebel = Moebel::find(10);
echo $moebel->getAbmessungen(); usw...
 
Ok, soweit klar.

Die Frage is ja, wie viel du in spezielle Methoden auslagern möchtest. - Und je nachdem hast du dann auch eine oder mehrere bis ganz viele Klassen.

Willst du eher
PHP:
$foo = $productDvdplayer->getProperty("usbslots");
$bar = $productChair->getProperty("height");
oder eher
PHP:
$foo = $dvdplayer->getCountUsbSlots();
$bar = $chair->getHeight();
Oberere Variante is eine Klasse für alle Produkte, dafür gibts keine speziellen Methoden für spezielle Produktmerkmale.
Unterere Variante is für jeden Scheiß ne neue Klasse mit x verschiedenen speziellen Methoden.

Was du effektiv schreiben wirst, wird wohl irgendwas in der Mitte von beiden sein.
 
Hi,

hat denn die obere Variante nen speziellen Namen, damit ich im Netz noch etwas ausführlicher was dazu lesen kann?

Was passiert denn, wenn 2 Produkte z.B. Höhenangaben haben und wie komme ich an die jeweiligen Daten für die einzelnen Produkte?
 
Zuletzt bearbeitet:
Je nach Implementierung entweder so oder so (s. vorheriger Post von mir).

Naja wenn es nur eine Klasse gibt, woher weiß ich dann welche Eigenschaft gemeint ist. Ist es nun die Höhe vom Stuhl oder vom DVD-Player?
Vielleicht versteh ichs ja auch falsch, aber der Aufruf wäre doch:

PHP:
// DVD
$productDvdplayer = new Product();
$foo = $productDvdplayer->getProperty("height");

// Stuhl
$productChair = new Product();
$bar = $productChair->getProperty("height");
 
Verstehst du richtig. Ich seh nur dein Problem nicht :ugly:
Ist es nun die Höhe vom Stuhl oder vom DVD-Player?
Höhe is Höhe.
Wenn ich im Regal 20cm Höhe frei habe, dann passt der DVD-Player mit 10cm Höhe rein, der Stuhl mit 110cm Höhe leider nicht. Is bei beiden Produkten aber dieselbe Höhe.

Hast du verschiedene Höhen, musst du diese Eigenschaften (Ansatz 1: getProperty()) auch unterschiedlich benennen, um sie auseinander zu halten.
 
Hast du verschiedene Höhen, musst du diese Eigenschaften (Ansatz 1: getProperty()) auch unterschiedlich benennen, um sie auseinander zu halten.

Ah, ok ja so hab ichs mir auch gedacht. :)

Angenommen man nimmt Ansatz1, wie komme ich dann an die Daten? In meinem Bsp. weiter oben würde ich diese find-Methode nutzen, um aus der Datenbank die Daten zu holen. Wie mache ich das jetzt hier? Um die Attribute zu bekommen muss ich sie ja erstmal setzen.
 
Du wirst wohl eine 1:n-Beziehung zwischen Artikel und Artikelattribut haben.
Beim Laden eines Artikels lädst du dann alle verknüpften Attribute oder - sinnvoller - du lädst sie nur, wenn du sie auch brauchst. Quasi der Cache-Ansatz:
PHP:
public class Article {

  private $id;
  private $propertiesLoaded = array();

  public __construct($id) {
    $this->id = $id;
    loadMe();
  }

  private function loadMe() {
    $row = DBManager::get()->queryfResult("SELECT name, price, ... FROM article WHERE id = %u;", $this->id);
    $this->setName($row['name']);
    $this->setPrice($row['price']);
  }

  public function getProperty($propertyName) {
    if(!isset($this->propertiesLoaded[$propertyName])) {
      $row = DBManager::get()->queryfResult("SELECT value FROM articleProperty WHERE article_id = %u AND name = '%s';", $this->id, $propertyName);
      if($row)
        $this->propertiesLoaded[$propertyName] = $row['value'];
      else
        $this->propertiesLoaded[$propertyName] = null; // not set
    }
    
    return $this->propertiesLoaded[$propertyName];
  }

}

$articleDvd = new Article(4711);
echo $articleDvd->getProperty('height'); // DB fetch
echo $articleDvd->getProperty('height'); // cache hit
(Ob das mit dem null !== unset hinhaut, weiß ich grad ned auswendig. Schon lange kein richtiges PHP mehr geschrieben :biggrin:)
 
Zuletzt bearbeitet:
theHacker, vielen Dank für deine hilfe.
Ich werd mir das mal ansehen.

Derzeit gibt es ja schon eine DB. Die allgemeinen Dinge stehen in einer Tabelle und die speziellen Dinge jeweils für die Artikelgruppen getrennt in weiteren Tabellen. In den speziellen Tabellen gibts dann jeweils den Fremdschlüssel aus der allgemeinen Tabelle.
 
Derzeit gibt es ja schon eine DB.
Warum hast du das dann nicht schon in Post #1 erwähnt? Wenn die DB schon da ist, schränkt das dein Code-Design doch schon um einiges ein. Oder genauer: Ist das DB-Design ordentlich, ist das Code-Design zu 99% fest vorgegeben.
 
Na da ja alles noch im Aufbau ist, kann ich auch an der DB noch Änderungen vornehmen, aber hatte auch gar nicht daran gdacht es zu erwähnen :roll:, da ich meinte das Coding is unabhängig von der DB.

Jedoch denke ich, das die DB so wie es jetzt ist ja schon recht ok ist. Alles in eine Tabelle schreiben will ich nicht ,da es ja dann Unmengen an NULL-Werten gibt bzw. Spalten, die nie benötigt werden