Beiträge von Arne Drews

    Ich habe mal folgenden Workflow erstellt, den ich einschlagen würde. Hier und da mag es sicher bessere Möglichkeiten geben, aber ich wollte nun auch nicht ein ganzes Projekt erstellen. Daher soll das nur die Richtung zeigen, die aus meiner Sicht OOP nahe kommt. Datenbank-Abfragen usw. habe ich ausgelassen, was in den Kommentaren auch zu lesen ist.

    Sowohl den Workflow, als auch die Klassen habe ich nur auf das Minimum begrenzt, das für dieses Beispiel nötig war. Ich denke aber, dass relativ gut erkennbar ist, wo die Vorteile liegen.

    Hier mal der Workflow:

    Die Klassen dazu:

    Spoiler anzeigen
    Spoiler anzeigen
    Spoiler anzeigen
    Spoiler anzeigen
    Spoiler anzeigen
    Spoiler anzeigen

    Gruß Arne

    Okay. Ich habe gelesen, dass das neue PDO dies nicht mehr unterstützt.

    Finde ich auch nicht schlimm, was ist der große Vorteil der MySQLi-Variante gegenüber so etwas:

    PHP
    $sQuery = "INSERT INTO table ( column1, column2 ) VALUES ( 1, 2 );";
    $sQuery .= "UPDATE table SET column2 = 3";
    
    $oPDO->exec( $sQuery );

    Anders macht MySQLi das auch nicht, nur dass es dort eine mit multi benannte Methode ist.

    Bis hierhin gibt es keinen Vorteil einer Multi-Methode.

    Ich würde das MySQL erledigen lassen, dann braucht es auch nur eine Query.

    SQL besteht ja nicht nur aus SELECT, INSERT und UPDATE.

    Und dass PDO keine Multi-Queries kann ist auch falsch!

    Bei MySQLi wird auch nichts anderes gemacht, als die Queries in einem String zu übergeben.

    Das einzige, was MySQLi noch in der Hinterhand hat ist, dass Du die einzelnen Resultate per next_result() zur Verfügung stellt.

    Wenn Du zwei Tabellen befüllen willst, benötigst Du zwei INSERT Queries.

    Als erstes würde ich definieren, dass stadt.id_stadt und adressen.ID PRIMARY KEY und AUTO_INCREMENT sind.

    Die Tabelle stadt würde ich als erstes füllen, damit Du die InsertId bekommst und in der zweiten Query auf die Tabelle adressen zur Verfügung hast.

    Drauf achten solltest Du, dass beim Einfügen in die Tabelle stadt keine doppelten Einträge möglich sind bzw. einen bereits vorhanden Eintrag einem INSERT vorzuziehen ist.

    Naja, so schwer ist der Eigenbau ja nun auch nicht.

    HTML seitig würde ich auf verschachtelte <ul> setzen.

    Jedes <li> bekommt ein entsprechendes, klickbares Symbol je nach Ebene vorangestellt.

    Vermutlich würde man es per CSS über Pseudo-Klassen, wie :active schon hinbekommen, aber spätestens, wenn mehrere Elemente der ersten Ebene geöffnet sein dürfen, muss man an der Stelle halt auf JS gehen.

    Ich würde empfehlen, damit erst mal so zu beginnen.

    Leider verstehe auch ich Dich ganz schlecht.

    Was ich auf den ersten Blicke sehe ist, dass Du bspw. den ersten Fehler, auf den ich in #13 hinaus wollte, in #16 nicht mehr machst.

    Nun weiß ich nicht, ob Du es verstanden und den Fehler korrigiert hast oder Du einfach Deinen Code tlw. falsch postest?!

    Wie sieht es denn mit anderen Sprachen aus? Kannst Du Dich in englisch vielleicht besser ausdrücken? Dann probier das mal.

    Habt ihr euch mal durchgelesen, was PrimeNG ist? Das ist eine Library von UI Elementen für AngularJS.

    Ihr wollt nur ein kleines Element daraus haben, benötigt dazu aber die komplette Library und Angular KnowHow.

    Selber machen macht mehr Sinn.

    Stell Dir in HTML/CSS eine Vorlage zusammen, wie es statisch aussehen soll.

    Sollte CSS zum Aufklappen nicht sinnvoll ausreichen, kommt halt JS mit ran.

    Du solltest nichts persönlich nehmen, was hier geschrieben wird. Wenn wir darauf beharren, dass Du debuggen sollst oder eigentlich die meisten Sachen hättest selbst sehen sollen, meinen wir das konstruktiv, auch wenn es nicht so rüber kommen mag.

    Du kannst uns aber ruhig glauben, manche hier haben einiges an Erfahrungen und wissen, dass das am Ende den größeren Lerneffekt hat.

    Keiner meint das böse...

    ;)

    Typische Abhandlung ( was auch immer dots sind :(

    • Alle slides/dots werden in eine NodeList geladen
    • Alle slides/dots werden ausgeblendet
    • Nur der per Funktionsaufruf übergebene slide/dot wird eingeblendet

    Vom Ablauf her nichts bewegendes, hier und da für meinen Geschmack fragwürdig umgesetzt, aber kann man machen.

    Da ist zu vieles falsch.

    Was erwartest Du z.B. an dieser Stelle?

    PHP
    if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['message'])) {
                    
    } echo "<br><b><h3>*** Please enter all required fields ***</h3></b>";
    else
    {

    Mit dem angesprochenen ErrorReporting würdest Du hier schon den ersten Fehler erhalten.

    Benutzereingaben solltest Du immer filtern:

    PHP
    $name = filter_input( INPUT_POST, 'name', FILTER_SANITIZE_STRING ); 
    $email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_STRING ); 
    $message = filter_input( INPUT_POST, 'message', FILTER_SANITIZE_STRING );

    Diese Abfrage:

    PHP
    if(isset($_POST["name"]) && isset($_POST["email"]) && isset($_POST["message"]))

    kommt zu spät, Du hast bereits zuvor versucht darauf zuzugreifen.

    Hier wieder etwas komplett sinnloses:

    PHP
    if ( $line > 0) {
       }

    Auch in $data steht etwas anders, als Du erwartest. Wenn Du es so befüllst:

    PHP
    $data = array("name" => $name, "email" => $email, "message" => $message);

    hast Du ein Array, nach diesem Schema:

    Code
    Array (
        [name] => 'Hans Wurst'
        [email] => 'hans.wurst@example.com'
        [message] => 'einmal mit CurrySoße'
    )

    Wenn Du jetzt foreach ( $data as $line ) verwendest, hast Du in $line immer nur ein Element:

    Code
    1. Durchlauf: Hans Wurst
    2. Durchlauf: hans.wurst@example.com
    3. Durchlauf: einmal mit CurrySoße

    Da Du eine Schleife verwendest, liegt die Vermutung nahe, dass Du an der Stelle alle bisherigen Kommentare der Reihe nach anzeigen willst. Dazu sollte Dein Array $data aber anders aufgebaut sein:

    Code
    Array (
        [0] => Array (
            [name] => 'Hans Wurst'
            [email] => 'hans.wurst@example.com'
            [message] => 'einmal mit CurrySoße'
        )
    )

    Und selbst wenn Du das hast, stimmt Deine Verarbeitung innerhalb der foreach nicht.

    Du musst dann nämlich auf $line zugreifen und nicht auf $data.

    Bei manchen anderen Sachen kann man ein Auge zudrücken, aber das waren jetzt mal die Selbstverständlichkeiten, die Dir längst hätten selbst auffallen sollen.

    Die Richtung ist besser.

    Wenn Du empfänglich bist, darf ich Dir vielleicht als Anregung mal einen Ansatz mit geben, den ich anhand Deines Beispiels verfolgen würde.

    Da OOP von Objekten ausgeht, würde ich im Ganzen betrachten, was ich alles als Objekt definieren könnte. Das wären für mich an dieser Stelle folgende:

    • Company ( der Schiffsverleih )
      Hier werden Eigenschaften/Methoden des Unternehmen, bspw. Anzahl der Schiffe, verfügbare Schiffe
    • Ship ( das/ein Schiff )
      Hier werden die Eigenschaften/Methoden eines Schiff verwaltet, bspw. die Verfügbarkeit
    • Booking ( die Buchung )
      Hier werden Eigenschaften/Methoden einer Buchung verwaltet, bspw. Zeitraum
    • Planner ( der Buchungsplaner )
      Quasi ein Kalender, der Informationen hat oder erhält, wann bspw. welches Schiff gebucht ist
    • PriceList ( das Preismodell )
      Da unterschiedliche Schiffe unterschiedliche Eigenschaften, wie etwa Preise haben können, sollte es unterschiedliche Preismodelle geben
    • Customer ( der Kunde/Buchende )
      Ist denke ich mal selbsterklärend

    Warum ( auf den ersten Blick ) so umständlich?

    Du hast mit diesen Objekten Deine Prozesse sinnvoll aufgeteilt. Ein Objekt im OOP sollte immer nur eine Aufgabe haben und das ist bspw. in Bezug auf die Buchung nur der Vorgang selber. Die Buchung weiß weder persistent welches Schiff, noch welcher Buchungszeitraum vorliegt. Die Buchung fungiert als eine Art Controller, die einfach nur Daten steuert und weiter gibt, in diesem Fall sinnvoller Weise an den Planner.

    Der terminiert den Buchungsvorgang auf den gewählten Zeitraum und das gewählte Schiff und sperrt diese Kombination für weitere Buchungsanfragen.

    Die PriceList hätte man auch mit Ship kombinieren können, aber ich versuche immer an Flexibilität zu denken und könnte mir vorstellen, dass es irgendwann mal zu Rabattaktionen kommt. Diese lassen sich im PriceList-Model sehr gut unterbringen. Man kann also die Klasse PriceList einfach gegen eine andere austauschen, um neue Preismodelle einzufügen. Alles andere im Code bleibt wie es ist, da die Eigenschaften und Methoden der unterschiedlichen PriceList-Klassen immer gleich sind. Nur die Logik unterscheidet sich.

    Das im Detail jetzt alles durchzugehen wird ziemlich lang und für viele auch sicher langweilig, daher belasse ich das hier dabei.

    Wenn Du Interesse hast, kann ich Dir gern mal eine kleine funktionierende Beispiel-Buchung auf so einer Basis aufbauen, dann kannst Du damit ja mal rumspielen. Wird allerdings erst am WE was, weil ich morgen für drei Tage beruflich unterwegs bin.

    Ich habe mir mal ein paar Details Deiner Klasse angesehen. Warum nutzt Du für Methoden die statische Klassifizierung, für Variablen aber den Instanz-Operator $this?

    PHP
    $this->buchername = $buchername;
    $this->anzahlBesucher = $anzahlBesucher;
    $this->buchungVon = $buchungVon;
    $this->buchungBis = $buchungBis;
                
    Schiffsverleih::sumBuchungszeit();
    Schiffsverleih::getTimeParts();
    Schiffsverleih::getBootNummer();
    Schiffsverleih::getAnzahlSchiffe();
    Schiffsverleih::getPrice();

    Mit $schiffsverleih = new Schiffsverleih(...)erstellst Du eine Instanz der Klasse. Darin solltest Du dann auch $this verwenden:

    PHP
    $this->sumBuchungszeit();
    $this->getTimeParts();
    $this->getBootNummer();
    $this->getAnzahlSchiffe();
    $this->getPrice();

    Die statische Schreibweise macht nur Sinn, wenn die Klasse auch statisch ist.

    Eine Referenz ist eine zusätzliche Variable welchen eine Kopie der anderen Variable ist.

    Das stimmt so nicht. Bei einer Referenz ist es keine Kopie!

    Eine Referenz an sich ist auch keine Variable. Mit einer Referenz verweist man auf den Adressspeicher einer vorhandenen Variablen oder eines Objektes.

    Wie kann man es denn in OOP umsetzen?

    Eine Methode kann eine Referenz auf seine übergeordnete Instanz zurückgeben. Ein Beispiel:

    Jetzt habe ich halt die Möglichkeit des MethodChaining:

    PHP
    $foobar = new FooBar( "Hello " );
    echo $foobar->addText( "World" )->getText();

    Gerne. Ne, es gibt leider immer noch hier und da einiges zu bedenken, wenn es in allen Browsern funktionieren soll. Man kann jetzt über M$ meckern, aber es sind tlw. auch Dinge dabei, die die aus meiner Sicht zumindest korrekt machen, gegenüber den modernen Browsern.

    Am besten hilft die Konsole bei sowas, da wird dann bspw. ja angezeigt .forEach() is not a method o.ä.

    Dann kann man bereits ahnen, worauf das hinausläuft.

    Na gut, eigentlich ist so einiges falsch an dem auskommentierten.

    Zunächst mal fehlen zwei schließende geschweifte Klammern. Dann müssen Events ohne den Prefix on angegeben werden. Dein nicht funktionierender Block sollte dann in etwa so aussehen:

    JavaScript
    element=document.querySelectorAll('input');
    element.forEach((i) => {
    
        i.addEventListener('change', (e) => {
    
            alert();
    
        };
    
    };

    Das wäre technisch eigentlich in den modernen Browsern korrekt, wie Opera das sieht, kann ich adhoc nicht sagen.

    Probleme macht auf jeden Fall die M$-Schiene. Dort ist nämlich die Schreibweise für die Funktionen nicht bekannt, hier müsste das gegen die Standard-Schreibweise getauscht werden:

    JavaScript
    element=document.querySelectorAll('input');
    element.forEach(function(i) {
    
        i.addEventListener('change', function(e) {
    
            alert();
    
        };
    
    };

    Jetzt gibt es eigentlich nur noch ein mir bekanntes Problem von Seiten M$: forEach() ist nur für echte Arrays verfügbar!

    querySelectorAll() gibt aber eine NodeList zurück, die streng genommen kein Array ist, weshalb IE behaupet: forEach()? Kenne ich nicht.

    Daher bleibt Dir an der Stelle eigentlich nur eine Standard-Loop Variante oder fehlende Funktionalitäten nachzubauen.

    Ich denke zwar, dass der Opera das mit der modernen Variante schon hinbekommen sollte, sofern die Klammern usw. korrekt gesetzt sind, aber dennoch wird so ein Script sicher auch mal in einem M$-Browser ausgeführt werden sollen und dann klappt es leider nicht.

    Ich würde übrigens auch nicht das change Event nehmen, sondern keyup.

    Oder einfach schnell selber bauen, wenn's nicht zwingend ein Picker sein muss:

    HTML
    <span class="timeframe"><input type="number" name="time[min]" value="00"><span>:</span><input type="number" name="time[sec]" value="00"><span>.</span><input type="number" name="time[msec]" value="000"></span>
    CSS
    .timeframe { padding:5px; border:1px solid #ccc; }
    .timeframe > INPUT { width:50px; border:none; text-align:right; }

    Mit etwas EventListening lässt sich da auch eine relativ gute Usability erreichen, ganz ohne jQuery.

    Solltest Du bereits jQuery im Einsatz haben, ist das PlugIn sicher eine gute Wahl. Aber dafür extra jQuery einzusetzen halte ich für Overhead.