it-swarm.com.de

Wie kann ich OOP) Konzepte anwenden, um eine einfache, aber reale Web-App zu erstellen?

Ich habe jetzt schon lange versucht, meinen Kopf um OOP zu wickeln. Ich sehe seine Vorteile. Ich habe viele, viele Tutorials gelesen und mir gleich viele Videos zu diesem Thema angesehen. Ich bekomme die Tier-/Katzen-/Hundebeispiele, ich bekomme die Auto-/Fahrbeispiele. Ich habe Probleme damit, diese Konzepte in einer realen Anwendung anzuwenden. Also habe ich mich vorgenommen, eine mit OOP zu erstellen.

Ich bitte nicht um Hilfe bei der Syntax oder beim Schreiben von spezifischem Code - ich kann das selbst in der Dokumentation und durch das Durchsuchen von Foren usw. finden. Was ich wirklich brauche, ist eine Anleitung und hin und wieder ein Push in die richtige Richtung. Gibt es erfahrene Programmierer, die bereit sind, mich zu betreuen?

Als mein Lernprojekt möchte ich eine einfache Kleinanzeigen "Web App" erstellen. Etwas Ähnliches wie Craigslist, aber in Bezug auf den Umfang viel verwässert. Ich möchte PHP5 und MySQL verwenden, weil ich mit ihnen vertraut bin.

Angenommen, es gibt nur diese beiden Anwendungsfälle:

  1. Etwas zum Verkauf anbieten
  2. Durchsuchen/Suchen nach etwas zu kaufen

Welche "Dinge" sollten Objekte sein? Ich kann mir vorstellen, dass jeder Gegenstand ein Objekt sein könnte, aber an welchem ​​Punkt? Und warum?

So füllt der Benutzer beispielsweise das Formular "Artikel zum Verkauf anbieten" aus. Sollte dieses Formular in ein Objekt umgewandelt werden, das an ein anderes Objekt übergeben wird, das die Werte in eine Datenbank einfügt?

Was ist, wenn ein anderer Benutzer surft und alle Elemente der Kategorie C anzeigen möchte? Ist es sinnvoll, dass die App jedes Mal, wenn sie eine Verbindung zu ihrer Datenbank herstellen muss, ein Datenbankobjekt erstellt und dann eine Reihe von Elementobjekten abruft und diese auf der Seite anzeigt? … Wenn ich das aufschreibe, wird mir klar, wie ahnungslos ich immer noch über OOP bin. Bitte helfen Sie mir, das zu beheben.

Wenn dies Ihrer Meinung nach kein gutes Projekt ist, um in OOP mit) zu waten, können Sie gerne eine andere Idee vorschlagen!

25
bernk

Ich denke ehrlich, dass der Rat hier für neue OO Lernende) bisher schrecklich war. Es ist keine gute Idee, Objekte sofort als Repräsentationen einer bestimmten Instanz eines durch definierten "Dings" zu betrachten Einige Klassen. Es ist besser, sie als unterteilte Komponenten einer Maschine zu betrachten, die eine gewisse Interaktion miteinander haben, aber nicht die Interna der anderen. Jede dieser Komponenten behält ihren Zustand bei

Wenn Sie ein ORM (Object-Relational-Mapping) für DB-Interaktionen verwenden möchten, enthält das von Ihnen verwendete oder erstellte Framework wahrscheinlich einige flache Objekte, die Tabellen darstellen, bei denen es sich wahrscheinlich um Sammlungen von "Dingen" handelt, aber ich mag ORMs persönlich nicht und ich denke nicht, dass sie notwendigerweise ideale OO Praktiken) darstellen, aber sie sind beliebt für große Web-Apps.

Außerdem verfügen Sie wahrscheinlich über einige wichtige Komponenten, die der Web-App-Computer ausführen muss, z. B. eine oder mehrere DB-Verbindungen (Sie können eine Klasse erstellen, die eine Verbindung aufrechterhält, und Sie können vorbereitete Abfragen von - PDO ausführen ist großartig für sich, aber ich würde es einpacken) und vielleicht ein Vorlagensystem für Ihre Ansichten. Möglicherweise möchten Sie, dass Ihre Controller PHP Objekte) sind. Wenn Sie ein Formular ausfüllen müssen, haben Sie möglicherweise ein Objekt, das Formularwerte für P/R/G, einen CSRF-Schutz, verwaltet Token und kann die Eingaben validieren.

Sie sollten nicht versuchen, nach "Dingen" zu suchen, die sich in Objekte verwandeln, wenn Sie Ihr Web-App-Design und Objektdiagramm erstellen. Stattdessen sollten Sie über die logischen Komponenten nachdenken, die zusammenkommen, um es zu erstellen. Ich denke nicht, dass Sie versuchen sollten, dies zu erzwingen, und es sollte ziemlich natürlich kommen, aber es ist sehr schwer, es richtig zu machen, und Sie werden definitiv einige Designentscheidungen auf dem Weg ändern müssen.

Mein letzter Rat lautet: Komposition über Vererbung ist der richtige Weg.

17
Explosion Pills

Hier erfahren Sie, wie Sie OOP] zum Kaufen und Verkaufen Ihrer Haustiere verwenden können. Dieselbe Methode kann zum Verkaufen von Autos oder Flugzeugen verwendet werden

<?php
// define a superclass .. no instances will be made of 'animal' itself,
// but it is useful to define common characteristics and behaviours
// (ie: properties and methods) of all our classes of animals
class Animal {

    // this constructor function is called whenever a new instance
    // of the Animal class is created (or any class that inherits from Animal)
    function Animal ($colour) {

        // install the argument as an attribute of any instances of Animal
        $this->colour = $colour;
    }

    // this method will be available to all classes that inherit from Animal
    function report () {
        return "This ".$this->colour." ".get_class($this)." has ".$this->legs." legs.<br />";
    }
}

// this class inherits from Animal
class Cat extends Animal {

    // set the legs attribute
    public $legs = 4;

    // create a method that can be called from any instances of Cat
    function make_noise () {
        echo "MEOW!<br />";
    }
}

// this class inherits from Cat, and from Animal
class Panther extends Cat {

    // specifies the colour attribute
    public $colour = "black";

    // overwrites the constructor function that would otherwise be
    // inherited from Animal, with a blank constructor.
    function Panther () {}

    // overwrites the method inherited from Cat
    function make_noise () {
        echo "ROARRRR!<br />";
    }
}

// this class inherits from Animal
class Snake extends Animal {
    public $legs = 0;
}

// this class is unrelated to the others
class PetShop {

    // set up an array to store the pets that the shop will stock
    public $pets = array ();

    // set up a variable to store the total cash in the pet shop
    public $cash;

    // this method creates a new object and adds it to the pets array
    function add_pet ($petclass, $price, $colour) {

        // set up a variable containing the number of elements in the pets array
        $n_pets = count($this->pets);

        // add to the pets array, a new instance of the class specified as
        // the first argument in this method, using the last argument as the
        // colour argument that is passed to the specified class's constructor
        $this->pets[$n_pets] = new $petclass($colour);

        // add a 'price' attribute to the pet object
        $this->pets[$n_pets]->price = $price;
    }

    // this method removes the specified pet from the array and adds the price
    // to the pet shop's cash variable
    function sell_pet ($n) {

        // add pet's price to the cash total
        $this->cash += $this->pets[$n]->price;

        // remove the pet object from the array
        array_splice($this->pets, $n, 1);

        // give a message about the sale
        echo "SALE: Pet no. ".$n." sold. Total cash is now \$".$this->cash.".<br /><br />";
    }

    // this method reports on the pet shop's stock
    function show_pets () {

        // show the number of pets available
        echo "<B>Shop stock:</B><br />We have ".count($this->pets)." pets for sale.";
        echo "<br /><br />";

        // iterate through the pets array and show information about each one
        for ($i = 0; $i < count($this->pets); $i++) {
            echo "<B>Pet No. ".$i.": </b>".$this->pets[$i]->report();
            echo "Price: \$".$this->pets[$i]->price."<br />";
        }
        echo "<br />";
    }
}

// instantiate a new PetShop object
$shop = new PetShop ();

// add three pets to the shop
$shop->add_pet(cat, 20, "tabby");
$shop->add_pet(snake, 40, "brown");
$shop->add_pet(snake, 60, "black");

// show the pet's stock
$shop->show_pets();

// sell the first pet in the stock
$shop->sell_pet(0);

// show the pet's stock after the sale
$shop->show_pets();
?>
9

Auf Anfrage von OP werde ich meinen Gästebuchcode teilen.
Nachrichtenklasse:

<?php 
Class message
{
    private $db;
    private $messageID;
    private $message;
    private $name;
    private $mail;

    public function setmessageID($messageID)
    {
        $this->messageID = $messageID;
    }

    public function getmessageID()
    {
        return $this->messageID;
    }

    public function setmessage($message)
    {
        $this->message = $message;
    }

    public function getmessage()
    {
        return $this->message;
    }

    public function setname($name)
    {
        $this->name = $name;
    }

    public function getname()
    {
        return $this->name;
    }

    public function setMail($mail)
    {
        $this->mail = $mail;
    }

    public function getMail()
    {
        return $this->mail;
    }
}

Objektklasse für Nachrichtendatenzugriff:

<?php 
class messageDAO
{
    private $db;
    private $aantalMessages;
    private $messages;
    private $message;

    //bij laden roept hij automatisch Db class aan (en de daarbij gezeten functies)
    public function __construct(Db $db)
    {
        $this->db = $db;
    }

    public function getMessages()
    {
        return $this->messages;
    }

    public function getAantalMessages()
    {
        return $this->aantalMessages;
    }

    //Function to retrieve messages
    public function findMessages($args)
    {       
        $dbh = $this->db->DBH();

        //$offset for pagination
        $offset = ($args['currentPage'] - 1) * $args['itemsPerPage'];

        $sth = $dbh->prepare("SELECT    SQL_CALC_FOUND_ROWS
                                                    messageen.messageID, 
                                                    messageen.message, 
                                                    messageen.name, 
                                                    messageen.mail
                                            FROM    `messageen` 
                                            ORDER BY messageen.datumToegevoegd DESC 
                                            LIMIT   ?, ?");
        $sth->bindParam(1, $offset, PDO::PARAM_INT);
        $sth->bindParam(2, $args['itemsPerPage'], PDO::PARAM_INT);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);

        $messages = array();

        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessageID(htmlentities(strip_tags($row['messageID'])));
            $message->setSessage(htmlentities(strip_tags($row['message'])));
            $message->setName(htmlentities(strip_tags($row['name'])));
            $message->setMail(htmlentities(strip_tags($row['mail'])));  
            $messages[] = $message; 
        }

        $sth = $dbh->prepare("SELECT FOUND_ROWS() as numberOfMessages");
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        $this->numberOfMessages = $sth->fetch();

        return $messages;
    }

    public function setMessageToEdit($args)
    {   
        $sth = $this->db->DBH()->prepare("SELECT    messages.message
                                            FROM    `messages`
                                            WHERE   messages.messageID = ?");
        $sth->bindParam(1, $args['messageID']);
        $sth->execute();
        $sth->setFetchMode(PDO::FETCH_ASSOC);
        //return the retrieved message
        while($row = $sth->fetch())
        {
            $message = new message();
            $message->setMessage(htmlentities(strip_tags($row['message'])));
            $message->setMessageID(intval($args['messageID']));
        }

        return $message;
    }

    //functie om messageen aan te passen
    public function save(message $message)
    {   
        //insert part
        //if(isset($message->getname()) && isset($message->getmessage()) && isset($message->getMail()))
        //{
            $sth = $this->db->DBH()->prepare("INSERT INTO   `messages`
                                                    SET     messages.name = ?,
                                                            messages.mail = ?,
                                                            messages.message = ?,
                                                            messages.dateAdded = NOW()");
            $sth->bindParam(1, $message->getName());
            $sth->bindParam(2, $message->getMail());
            $sth->bindParam(3, $message->getMessage());
            $sth->execute();
        //}

        //update part       
        /*if(isset($message->getmessageID()) && isset($message->getmessage()))
        {
            $sth = $this->db->DBH()->prepare("UPDATE    `messageen`
                                                SET     messageen.message = ? 
                                                WHERE   messageen.messageID = ?
                                                LIMIT   1");
            $sth->bindParam(1, $message->getmessage());
            $sth->bindParam(2, $message->getmessageID());
            $sth->execute();
        }*/
    }
}

index.php

<?php
//include file loader.php
include("includes/loader.php");

$guestbook = new guestbook($db);
$user = new user($db);
$messageDAO = new messageDAO($db);

//Make a array named error
$error = array();

//Get action (login/setmessage/editmessage/deletemessage)
if(isset($_GET['action']))
{   
    switch ($_GET['action'])
    {   
        //if login submit is pressed
        case 'login':
            //Check if filled
            if(isset($_POST['username']) && isset($_POST['username']))
            {
                $error['usernameEmpty'] = (bool) !strlen(trim($_POST['username']));
                $error['passwordEmpty'] = (bool) !strlen(trim($_POST['password']));
            }

            if(in_array(1, $error))
            {
                //Assign $error to smarty
                $smarty->assign('error', $error);
            }

            else
            {
                if(isset($_POST['username']) && isset($_POST['username']))
                {
                    $user->setLoggedIn(array('username'=>$_POST['username'],
                    'password'=>$_POST['password']));

                    if($user->getLoggedIn() != true)
                    {                   
                        $smarty->assign('loggedInError', $user->getLoggedIn());
                    }
                }
            }
            break;

        //Als if "place message" is pressed
        case 'placemessage':
            //if user is not logged in
            if($user->getLoggedIn() != true)
            {
                //Controleren of message-velden wel zijn ingevuld
                $error['nameEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messagename']))));
                $error['mailEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags($_POST['messageMail']))));
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place message...','', $_POST['messageInput'])))));

                if($error['mailEmpty'] != 1)
                {
                    $error['mailInvalid'] = !filter_input((INPUT_POST), 'messageMail', FILTER_VALIDATE_EMAIL);
                }

                if(in_array(1, $error))
                {
                    $smarty->assign('error', $error);
                }

                else
                {
                    $message = new message();

                    $message->setname($_POST['messagename']);
                    $message->setMail($_POST['messageMail']);
                    $message->setmessage($_POST['messageInput']);

                    dump($message);

                    //place message             
                    $messageDAO->save($message);
                }
            }

            //if user is logged in
            else 
            {
                //is message filled?
                $error['messageEmpty'] = (bool) !strlen(trim(htmlentities(strip_tags(str_replace('place hier uw message...','', $_POST['messageInput'])))));

                if($error['messageEmpty'] != 1)
                {   
                    $user->setUser();

                    $guestbook->placemessage(array('name'=>$user->getLoggedInUsername(), 
                    'mail'=>$user->getLoggedInUserMail(),
                    'messageInput'=>$_POST['messageInput']));
                }

                else 
                {
                    $smarty->assign('error', $error);
                }
            }
            break;

        case 'deletemessage':
            $user->setUser();

            if($user->getLoggedInUserAdmin() == 1)
            {
                if(isset($_GET['messageID']) && is_numeric($_GET['messageID']) && isset($_GET['key']))
                {
                    $guestbook->setURLKey($_GET['messageID']);

                    if($guestbook->getURLKey() == $_GET['key'])
                    {                   
                        $guestbook->verwijdermessage(array('messageID'=>$_GET['messageID']));
                    }
                }
            }
            die(header("location: /index.php"));
            break;
    }
}

if(isset($_GET['pagina']) && is_numeric($_GET['pagina']))
{

    $currentpage = $_GET['pagina'];
}

else
{
    //$currentpage is 1
    $currentpage = 1;
}

$user->setUser();

//assign var to smarty
$smarty->assign('messages', $messageDAO->findmessages(array('currentpage'=>$currentpage, 'itemsPerPagina'=>10)));
$smarty->assign('user', $user);

//Pagination

$numbermessages = $messageDAO->getnumbermessages();


$totalpages = ceil($numbermessages['numbermessages'] / 10);


if($currentpage < 1)
{
    //$currentpage is 1
    $currentpage = 1;
}


if($currentpage > $totalpages)
{

    $currentpage = $totalpages;
}

$smarty->assign('numbermessages', $messageDAO->getnumbermessages());
$smarty->assign('guestbook', $guestbook);
$smarty->assign('currentpage', $currentpage);
$smarty->assign('totalpages', $totalpages);

//display index.tpl
$smarty->display('index.tpl');

Ich habe einige der Variablen und Funktionen umbenannt, um für Sie einen Sinn zu ergeben (übersetzt von Niederländisch nach Englisch: P), sodass Sie manchmal seltsame Gefühle finden, weil ich nur schnell ersetzt habe usw. Viel Spaß damit. Auch dies ist nicht der gesamte Code, da dies dazu führen würde, dass ich Code im Wert von 20 Dateien poste: P.

5
Bono

Wie von Explosion Pills erwähnt, beziehen sich die meisten Objekte in einer komplexen Anwendung eher auf Anwendungskomponenten (z. B. Datenbankverbindungspools, Befehle, Datenstrukturen wie Hashmaps) als auf reale Entitäten (wie eine Bordkarte, eine Rechnung oder eine MP3-Datei) ). Es gibt viele gute Bücher über Designmuster, die Ihnen zeigen, wie Menschen viele wiederkehrende Probleme in diesem Bereich gelöst haben. Das so genannte GOF-Buch ist gründlich, aber sehr trocken. Head First Design Patterns sind möglicherweise leichter zugänglich.

In Bezug auf Analyse und Design in der realen Welt. Es ist oft hilfreich, in Substantiven und Verben zu denken. Zum Beispiel kann eine Videokreditbibliothek (sind diese jetzt veraltet?) Folgende Dinge/Substantive haben:

  • Video
  • Kreditnehmer

In Bezug auf Verben:

  • Ein Kreditnehmer kann ein Video für längere Zeit aufnehmen
  • Ein Kreditnehmer kann ein Video an das Geschäft usw. zurückgeben.

Diese können dann in Klassen mit Operationen umgewandelt werden (es ist lange her, dass ich irgendetwas getan habe PHP, also werde ich es vermeiden):

class Borrower
{
  public void borrow(Video video, int daysToBorrow)
  {
     ...
  }

  public void returnVideo(Video video, boolean calculateFine)
  {
     ...
  }
}

Es erfordert viel Übung und Herumspielen. Das Beste, was Sie tun können, ist, festzuhalten und aus fehlgeschlagenen Designs zu lernen. Meiner Meinung nach ist OO etwas, das Sie im Laufe Ihres Lebens weiter lernen und entwickeln können (es ist nicht einfach und es gibt keine perfekten Lösungen für irgendetwas). Gutes Design ist oft iterativ, also erwarten Sie es Probieren Sie einige verschiedene Ideen für Ihre Webanwendung "Craig's List" aus.

3
mward

Am besten finden Sie eine Möglichkeit, sich auf den Kern Ihrer Anwendung zu konzentrieren - "post", "user", "post :: FindByName ()", "user-> Validate ()" usw., ohne sich Sorgen zu machen Zu viel über die Installation - wie man Beiträge an Datenbanktabellen klebt, wie man die Anzeige für einen Beitrag zwischen verschiedenen Suchvorgängen konsistent hält und wie man das Formular "Beitrag eingeben" auf einen Datenbankeintrag klebt.

Glücklicherweise gibt es viele Frameworks, die dies für Sie tun. Das vorherrschende Paradigma in OO Webanwendungen ist "Model-View-Controller", auch bekannt als MVC ; in PHP, Es gibt eine Reihe von Standard-MVC-Frameworks, die Sie verwenden können.

Während dies Ihr Lernbedürfnis erweitert, müssen Sie jetzt sowohl MVC als auch OO - lernen - dies bedeutet, dass Ihre OO Bemühungen] hauptsächlich auf das " Modell "-Ebene, die Ihre Geschäftsdomäne darstellt; hier ist OO" am natürlichsten und ausdrucksstärksten. Mit den meisten MVC-Frameworks können Sie Ihre "Modell" -Ebene definieren und dann automatisch eine Website erstellen Um dies zu umgehen, können Sie mithilfe einer als Gerüst bezeichneten Technik schnell mit verschiedenen Implementierungen für Ihr Domänenmodell experimentieren, ohne die gesamte Installation entfernen zu müssen.

1
Neville Kuyt