Ankündigung

Einklappen
Keine Ankündigung bisher.

Objekt als Attribut eines weiteren Objekts. Wie ordentlich auslesen?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Objekt als Attribut eines weiteren Objekts. Wie ordentlich auslesen?

    Moin,

    die Situation, dass man ein Objekt einer Eigenschaft eines weiteren Objekts zuweist, tritt natürlich häufig ein und daher stellt sich mir oft die Frage nach dem richtigen Design.

    Als Beispiel habe ich eine Klasse Clubs und eine Klasse Events gewählt. In einem Club können beliebig viele Events stattfinden. Ich möchte die Events also in einer Eigenschaft der Klasse Club ablegen können, um die Events unter dem jeweiligen Club auflisten zu können.

    club.class.php
    PHP-Code:
    <?php
    class Club {
      private 
    $id;

      private 
    $name;

      
    // ...

      
    private $events = array(); // Objekte vom Typ Event

      
    public function __construct($id$name) {
        
    $this->id $id;
        
    $this->name $name;
      }

      public function 
    getId() {
        return 
    $this->id;
      }

      
    // ...

      
    public function addEvent(Event $event) {
        
    $this->events[] = $event;
      }

      public function 
    addEvents(array $events) {
        foreach (
    $events as $event) {
          if (
    $event instanceof Event) {
            
    $this->addEvent($event);
          }
        }
      }

      public function 
    getEvents() {
        return 
    $this->events;
      }
    }
    event.class.php
    PHP-Code:
    class Event {
      private 
    $id;  

      private 
    $name;

      
    // private $clubID;

      
    private $club// Objekt vom Typ Club

      
    public function __construct($id$name) {
        
    $this->id $id;
        
    $this->name $name;
      }

      public function 
    getId() {
        return 
    $this->id;
      }

      
    // ...

      
    public function setClub(Club $club) {
        
    $this->club $club;
      }

      public function 
    getClub() {
        return 
    $this->club;
      }

    Der Ablauf sieht momentan so aus, dass ich mir über die Klasse Club_Manager sämtliche Clubs und dann über den Event_Manager die zugehörigen Events auslese und den Clubs hinzufüge.

    PHP-Code:
    $clubs $club_manager->getClubs();

    foreach (
    $clubs as $club) {
      
    $events $event_manager->getEventsByClubId($club->getId());
      
    $club->addEvents($events);

    Jedoch möchte ich für eine Art Kalenderansicht auch eine Auflistung der Events - nicht nach Clubs sortiert, sondern nach dem Datum - ausgeben können.

    Dazu lese ich mir dann zuerst die Events aus und hole mir dann den zugehörigen Club, da dieser als Information zum jeweiligen Event angezeigt werden soll.

    PHP-Code:
    $events$event_manager->getEvents();

    foreach (
    $events as $event) {
      
    $club $club_manager->getClubById($event_manager->getClubId($event->getId()));
      
    $event->addClub($club);

    Man sieht daran schon, dass alleine das Auslesen des Clubs für das jeweilige Event schon ziemlich umständlich - über 2 Manager - passiert. Dies ist der Fall, da die Events ja über eine Club-ID in der Datenbank dem jeweiligen Club zugeordnet sind, die Clubs aber nicht den Events, was auch sinnfrei wäre.

    Zuvor hatte ich es noch so gehandhabt, dass ich beim Erzeugen des Eventobjekts die Club-ID gleich mit ausgelesen habe und als Eigenschaft dem Event hinzugefügt habe. Dann würde ich mir den Weg über den Event_Manager sparen, die Club-ID zum Event nachträglich auslesen zu müssen.

    Allerdings brauche ich die Club-ID als Eigenschaft dann erstens nur dafür und zweitens nur so lange, bis ich dann schließlich den Club ausgelesen und als Eigenschaft dem Event hinzugefügt habe. Denn dann kann ich die ID ja wieder über den Club selbst abrufen.

    Viel Text für eine kurze Frage: Was haltet ihr davon? Ist mein aktueller Ansatz so vernünftig?

    Andere Vorschläge und Tipps, wie man es richtig macht, werden gerne genommen.

    Viel Spaß
    [URL]http://hallophp.de[/URL]

  • #2
    Also ich muss sagen, ich finde die Strukturierung der Akteure, also Club, Event, Club-Manager und Event-Manager, recht gut. Du hast dadurch eine klare Aufteilung in den Klassen, jede macht seine Arbeit und Fehler wären einfach zu analysieren. Allerdings würde ich bei der Ermittlung des Clubs, eines Events anders vorgehen.

    PHP-Code:
    $club $club_manager->getClubById($event->getClub()->getId()); 
    Sowas in der Art.

    Kommentar


    • #3
      Mach das doch so, dass beim Auslesen des Events aus der Datenbank die ClubId mit ausgelesen wird. Wenn du dann anschließend die Daten aus der Datenbank in ein neues Event Objekt verfrachtest, kannst du ja bei der setClubId bzw setClub Methode gleich das passende Club Objekt vom ClubManager holen und als Eigenschaft des Event Objekts setzen.

      Kommentar


      • #4
        @Tidus
        Das ist so leider nicht möglich, da der Club an dieser Stelle ja erst dem Event hinzugefügt wird. Diesen finde ich zu diesem Zeitpunkt noch nicht unter der Eigenschaft $club in der Klasse Event und kann ihn daher auch nicht über
        Code:
        $event->getClub()
        auslesen, sondern muss zum Manager greifen, um die Club-ID zum Event auszulesen.

        Zitat von peaceman
        Mach das doch so, dass beim Auslesen des Events aus der Datenbank die ClubId mit ausgelesen wird.
        Ja, so habe ich es zuvor gemacht. Allerdings habe ich die Club-ID dann als Eigenschaft im Event-Objekt abgelegt, um damit dann später den passenden Club auslesen zu können.

        Nach deiner Idee müsste ich dann der Funktion getEvents() im Event_Manager auch noch eine Instanz des Club_Managers übergeben, damit ich mit diesem anhand der ermittelten ID aus der Datenbank den Club auslesen und dann direkt dem Eventobjekt zuweisen kann.

        Das sähe dann so aus:
        Code:
        $events = $event_manager->getEvents($club_manager);
        Alle Clubs werden dann direkt hinzugefügt und ich bräuchte auch keine weitere Schleife.

        Das ist natürlich eine weitere Möglichkeit, darüber habe ich so noch gar nicht nachgedacht. Die Manager selbst hatten bei mir bisher nichts miteinander zu tun. *grübel*

        Mir fällt auch nichts ein, was dagegen sprechen würde. Werde ich wohl so umsetzen, wenn nicht noch jemand dazwischen haut.

        Danke euch für den Schubs.
        [URL]http://hallophp.de[/URL]

        Kommentar


        • #5
          Mit Managern mache ich das auch immer, sehr schön!

          Nur: du führst jetzt in einer Schleife Datenbankabfragen durch, das ist schlecht.

          PHP-Code:
          <?php
          $events
          $event_manager->getEvents();
          $clubs $club_manager->getClubs($events->getClubIds());

          foreach (
          $events as $event) {
            
          $club $clubs->getClub($event->getClubId());
            
          $event->addClub($club);
          }  
          ?>
          Davon ausgehend, dass du Listen von Clubs/Events auch in einer eigenen Klasse ablegst.
          PHP-Code:
          <?php
          class Event_Array extends AIS_Util_Iterator
          {
            public function 
          __construct() {
              
          parent::__construct("Event");
            }
            public function 
          getClubIds() {
              
          $clubIds = array();
              foreach (
          $this->_elements as $event) {
                
          $clubIds[] = $event->getClubId();
              }
              
          $clubIds array_unique($clubIds);
              
          $clubIds array_values($clubIds);
              return 
          $clubIds;
            }
          }

          class 
          AIS_Util_Iterator implements IteratorCountable
          {
              protected 
          $_acceptClass;
              protected 
          $_elements = array();

              public function 
          __construct($acceptClass)
              {
                  
          $this->_acceptClass $acceptClass;
              }

              public function 
          __clone()
              {
                  foreach (
          $this->_elements as $i => $element) {
                      
          $this->_elements[$i] = clone $element;
                  }
              }

              public function 
          count()
              {
                  return 
          count($this->_elements);
              }

              public function 
          current()
              {
                  return 
          current($this->_elements);
              }

              public function 
          next()
              {
                  return 
          next($this->_elements);
              }

              public function 
          previous()
              {
                  return 
          previous($this->_elements);
              }

              public function 
          key()
              {
                  return 
          key($this->_elements);
              }

              public function 
          valid()
              {
                  return (bool)
          current($this->_elements);
              }

              public function 
          rewind()
              {
                  return 
          reset($this->_elements);
              }

              public function 
          reset()
              {
                  
          $this->_elements = array();
              }

              public function 
          push($object)
              {
                  
          $this->_check($object);
                  return 
          $this->_elements[] = $object;
              }

              public function 
          pop()
              {
                  return 
          array_pop($this->_elements);
              }

              public function 
          shift()
              {
                  return 
          array_shift($this->_elements);
              }

              public function 
          unshift($object)
              {
                  
          $this->_check($object);
                  return 
          array_unshift($this->_elements$object);
              }

              public function 
          isFirst()
              {
                  
          $hasPrevious prev($this->_elements);
                  if (
          $hasPrevious) {
                      
          next($this->_elements);
                  } else {
                      
          reset($this->_elements);
                  }
                  return !
          $hasPrevious;
              }

              public function 
          isLast()
              {
                  
          $hasNext next($this->_elements);
                  if (
          $hasNext) {
                      
          prev($this->_elements);
                  } else {
                      
          end($this->_elements);
                  }
                  return !
          $hasNext;
              }

              public function 
          shuffle()
              {
                  
          shuffle($this->_elements);
              }

              protected function 
          _check($object)
              {
                  if (!
          $object instanceof $this->_acceptClass) {
                      throw new 
          InvalidArgumentException("given argument is not an object of type " $this->_acceptClass);
                  }
              }
          }
          ?>
          Edit: Die Event_Array Klasse kannst du dann auch zum Sortieren benutzen:
          $event_array->sortByDate();
          "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

          Kommentar


          • #6
            Mit Managern mache ich das auch immer, sehr schön!
            Den Tipp hattest du mir vor einiger Zeit mal gegeben

            Nun, meine Liste würde ich wohl Array nennen , allerdings hat es nicht die Vorteile, die du offenbar mit deiner Struktur erreichst.

            Was du da machst, scheint mir soweit klar zu sein. Deine Klasse Event hat also auch eine Eigenschaft allein für die ClubID, dafür fehlt die Eigenschaft für den Club selbst, richtig?
            Stattdessen hast du zwei Listen für die Clubs und die Events und suchst dir mit den Event-IDs die Clubs aus der Liste der Clubs raus.

            Von wo aus schiebst du denn die Objekte in die Klasse *_Array? Dort mache ich dann eine neue Liste auf und schiebe die Instanzen rein.

            Ich glaube, dass muss ich auch mal umsetzen

            Dafür muss ich zwar einiges umbauen, aber es scheint die Mühe wert zu sein.
            [URL]http://hallophp.de[/URL]

            Kommentar


            • #7
              Naja Event hat schon eine $club-Eigenschaft, $event->getClub() soll ja schon möglich sein. Nur ist dieser Wert eben nicht immer verfügbar.

              Stell dir vor du fügst jedem Event immer Clubs hinzu und jedem Club immer seine Events. Dann bist du (ohne Cache sowieso) in einem Deadlock bzw. lädst die gesamte Datenbank Also brauchst du irgendwann einen Cut der sagt, dass ein Objekt nur "light" geladen wird, sprich ohne Fremdschlüsselbeziehungen aufzulösen.

              Von wo aus schiebst du denn die Objekte in die Klasse *_Array?
              Vom Manager.

              PHP-Code:
              <?php
              class Club_Manager {
                
              /**
                 * @return Club_array
                 */
                
              public function getClubs($light false) {
                  
              // sql bla
                  
              $clubs = new Club_Array();
                  foreach (
              $sqlFetch as $clubData) {
                    
              $club = new Club();
                    
              $club->import($clubData);
                    
              $clubs->push($club);
                  }
                  if (!
              $light && $clubs->hasEvents()) {
                    
              $eventManager $this->_getEventManager();
                    
              $eventManager->setFiltersMultiple($clubs->getEventIds());
                    
              $events $eventManager->getEvents(true); // light
                    
              foreach ($clubs as $club) {
                      
              $club->addEvents($event->getByClubId($club->getId()));
                    }
                  }
                  return 
              $clubs;
                }
              }
              ?>
              So in etwa sieht das bei mir aus. Nur musst du dann eben im Code wissen, dass deine Events nur "light" sind und entsprechend getClub() (also z.B. $club->getEvents()->getFirst()->getClub()) null oder eine Exception zurückwirft.
              "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

              Kommentar


              • #8
                Zitat von Chriz Beitrag anzeigen
                Naja Event hat schon eine $club-Eigenschaft, $event->getClub() soll ja schon möglich sein. Nur ist dieser Wert eben nicht immer verfügbar.
                Gut, alles klar, das versteht sich.

                Danke für das Codebeispiel, da muss ich mir erstmal gut überlegen, wie ich meinen Code jetzt am besten umbaue. Du gehst das Ganze doch noch sehr anders an, als es im Moment bei mir aussieht.

                Na, es wird sich schon ein Weg finden.

                Danke für die Hilfe.
                [URL]http://hallophp.de[/URL]

                Kommentar


                • #9
                  Wieso, wie sieht dein Code innen denn aus? Die Schnittstellen sind doch schon ähnlich oder?
                  "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

                  Kommentar


                  • #10
                    Zitat von Chriz Beitrag anzeigen
                    So in etwa sieht das bei mir aus. Nur musst du dann eben im Code wissen, dass deine Events nur "light" sind und entsprechend getClub() (also z.B. $club->getEvents()->getFirst()->getClub()) null oder eine Exception zurückwirft.
                    Das könnte man ja so machen, dass der Club erst bei Bedarf nachgeladen wird.

                    Kommentar


                    • #11
                      Von wem? Von Event selbst, dann ist das Objekt nicht mehr unabhängig. Außerdem wenn du Listen durchläufst führst du wieder Datenbankabfragen in Schleifen aus.
                      "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

                      Kommentar


                      • #12
                        Ja, natürlich sind die ähnlich. Es wird auch kein Problem sein, auf deinen AIS_Util_Iterator umzustellen und Listen zu nutzen. Auch die Implementierung der Funktionen anzupassen, dürfte nichts kaputtmachen.

                        Was heißt anders? Einfach fortgeschrittener. Meine Datenbankklasse gehört in die Tonne bzw. generalüberholt und ich sollte auch darüber nachdenken, die Objekte ohne Parameter zu erzeugen, sondern evtl. auch eine import-Schnittstelle zu definieren. Bei User-Instanzen muss man ja auch mal einen Gast erzeugen, dessen Daten nicht aus der Datenbank kommen und er daher eigentlich nur ein leeres Objekt ist.

                        Insgesamt gibt es eben viel zu tun und es geht dabei leider nicht nur um diese 2 Klassen.

                        Trotzdem bin ich froh über die Tipps. Bringen mich weiter.

                        Gruß
                        [URL]http://hallophp.de[/URL]

                        Kommentar


                        • #13
                          Event würde dann beim ClubManager nach einem Club mit der entsprechenden Id fragen und daraufhin das passende Club Objekt geliefert bekommen. Inwiefern wäre das Event Objekt dann nicht mehr unabhängig?

                          Kommentar


                          • #14
                            Event würde dann beim ClubManager nach einem Club mit der entsprechenden Id fragen
                            Genau, damit muss sich das Objekt selbst um die Beschaffung der benötigten Instanz kümmern und damit hast du eine Abhängigkeit. Es muss wissen wie und woher es den Club bekommt.
                            Wenn es aber direkt über den Manager läuft, wird der entsprechende Club ja sofort geladen (oder auch nicht bei $light !== false) und dem Event injiziert (Dependency Injection).
                            [URL]http://hallophp.de[/URL]

                            Kommentar


                            • #15
                              Man bräuchte noch einen Manager Manager
                              "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

                              Kommentar

                              Lädt...
                              X