Como posso aplicar os conceitos de POO para criar um aplicativo Web simples, mas do mundo real? [fechadas]

25

Venho tentando há muito tempo envolver minha cabeça em torno de OOP. Eu vejo suas vantagens. Eu li muitos tutoriais e assisti a uma quantidade igual de vídeos sobre o assunto. Eu recebo os exemplos de animais / gatos / cães, os exemplos de carros / unidades. O que estou enfrentando é como aplicar esses conceitos em um aplicativo do mundo real. Então, eu decidi construir um usando OOP.

Não estou pedindo ajuda com sintaxe ou escrevendo código específico - posso encontrar isso na documentação e pesquisando nos fóruns etc. O que realmente preciso é de alguma orientação e um empurrão na direção certa de vez em quando. Existem programadores experientes dispostos a me orientar?

Como meu projeto de aprendizado, gostaria de criar um "aplicativo da web" simples para classificados. Algo semelhante ao Craigslist, mas bastante diluído em termos de escopo. Eu gostaria de usar PHP5 e MySQL, porque estou familiarizado com eles.

Digamos que existem apenas dois casos de uso:

  1. Publicando algo para venda
  2. Navegando / procurando algo para comprar

Quais "coisas" devem ser objetos? Eu posso imaginar que cada item poderia ser um objeto, mas em que momento? E porque?

Por exemplo, o usuário preenche o formulário "lançar item à venda"; esse formulário deve se transformar em um objeto que é passado para outro objeto que insere os valores em um banco de dados?

E quando outro usuário está navegando e solicita a visualização de todos os itens da categoria C? Faz sentido que, sempre que o aplicativo precise se conectar ao banco de dados, ele crie um objeto de banco de dados, obtenha um monte de objetos de itens e os exiba na página? ... escrever isso certamente me faz perceber o quanto eu ainda sou ignorante sobre OOP. Por favor me ajude a consertar isso.

Se, na sua opinião, esse não é um bom projeto para começar a entrar no OOP, fique à vontade para sugerir outra idéia!

Bernk
fonte
1
Estou no mesmo barco, acho que entendi OOP - já faz um tempo desde que eu tentei o Java, mas quando se trata de PHP, eu sabia como fazer coisas assim instantaneamente da maneira 'normal', mas quando se trata de pensar em como isso seria feito usando OOP, eu perdi a vontade de viver.
Martincarlin87 16/05
O formulário não é transformado em um objeto. Um objeto é uma instância de uma classe. Você poderia vê-lo assim. $ item-> saveItem ($ _ POST ['nome'], $ _POST ['descrição']); editar O que realmente me ajudou a descobrir OOP é criar um aplicativo da web simples "livro de visitas". Log os usuários fazem no, postar mensagens, editar as mensagens, mensagens de exclusão e procurar mensagens etc.
@pduersteler boa ideia, como faço para fazer isso? Na verdade, esta é a minha primeira pergunta sobre stackoverflow :)
@Bono Talvez um aplicativo de livro de visitas como você mencionou seja realmente um lugar melhor para começar. O outro que eu pensava era um aplicativo de lista muito simples, onde os usuários fazem login, fazem / editam / excluem listas, adicionam / editam / excluem itens dessas listas. Você se importaria de compartilhar seu aplicativo de livro de visitas conosco / comigo?
Eu não me importaria de compartilhá-lo, embora fosse um monte de código para postar. Eu poderia compartilhar uma aula de exemplo simples com você, se você quiser. Também eu não sei o quão bem este código vai funcionar, porque, francamente, tem sido um tempo: P eu vou postá-lo abaixo

Respostas:

17

Sinceramente, acho que o conselho aqui tem sido terrível para os novos aprendizes de OO até agora. Não é uma boa idéia começar imediatamente a pensar em objetos como representações de uma instância específica de uma "coisa" definida por alguma classe. É melhor pensar neles como componentes compartimentados de uma máquina que interagem um com o outro, mas não os internos. Cada um desses componentes mantém o estado

Se você deseja usar um ORM (mapeamento relacional de objetos) para interações com banco de dados, qualquer estrutura que você use ou crie provavelmente terá alguns objetos rasos que representam tabelas, que provavelmente são coleções de "coisas", mas eu não gosto de ORMs pessoalmente , e não acho que eles representem necessariamente práticas ideais de OO, mas são populares para aplicativos da Web grandes.

Além disso, você provavelmente terá alguns componentes importantes que a máquina de aplicativos da web precisa para executar, como uma ou mais conexões com o banco de dados (você pode criar uma classe que mantém uma conexão e executar consultas preparadas - PDOé ótimo por si só , mas eu o resumiria) e talvez um sistema de modelos para suas visualizações. Você também pode querer que seus controladores sejam objetos PHP. Se você tiver um formulário para preencher, poderá ter um objeto que mantenha os valores do formulário para P / R / G, um token de proteção CSRF e possa executar a validação em suas entradas.

Você não deve tentar procurar por "coisas" para se transformar em objetos ao construir o design do aplicativo da web e o gráfico de objetos. Em vez disso, você deve pensar nos componentes lógicos que se reúnem para criá-lo. Não acho que você deva tentar forçar isso, e isso deve ocorrer naturalmente, mas é muito difícil de fazer corretamente e você definitivamente terá que mudar algumas decisões de design ao longo do caminho.

Meu conselho final é este: composição sobre herança é o caminho a percorrer.

Comprimidos de explosão
fonte
Uma regra prática que tenho, especialmente para linguagens dinâmicas, é tentar criar classes apenas se eu quiser tirar proveito do polimorfismo (ou seja, se essas classes implementarem versões diferentes do mesmo método, e a lógica dependerá disso). de alguma forma). Caso contrário, tento errar ao escrever em um estilo mais "processual", para mantê-lo simples.
Hugomg 17/05/12
9

Aqui está como você pode usar o OOP para comprar e vender seus animais de estimação, a mesma metodologia pode ser usada para vender carros ou aviões;

<?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();
?>
Lawrence Cherone
fonte
28
Se eu ver mais um exemplo oop com carros ou animais, estou indo perdê-lo
Neil McGuigan
5

A pedido do OP, compartilharei meu código do livro de visitas.
Classe de mensagem:

<?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;
    }
}

Classe de Objeto de Acesso a Dados da Mensagem:

<?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');

Renomeei algumas das variáveis ​​e função para fazer sentido para você (traduzido do holandês para o inglês: P), para que você possa encontrar algumas frases estranhas às vezes porque fiz uma substituição rápida etc. Divirta-se com isso. Além disso, este não é o código inteiro, porque isso resultaria em eu postar 20 arquivos no código: P

Bono
fonte
3

Conforme mencionado por Explosion Pills, em um aplicativo complexo, a maioria dos objetos está relacionada a componentes de aplicativos (por exemplo, conjuntos de conexões de banco de dados, comandos, estruturas de dados como hashmaps) e não a entidades do mundo real (como cartão de embarque, fatura ou arquivo mp3). ) Existem muitos bons livros sobre padrões de design que mostram maneiras pelas quais as pessoas resolveram muitos problemas recorrentes nessa área. O livro do GOF, como é conhecido, é completo, mas muito seco; os padrões de design do Head First podem ser mais acessíveis.

Em termos de análise e design do mundo real. Muitas vezes, é útil pensar em termos de substantivos e verbos. Por exemplo, uma biblioteca de empréstimo de vídeo (agora obsoleta?) Pode ter as seguintes coisas / substantivos:

  • Vídeo
  • Mutuário

Em termos de verbos:

  • Um mutuário pode gravar um vídeo por um período de tempo
  • Um Mutuário pode devolver um vídeo à loja etc.

Eles podem ser transformados em classes com operações (faz muito tempo que eu fiz PHP, então evitarei):

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

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

É preciso muita prática e brincadeiras. A melhor coisa a fazer é ficar preso e aprender com os projetos com falha. Na minha opinião, OO é algo que você pode continuar aprendendo e desenvolvendo ao longo da sua vida (não é fácil e não há soluções perfeitas para nada). Um bom design geralmente é iterativo; portanto, tente experimentar algumas idéias diferentes para o seu webapp "Lista de Craig".

mward
fonte
1

A melhor coisa a fazer é encontrar uma maneira de se concentrar no núcleo do seu aplicativo - "post", "user", "post :: FindByName ()", "user-> Validate ()" etc., e não se preocupe muito sobre o encanamento - como colar postagens em tabelas do banco de dados, como manter a exibição de uma postagem consistente entre pesquisas diferentes e como colar o formulário "inserir postagem" em um registro do banco de dados.

Felizmente, existem muitas estruturas que fazem isso por você; o paradigma dominante nos aplicativos da Web OO é "Model-View-Controller", também conhecido como MVC ; no PHP, existem várias estruturas MVC prontas para uso que você pode usar.

Embora isso expanda sua necessidade de aprender - agora você precisa aprender sobre MVC e OO - significa que seus esforços de OO são restritos principalmente à camada "Modelo", que representa seu domínio de negócios; é aí que o OO é mais natural e expressivo. A maioria das estruturas MVC permite que você defina sua camada "modelo" e crie automaticamente um site em torno dela usando uma técnica conhecida como andaime - dessa forma, você obtém uma maneira rápida de experimentar diferentes implementações para o seu modelo de domínio, sem tendo que desfazer todo o encanamento.

Neville Kuyt
fonte