PHP OOP Objekte aus DB laden

  • Themenstarter Themenstarter ByeBye 154279
  • Beginndatum Beginndatum
B

ByeBye 154279

Hallo,


ich bräuchte da mal bitte einen kleinen Denkanstoß ;)

Ausgangslage:
Ich habe eine Datenbank mit Werten.
Und eine Singleton-Klasse "Verwaltung"

Aus der Datenbank instanziere ich Objekte der Klasse A, die ich dem Objekt "meineVerwaltung" zuweise.
Dies geschieht im Konstruktor.
D.H. alle Daten werden ohne Filtermöglichkeit ins Objekt "meineVerwaltung" geladen.

Um meine Daten zu filtern , verwende ich array_filter.
Jedoch könnte ich mir aufgrund der hohen Datenlagen/vielen Daten vorstellen, dass
dies nicht performance schonend ist.

Welche Möglichkeiten habe ich vorweg schon einen Filter einzubauen?

Soll ich in der Klasse Verwaltung
eine Funktion bereitstellen "getDaten($Filter)"
und dann die Objekte zurückgeben?
Dann müsste ich aber jedesmal das Array mit den Objekten der Klasse A "neuschreiben" oder soll ich es temporär machen?

Danke im Voraus :)

bo
 
In solchen Fällen mache ich die Classe Verwaltung meistens als Ableitung von ArrayObject.
Man kann da von Aussen zugreiffen wie auf einen Array. Man kann eigene Filter einbauen etc.

Hab hier mal einige Beispiele dazu zusammengestellt:
PHP:
<?php 
class A{
    private $value;
    public function __construct($value){$this->value = $value;}
    public function getValue(){return $this->value;}
}

class Verwaltung extends ArrayObject{
    /** $array ist hier nur ein Beispiel. Dieser Array wird später aus der DB geladen */
    public function __construct($array, $filter = false){
        if (is_array($filter)) $array = self::multiFilter($array, $filter);
        else if ($filter) $array = self::singleFilter($array, $filter);        
        parent::__construct($array, ArrayObject::ARRAY_AS_PROPS);
    }
    /** Eingebauter Filter für ein Filterstring */
    public function filterByFilterString($filterString){
        return self::singleFilter($this, $filterString); 
    }
    /** Eingebauter Filter für ein Value */
    public function filterBySingleValue($value){
        return self::multiFilter($this, $value); 
    }
    /** Eingebauter Filter für mehrere Values */
    public function filterByArray($valueArray){
        return self::multiFilter($this, $valueArray); 
    }
    private static function singleFilter($arrayA, $filterString){
        return array_filter(self::convertToArray($arrayA), create_function('$obj', $filterString));
    }
    private static function multiFilter($arrayA, $valueArray){
        return array_uintersect(self::convertToArray($arrayA), self::convertToArray($valueArray), 
            create_function('$a, $b', 
                '$a = is_object($a)? $a->getValue(): $a; 
                $b = is_object($b)? $b->getValue(): $b;
                return strcasecmp($a." ", $b." ");')
        );
    }
    private static function convertToArray($variant){
        if ($variant instanceof ArrayObject) return $variant->getArrayCopy();
        elseif (is_array($variant)) return $variant;
        elseif ($variant instanceof A) return array($variant);
        else return array($variant);
    }   
}

$testDaten = array('k1' => new A(11), 'k2'=>new A(22), 'k3'=>new A(33));
//Construct ohne Datenfilter
$v = new Verwaltung($testDaten);
//Ausgabe aller A
echo "<hr />Ausgabe aller A:<br />";
var_dump($v);
//Ausgabe als Property
echo "<hr />Ausgabe als Property:<br />";
var_dump($v->k2);
//Ausgabe über Index
echo "<hr />Ausgabe über Index:<br />";
var_dump($v['k1']);
//Ausgabe über array_filter
echo "<hr />Ausgabe über array_filter:<br />";
var_dump(array_filter($v->getArrayCopy(), create_function('$obj', 'return $obj->getValue()==22 || $obj->getValue() ==33;')));

echo "<hr />Eingebauten filterByFilterString nutzen:<br />";
var_dump($v->filterByFilterString('return $obj->getValue()==22 || $obj->getValue() ==33;'));

echo "<hr />Eingebauten filterBySingleValue nutzen:<br />";
var_dump($v->filterBySingleValue(11));

echo "<hr />Eingebauten filter2 nutzen:<br />";
var_dump($v->filterByArray(array(11,33)));

//Construct mit Datenfilter
$v = new Verwaltung($testDaten, 'return $obj->getValue()==11;');
echo "<hr />Construct mit Datenfilter:<br />";
var_dump($v);

//Construct mit Datenfilter
$v = new Verwaltung($testDaten, array(11, 22));
echo "<hr />Construct mit Mehrfachdatenfilter:<br />";
var_dump($v);
?>
 
Ich weiß jetzt nicht genau wie dein Code aussieht, aber performanter wäre natürlich schon via SQL Query nur die gewünschten Daten zu selektieren.
Um das ganze dann dynamisch zu machen, könntest du kleine Filterklassen schreiben, die den richtigen Query enthalten um die benötigten Daten zu holen:

PHP:
Interface Datenfilter
{
  function getQuery();
}

class DataFilterDatum implements Datenfilter
{
  function __construct($datumVon, $datumBis)
  {
   $this->datumVon = $datumVon;
   $this->datumBis = $datumBis;

  }
  function getQuery()
  {
    //Baue query zusammen und gib ihn zurück
  }

}
Diese Filter könntest du dann der Klasse mitgeben (zB via function addFilter(DatenFilter $f), die für das Holen aus der DB verantwortlich ist.


Ich könnte mir vorstellen, dass man auch mehrere Filter(Queries) so verketten kann dass am Ende nur noch die gewünschten Reihen zurückkommen. Aber da müsste man dann mal tiefer drüber nachdenken wie und ob das möglich ist.
 
Diese Filter könntest du dann der Klasse mitgeben (zB via function addFilter(DatenFilter $f), die für das Holen aus der DB verantwortlich ist.


Hey,

kannst du mir mal ein ganz einfaches Beispiel dafür geben?
Bei diesem Thema .... "Addons" zu einem Objekt/Klasse zuzuweisen, habe ich bisher kaum/keine Erfahrung.

Danke


bo
 
Klar :)


Stell dir vor du hast eine Klasse Bibliothek die alle Bücher zu als Array zurück gibt wenn du die Methode getBuecher(); aufrufst:

PHP:
  class Bibliothek
  {
    private $filters = null;

    function __construct()
    {
    }

    function getBuecher()
    {
      if ($this->filter == null)
      {
        //benutze gar keinen filter und benutze den standard query um alle bücher zu holen
        $query = "SELECT * FROM bibliothek";
      } else
      {
        //wenn Filter verfügbar ist, benutzen!
        $query = $this->filter->getQuery();
      }

      $result = mysql_query($query);
      //daten weiterverarbeiten und zurückgeben

    }
    function setFilter(Datenfilter $f)
    {
      $this->filter =$f;
    }
  }

  interface Datenfilter 
  {
    function getQuery();
  }

  class BuecherAusgeliehen implements Datenfilter
  {
    function __construct()
    {
    }
    function getQuery()
    {
      $query = "SELECT * FROM bibliothek WHERE ausgeliehen = 1";
      return $query;
    }
  }


  class NurSachbuecher implements Datenfilter
  {
    function __construct()
    {
    }
    function getQuery()
    {
      $query = "SELECT * FROM bibliothek WHERE buchtyp = 'sachbuch'";
      return $query;
    }
  }


  //so benutzt man dann die Klassen
  $bib = new Bibliothek();
  $alleBuecher = $bib->getBuecher(); //Würde alle Bücher zurückgeben

  //jetzt filter setzen
  $nurausgeliehenFilter = new BuecherAusgeliehen();
  $bib->setFilter($nurausgeliehenFilter);
  $buecherAusgeliehenResult = $bib->getBuecher(); //gibt nur ausgeliehene Bücher zurück
  
  //anderen Filter setzen
  $nurSachbuecherFilter = new NurSachbuecher();
  $bib->setFilter($nurSachbuecherFilter);
  $res = $bib->getBuecher();  //gibt nur Sachbücher zurück
Dieses Beispiel arbeit nur mit einem Filter, aber ich hoffe das Prinzip habe ich damit gezeigt!
 
Zurück