OOP -> Verständnisproblem

Steusi

Nasenbär
Hallo Leute,

ich arbeite mit Objekten in PHP und verzweifle gerade, wie kann ich die einzelnen Objekten handhaben. Irgendwie fehlt mir etwas "übergeordnetes", das mir die Verwaltung erleichtert.

Ein Beispiel:
Ich ziehe aus einer Datenbank Informationen zu Artikeln. Dabei ist jeder Tupel (in der DB) -> ein Objekt (in PHP)

Wie macht man dan clever?
Ich hätte alle neuen Objekte in ein Array gepresst, damit ich sie "wiederfinde" und ansprechen kann, aber das erscheint mir nicht richtig!
Würde vereinfacht so aussehen:
PHP:
// SQL-Abfrage usw.
while($row = mysql_fetch_object($sql_article)){
        // Arcticle als Objekte
        $article[] = new Article($row->number,
                               $row->name,
                               $row->preis,
                               $row->Menge
                               $row->ziel);
}
Da es um den Versand geht, hat jeder Artikel ein Ziel (vlt. ist hier auch schon ein Denkfehler).
Jedenfalls würde mich nun interessieren wie groß die Summe der Mengen ist mit dem Ziel "Hamburg".

article[0]->Ziel = Hamburg
article[0]->Menge = 5
article[1]->Ziel = Hamburg
article[1]->Menge = 7

Ergebnis = 12
Doch da ich es in ein Array gepackt habe, wären dafür unnötig viele Schleifendurchläufe notwendig. Aber vlt. bin ich auch zu tief in die Datenbankorientierte Denkweise verankert.

Hoffe jemand kann mir einen Denkanstoß geben.
Wäre dankbar :)
 
Hi,

warum unnötig viele Schleifendurchgänge?

PHP:
$sum = 0;
foreach($article as $current) {
  if($current->ziel == "Hamburg")
    $sum += $current->Menge;
}
echo $sum;

Alternativ könntest du statt mit den Objekten direkt auf der Datenbank arbeiten und dir das gewünschte Ergebnis so holen:
SQL:
SELECT SUM(`Menge`) AS Summe FROM `tabelle` WHERE `Ziel` = 'Hamburg';

Gruß
BK
 
Zuletzt bearbeitet von einem Moderator:
Danke, stimmt, der Verweis auf das Objekt ist auf diese Weise ja bereits gewährleistet.
Also ist mein Denkansatz doch nicht so falsch, aber je Komplexer es wird desto mehr wirkt es so, gut muss ich mich weiter einarbeiten.

Das mit der Datenbank ist mir bewusst und sieht mir mich immer noch einfacher und klarer aus, doch leider bekomme ich mein Hauptproblem damit nicht mehr gelöst :)

Aber gibt es nicht eine Möglichkeit einen Objekt handler zu basteln?
Sprich ein zusätzliche Klasse, welches in sich die einzelnen Objekte erzeugt? Dann kann ich dort doch Methoden implementieren.
Gibt es dazu eine schicke Anleitung?
 
Zuletzt bearbeitet:
Es gibt verschiedene Ansätze.
Mein Favorit:
Eine Klasse die als Behälter der anderen Objekte dient. Diese kannst du als Ableitung von ArrayObject machen, dann kannst du diese problemlos wieder als Array verwenden.
Du kannst im gegensatz zu einem normalen Array den offsetSet abfangen und so sicherstellen dass nur Objekten der richtigen Klasse angefügt werden.
Zudem kannst du das ganze Laden des Arrays aus der DB auch bequem da reinpacken. Ausserhalb dieser Klasse interesseirt es nicht woher die Daten kommen.
Auch Funktionen wie sum() oder Filterfunktionen können eingebaut werden


Kleines beispiel.

PHP:
<?php 
//Definieren eines Items, Nodes, Token oder wie auch immer
class Item{
    public function __construct($key, $value){
        $this->key = $key;
        $this->value = $value;
    }
}

//Die eigentltiche Liste
class ItemList extends ArrayObject{
    
    /**
     * Lädt den Array anhand der Datenbank
     */
    public function loadFromDatabase(){
        //TODO: Laden der Daten aus der DB. Also das ganze SELECT-Geschmiss
        $sql = "SELECT * FROM test";
        $result = mysql_query($sql);
        while($row = mysql_fetch_array($result)){
            $this[] = new Item($row['key'], $row['value']);
        }
    }
    
    /**
     * Erstell die Summe aller Values der Items
     * @return  Number
     */
    public function sum(){
        $sum = 0;
        foreach ($this AS $item){
            $sum += $item->value;
        }
        return $sum;
    }
    
    /**
     * Filtern nach Key
     * @param   String        Key
     * @return  ItemList
     */
    public function getfilteredCopyByKey($key){
        return new ItemList(array_filter(parent::getArrayCopy(), create_function('$item', "return \$item->key == '{$key}';")));
    }
    
    //Abfangen das wirklich nur Item-Instanzen hinzugefügt werden
    public function offsetSet($offset, $item){
        if(!is_a($item, 'Item')){
            //TODO: Fehler generieren
            echo "\$item ist kein objekt vom typ Item<br />\n";
            echo "Value: {$item}<br />\n";        
        }else{
            parent::offsetSet($offset, $item);
        }
    }
}
?>

Und nun einige Beispiel der Anwendung
PHP:
<?php
//Und nun ienige Anwendungsbeispiele

$iList = new ItemList();

//Items aus der DB laden
$iList->loadFromDatabase();

//Versuch einen Wert mit einem nicht Item-Objekt zu setzen
$iList[] = "Fehler Test 1";

//Gültige Werte hinzufügen
$iList[] = new Item('a', 1);
$iList[] = new Item('a', 2);
$iList[] = new Item('b', 4);
$iList[] = new Item('a', 7);

//Versuch den Wert mit Index 1 mit einem nicht Item-Objekt zu überschreiben
$iList[1] = "Fehler Test 2";

//Versuch über append() einen nicht Item-Objekt zu überschreiben
$iList->append("Fehler Test 3");

//Die Summe Aller values
var_dump($iList->sum());

//Beispiel mit Filtern mit array_filter
$iListA = new ItemList(array_filter((array) $iList, create_function('$item', 'return $item->key == "a";')));

// Die Summe der gefilternten Values
var_dump($iListA->sum());

//Ausgabe aller gefiltertne Elemente
foreach($iListA as $item){
    var_dump($item);
}

//Beispiel zum Filtern mit eingebauten filter
$iListB = $iList->getfilteredCopyByKey('b');
var_dump($iListB->sum());
?>

Ausgabe (ohne die Daten aus der DB...)
Code:
$item ist kein objekt vom typ Item<br />
Value: Fehler Test 1<br />
$item ist kein objekt vom typ Item<br />
Value: Fehler Test 2<br />
$item ist kein objekt vom typ Item<br />
Value: Fehler Test 3<br />

-- Summe aller values
int(14)

-- Summe aller values der geifilterten Liste nach A
int(10)
-- Deren Einträge...
object(Item)#2 (2) {
  ["key"]=>
  string(1) "a"
  ["value"]=>
  int(1)
}
object(Item)#3 (2) {
  ["key"]=>
  string(1) "a"
  ["value"]=>
  int(2)
}
object(Item)#5 (2) {
  ["key"]=>
  string(1) "a"
  ["value"]=>
  int(7)
}

-- Summe aller values der geifilterten Liste nach B
int(4)


Ein weiteres Besipeil für erweitertes ArrayObject
PHP Extended ArrayObject
 
Zurück