[PHP5] Start mit OOP / Frage zu Klassenstruktur

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

  • [PHP5] Start mit OOP / Frage zu Klassenstruktur

    Hallo,

    ich habe vor, meine private Seite neu zu machen, und zwar objektorientierter, also mit Klassen.

    Im Moment gibt es einfach nur eine riesige Sammlung an Funktionen, und das soll sich jetzt ändern, bzw. es soll strukturierter werden.
    Deswegen wende ich mich mal an die Allgemeinheit.

    Problem: was packe ich in welche Klasse?

    Die Webseite ist rein privat mit Authenitifizierung/Login.
    Hauptbestandteil: ein Bundesliga-Tippspiel.
    Sonstiges: kleines Forum, Fotos.

    Ich baue die Klasse user. Da rein kommen Eigenschaften wie die User-ID, der Username, der richtige Name etc.

    Tippspieler benötigen außerdem Eigenschaften wie z.B. aktueller Tabellenplatz oder aktuelle Form, aber auch z.B. Funktionen die überprüfen ob der aktuelle Spieltag schon getippt wurde, Verabeitung der Tipps etc.

    Frage: würdet ihr die ganzen Tippspiel-Klamotten mit in die User-Klasse packen, oder eine sep. Klasse verwenden?

    Ich tendiere ja zu zwei Klassen...


    Mein viel größeres Problem:
    ich verwende das PEAR-Package "MDB2" für alle Datenbankoperationen.

    Dabei wird anfangs ein Objekt erzeugt, welches die Verbindung zur Datenbank aufbaut und z.B. Abfragen ausführen kann.

    Darauf muss ich in verschiedenen Klassen bei verschiedenen Funktionen zurückgreifen können.
    Im Moment binde ich es per "global" in die Funktionen ein - gibt es da keinen besseren Weg?

    Gruß,
    Dennis

  • #2
    Zu der Frage bezüglich des Datenbank-Objekts:
    PHP-Code:
    class IrgendeineKlasse
    {
        protected 
    $_database null;

        public function 
    __construct(MDB2 $database_object)
        {
            
    $this->_database $database_object;
        }

    Ist PEARs MDB2 eigentlich als Singleton implementiert? Falls ja, kannst du auch global über MDB2::getInstance() (oder ähnliches) darauf zugreifen und kannst dir die Übergabe an den Klassenkonstruktor sparen. Sauberer ist allerdings ersteres.


    Grüße
    Zuletzt geändert von Griecherus; 21.11.2008, 21:36.
    Nieder mit der Camel Case-Konvention

    Kommentar


    • #3
      Original geschrieben von Griecherus
      Sauberer ist allerdings ersteres.
      Geschmackssache. Ich finde letzteres sauberer.

      Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

      bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
      Wie man Fragen richtig stellt

      Kommentar


      • #4
        Original geschrieben von ghostgambler
        Geschmackssache. Ich finde letzteres sauberer.
        Inwiefern?
        Nieder mit der Camel Case-Konvention

        Kommentar


        • #5
          Geschmackssache.
          Dem kann ich mich nur anschließen. Am geschicktesten ist sogar noch, beides zu ermöglichen, zum Beispiel auf folgendem Wege:
          PHP-Code:
          class Foo {
              private 
          $_db=NULL;
              public function 
          __construct(DB $db=NULL) {
                  if(
          $db!==NULL) {
                       
          $this->setDB($db);
                  }
              }
              public function 
          getDB() {
                  if(
          $this->_db===NULL) {
                      
          $this->_db=Registry::get('DB');
                  }
                  return 
          $this->_db;
              }
              public function 
          setDB(DB $db) {
                  
          $this->_db=$db;
              }

          So kannst du die zu verwendende Instanz von außen konfigurieren (über die Registry) oder direkt an der Instanz setzen. Erlaubt einerseits die generische Erstellung zum Beispiel durch eine Factory und ist andererseits nicht total von der Konfiguration abhängig.

          Kommentar


          • #6
            Guten Morgen,

            vielen Dank für die Antworten!!!

            Scheint mir eine Lösung zu sein, auf die ich auch hätte selber kommen können...
            Und trotzdem klappt es nicht.

            Folgendes (verkürzt):
            PHP-Code:
            <?php
                
            class bla{
                    
                    private 
            $mydb=null;
                    
                        function 
            set_mydb($foo){
                            
            $this->mydb=$foo;
                        }
                    
                        function 
            sql_irgendwas(){
                            
            $res $this->mydb->query('SELECT * FROM blabla');
                        }
                }
                
                
                
            $mdb2 =& MDB2::connect($dsn$options);
                
                
            $x=new bla();
                
            $x->set_mydb($mdb2);
                
                
            $x->sql_irgendwas();
            ?>
            Die letzte Zeile sorgt für eine Fehlermeldung, weil in der Funktion sql_irgendwas "$this->mdb2" nicht definiert ist.

            Warum nicht? Was mache ich falsch?

            Wenn ich die Funktion so veränder:
            PHP-Code:
                        function sql_irgendwas(){
                            
            $mydb=$this->mydb;
                            
            $res $mydb->query('SELECT * FROM blabla');
                        } 
            ...funktioniert's ...

            Versteh ich nicht...

            Edit: Danke für den Hinweis (Posting hier drunter), hab's geändert.
            Hatte das Beispiel nur zum Posten zusammengetippt, war quasi ein "Tippfehler" - Problemstellung bleibt aber gleich.
            Zuletzt geändert von Dennis79; 22.11.2008, 11:56.

            Kommentar


            • #7
              Verwechselst du nicht mydb mit mdb2?

              Kommentar


              • #8
                Du erzeugst $mdb2 als Referenz. Warum?

                Kommentar


                • #9
                  Hallo,

                  ich muss gestehen, dass ich mit der Gegenfrage von onemorenerd nix anfangen kann.

                  Der Einstieg in die Welt der Klassen gestaltet sich weiterhin schwierig. Zwar glaube ich das Werkzeug dafür mittlerweile halbwegs zu kennen, aber ich weiß es nicht richtig einzusetzen.

                  Peter (kropff) hat mir zudem geflüstert, dass das sowieso der falsche Weg sei, weil man seine SQl-Abfragen in einer Klasse zusammen hält.

                  Danach hab ich wirklich lange überlegt, wie das denn wohl machen könnte.

                  Folgender, sehr bescheidener Versuch ist dabei herum gekommen:

                  PHP-Code:
                  class dbc{
                      
                       public 
                  $mdb2;

                       public function 
                  __construct() {

                       require_once 
                  'MDB2.php';
                          
                  $dsn = array(
                              
                  'phptype'  => 'mysql',
                              
                  'username' => 'root',
                              
                  'password' => '',
                              
                  'hostspec' => 'localhost',
                              
                  'database' => 'de1180838',
                          );
                          
                  $options = array(
                              
                  'debug'       => 1,
                              
                  'portability' => MDB2_PORTABILITY_ALL,
                          );
                      
                          
                  // uses MDB2::factory() to create the instance
                          // and also attempts to connect to the host
                          
                  $mdb2 =& MDB2::connect($dsn$options);
                          
                  $this->mdb2 $mdb2;
                          if (
                  PEAR::isError($mdb2)) {
                              die(
                  $mdb2->getMessage());
                          }
                       
                       }
                       
                           public function 
                  get_user(){
                           
                  $res =& $this->mdb2->query('SELECT * FROM user_auth WHERE (user_auth.pk_user=1)');

                              return 
                  $res->fetchAll(MDB2_FETCHMODE_ASSOC);
                           }
                  }

                  class 
                  testobj{
                      private 
                  $mdb2;

                           public function 
                  __construct() {
                               
                  $this->mdb2=new dbc();
                               
                           }
                           
                           public function 
                  whois(){
                               return 
                  $this->mdb2->get_user();
                           }
                           

                  }

                  $bla=new testobj();
                  var_dump($bla->whois()); 
                  Das funktioniert sogar!

                  Aber ist das so korrekt, dass ich in der Klasse testobj die Klasse dbc aufrufe?

                  Oder wie macht man's richtig?

                  Die Funktion "get_user" muss natürlich noch allgemeiner gehalten werden. Das war jetzt nur für einen ersten Test so angelegt.


                  Warum sind Konstruktoren eigentlich public? Würde da ein "private" nicht völlig ausreichen?
                  Ich hab das jetzt nur so gemacht, weil es in vielen Beispielen auch so war...

                  Gruß,
                  Dennis

                  Kommentar


                  • #10
                    MDB2 ist ein PEAR-Paket. Das sollte mit autoloading/include_path von selbst geladen werden.

                    Die Klasse DBC ist ein Zwitter - einerseits kapselt sie deine DB-Schnittstelle (MDB2 macht auch nichts anderes), andererseits ist sie ein Datenobjekt (von außen sieht es aus, als trüge sie die Userdaten in sich).

                    Frage dich ...
                    Was willst du eigentlich machen?
                    Welche Entitäten sind daran beteiligt?
                    Wie agieren die Entitäten miteinander?
                    Was ist das Ergebnis?


                    Wenn Konstruktoren private wären, könnte man sie von außen nicht aufrufen - das ist ja der Sinn von private. Wenn man den Konstruktor von außen nicht aufrufen kann, wie erzeugt man dann ein Objekt?

                    Kommentar


                    • #11
                      Hi,

                      das "require_once 'MDB2.php';" steht da nur mit drin, weil ich eine einfache Testdatei erstellt habe.

                      Ich hoffe, Du meintest das überhaupt.
                      Jedenfalls kommt diese Zeile später nicht mit in die Klasse.

                      Deine Fragen habe ich mir alle schon gestellt.
                      Auf 2 & 3 zu antworten, würde wahrscheinlich zu weit gehen.
                      Es handelt sich halt um ein Tippspiel.
                      Es gibt User. Diese können Tippspieler sein. Tippspieler sind aktiv oder inaktiv, haben einen Platz in der ewigen Rangliste und bei aktivem Status auch einen Platz in der aktuellen Tabelle, haben den nächsten Spieltag schon getippt oder nicht, usw usw.
                      Saisons, Tipps, Rangliste etc. sind natürlich auch schon wieder eigenständige Objekte.
                      Kurz: es würde zu weit gehen.

                      Frage 1 & 4 hängen irgendwie zusammen.

                      Also es gibt da dies
                      e private Seite - meine private Seite.
                      Der aktuelle Stand ist der, dass z.B. Code & Content nicht sauber voneinander getrennt sind. Teilweise noch schlicht runtergeschrieben, größtenteils aber in Funktionen "ausgelagert".

                      Was ich vor allem machen will, ist den Umgang mit Klassen zu lernen.
                      Deswegen nehme ich mir vor: $private_homepage = new homepage();

                      Die reine Trennung von PHP und HTML hab ich eigentlich schon gesichert (Template Engine).
                      Jetzt möchte ich aber auch eine ordentliche PHP-Struktur haben, und dafür erscheinen mir Klassen als sinnvoll.
                      Außerdem erspart es auf lange Sicht viel Schreibarbeit.

                      Und da ich mir "keinen abbrechen" will, und nicht am Ende feststellen möchte, dass man alles auch viel einfacher/besser machen könnte, frag ich lieber gleich am Anfang nach.

                      Gruß,
                      Dennis

                      Kommentar


                      • #12
                        Private Konstruktoren machen bei Singletons durchaus Sinn! Wobei sich im Gegenzug aber auch sofort die Frage auftut, ob Singletons an sich überhaupt sinnvoll sind.

                        Und wofür sind die & da?
                        Ich denke, das ist doch PHP5 Code!

                        Schau mal bei Google nach "OOP Design Pattern".
                        Insbesondere das "Dependency Injection Pattern" erlaubt eine lose Bindung der Objekte.
                        Zuletzt geändert von combie; 24.11.2008, 21:30.
                        Wir werden alle sterben

                        Kommentar


                        • #13
                          Original geschrieben von combie
                          Wobei sich im Gegenzug aber auch sofort die Frage auftut, ob Singletons an sich überhaupt sinnvoll sind.
                          Wie willst Du sonst sicherstellen, dass ein Objekt dem Highlander-Prinzip gehorcht?

                          Kommentar


                          • #14
                            Ja genau!!
                            Wozu soll das auch gut sein?

                            Warum die Notwendigkeit "es darf nur einen geben" in der Klasse selber festlegen?
                            Das wäre Unsinn!

                            Irgendwann brauchst du einen 2ten Druckerport/Datenbankverbindung/Prozessor/Festplatte oder was auch immer.
                            Und dann? Die Klasse umbauen?

                            Die Singleton Eigenschaft einer Klasse ist unter PHP<5.3 nicht vererbbar. Du machst dir damit also große Teile der OOP kaputt.
                            Und das ohne wirkliche Not!

                            Nein!
                            Singleton: Obwohl ich es auch ab und an aus Bequemlichkeit nutze, halte ich es für ein anti Pattern. Fast auf gleichem Level wie globale Variablen.

                            Setze stattdessen z.B. das Registry Pattern ein. Dann bleibt die Einschränkung in der Applikation und nicht in der HelferKlasse, wo sie nichts zu suchen hat.
                            Zuletzt geändert von combie; 24.11.2008, 23:03.
                            Wir werden alle sterben

                            Kommentar


                            • #15
                              Original geschrieben von combie
                              Setze stattdessen z.B. das Registry Pattern ein. Dann bleibt die Einschränkung in der Applikation und nicht in der HelferKlasse, wo sie nichts zu suchen hat.
                              Wenn man allein an einem Projekt arbeitet, mag das ja ok sein.
                              Aber stell' Dir mal ein größeres Projekt vor, mit neuen, unerfahrenen Entwicklern, die ins Team kommen. Wie willst Du dann verhindern, das eine neue Instanz mit new() erzeugt wird?

                              Kommentar

                              Lädt...
                              X