Autor Zpráva
DavidOpp
Profil *
Zdravím všechny, mám na Vás prosbu. Umím vytvořit výpis z databáze v pohodě, jen né OOP, aspoň si to tedy myslím... Mohli by mi z kódu co níže prezentuji někdo říci zda to je alespoň trochu OOP a jaké to má nedostatky ? Prosím Vás, aby jste se zdrželi nějakého posměvování nebo tak, jsem s OOP začátečník a potřebuji jen ( nasměrovat, poradit ) abych se poučil.
Hlavní funkcionalita
1) mám nějaké údaje v databázy, které chci vypsat
2) o získání dat se postará třída Database a předá tak data v jednotlivých proměnných do třídy Request
3) nejprve musím zavolat funkci v DB co mi do třídy Request předá data (toto myslím, že asi nebude správně)
4) FINÁLNÍ ČÁST - tam kde chci data vypsat volám již třídu request a její private proměnné typu array získám pomocí getteru,který pak vypisuju pomocí foreach ( toho asi taky není správně... :/ )

1) TŘÍDA DATABASE
  function get_all_assisted_request() {

        $service = array();
        $eshopName = array();
        $url = array();
        $nameProduct = array();
        $description = array();
        $quantity = array();
        $price = array();
        $user = array();
        $id = array();

        $data = $this->connect()->query("SELECT * FROM assisted_packages_request WHERE id ");

        foreach ($data as $val) {
            array_push($service, $val['service']);
            array_push($eshopName, $val['eshopName']);
            array_push($url, $val['eshopUrl']);
            array_push($nameProduct, $val['eshopNameProduct']);
            array_push($description, $val['eshopDescription']);
            array_push($quantity, $val['eshopQuantity']);
            array_push($price, $val['price']);
            array_push($user, $val['user']);
            array_push($id, $val['id']);
        }

        return new a_AssistedRequest($id, $user, $service, $eshopName, $url, $nameProduct, $description, $quantity, $price);
    }

2) TŘÍDA REQUEST
class a_AssistedRequest {

    private $service;
    private $eshopName;
    private $url;
    private $nameProduct;
    private $description;
    private $quantity;
    private $price;
    private $user;
    private $id;

    public function __construct($id, $user, $service, $eshopName, $url, $nameProduct, $description, $quantity, $price) {
        $this->service = $service;
        $this->description = $description;
        $this->eshopName = $eshopName;
        $this->price = $price;
        $this->quantity = $quantity;
        $this->nameProduct = $nameProduct;
        $this->url = $url;
        $this->user = $user;
        $this->id = $id;
    }

    function getUser() {
        return $this->user;
    }

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

    public function getService() {
        return $this->service;
    }

    function getEshopName() {
        return $this->eshopName;
    }

    function getUrl() {
        return $this->url;
    }

    function getNameProduct() {
        return $this->nameProduct;
    }

    function getDescription() {
        return $this->description;
    }

    function getQuantity() {
        return $this->quantity;
    }

    function getPrice() {
        return $this->price;
    }

}

3) VÝPIS DAT
 $x = $database->get_all_assisted_request();
    print_r($x->getUser());
Joker
Profil
DavidOpp:
Tak první věc je, jestli má vůbec smysl vyrábět „databázovou“ třídu.
Kdysi jsem to taky zkoušel a došel k tomu, že nemá.

Psát databázovou třídu na té nejnižší úrovni, že by přebírala SQL dotazy, nemá smysl, protože to se používá tak často, že určitě bude existovat nějaké už hotové řešení.

O úroveň výš je databázová třída, která pracuje s mými „business objekty“, tj. má metody typu:
createUser($user), updateUser($user), deleteUser($user), getUserById($id), getUserByQuery($conditions, $limit, $order), createProduct($product), updateProduct($product), deleteProduct($product), getProductById($id), getProductByQuery($conditions, $limit, $order), …

Na první pohled je to užitečnější, ale na druhý pohled: Vzniká ohromná třída s hromadou metod pracujících s nesourodými objekty. Ta třída se musí používat ve všech koutech aplikace, kde se pracuje s perzistentními objekty, přičemž zároveň každá změna nějakého perzistentního objektu znamená úpravu té třídy.
Ani ta abstrakce od datového úložiště není slavná, protože každá změna načítání u jednoho objektu vede zase na úpravu té třídy.
Vzniká třída, která je zaháčkovaná všude možně a zároveň se kvůli každé prkotině v ní musejí dělat úpravy- což není dobrá kombinace.

Postupem času z toho nejspíš vyplyne to, co je při bližším pohledu zřejmé z toho mého výčtu metod výše: V metodách té třídy se začne objevovat vzor, kdy děláte pořád stejné operace, ale s různými typy objektů.
Zjistí se, že ta databázová třída nedělá hromadu různých operací, ale všechny ty metody se dají roztřídit na několik základních operací (konkrétně se jim říká CRUD: Create, Read, Update, Destroy), které se tam neustále opakují pro každý objekt zvlášť.

A tedy to vlastně není jedna třída, ale hromada tříd, kde každá implementuje pár stejných operací.
Takže by mi stačilo řekněme rozhraní IRepository s metodami getById, getByQuery, create, update a delete a následně třídy UserRepository, ProductRepository, atd. implementující to rozhraní.


A ještě dodatek: Případné metody, které jsou tam navíc a nezapadají do toho schématu, se obvykle ukáží být metodami těch business objektů.
DavidOpp
Profil *
Joker:
Děkuji moc za obsáhlou odpověď. Takže jestli to chápu správně, tak by měli být základní metody getById, getByQuery, create, update a delete. A pokaždé když bych hrabal do DB tak využil tyto metody a neměl miliony dalších co vlastně dělají to samé akorát se jinak jmenují. Pak už jen třídy pro dané subjekty třeba Users a Products ve kterých budu využívat metody getById, getByQuery, create, update a delete a tím je upravovat ?
Radek9
Profil
DavidOpp:
Přesně tak. Ty jednotlivé repozitáře (Users a Products) prostě objektově reprezentují tabulku a v těch metodách si skládáš SQL dotaz podle zadaných parametrů.
DavidOpp
Profil *
Dobře, děkuji moc ! Jinak se prosím chci ještě zeptat, je ten kód co jsem prezentoval aspoň myšlenkově OOP ? Myslím získání dat, předání do třídy request a následné vypasání dat ? Když nebereme v potaz zbytečně statický kód v třídě DB ?
Joker
Profil
DavidOpp [#3]:
Tak ty názvy samozřejmě nejsou závazné, ale pokud jde o smysl, zhruba k tomu seznamu jsem došel.

Respektive ty CRUD operace jsou takový standard, ale v implementaci mi přijde šikovné to „Read“ ještě dělit na dvě situace: Jestli se ptám na jeden objekt podle „primárního klíče“ (nějakého jednoznačného identifikátoru), nebo jestli hledám kolekci objektů vyhovujících nějakému dotazu.
To rozdělení je podle mě šikovné i proto, že se liší návratová hodnota, první metoda vrací přímo ten objekt, druhá vrací pole těch objektů.

Radek9 [#4]:
To bych neřekl.
Ty „repozitáře“ ne že by vyloženě reprezentovaly databázi, jsou to prostě objekty, které se starají o uchování a dohledání business objektů.
Čili repozitář má zařídit, když se ho zeptám na uživatele se jménem Pepa, abych dostal seznam příslušných objektů. Odkud ty objekty vezme je jeho problém.

Má to i to kouzlo, že když je nutné něco otestovat a nemám ještě připravenou databázi nebo data, můžu si udělat třeba TestUserRepository, která mi vrátí natvrdo daná testovací data.

Pak už jen třídy pro dané subjekty třeba Users a Products ve kterých budu využívat metody getById, getByQuery, create, update a delete a tím je upravovat ?
Tohle není přesné. Třídy User a Product (raději v jednotném čísle) jsou jen výsledek, samy o tom repozitáři nepotřebují vědět.

Pracuje se s tím asi takhle- řekněme, že chci uživatele s ID 1 a pak nějak změnit jeho data:
1. Získám repozitář uživatelů (tam by šel použít vzor factory, čili nějaký systémový objekt bude mít factory metodu, která mi vrátí správný repozitář).
2. Repozitáři řeknu, že chci uživatele #1.
3. Repozitář mi vrátí objekt uživatele (typicky udělá SELECT dotaz, výsledek transformuje na příslušný objekt a ten vrátí).
4. S objektem si udělám co chci a když ho pak chci uložit:
5. Řeknu repozitáři „Ulož tenhle objekt“ a předám mu objekt uživatele.
6. Repozitář už zajistí uložení objektu (typicky udělá UPDATE dotaz).

Samotná třída User nebo Product repozitář nepotřebuje, jen se předávají dovnitř repozitáře.

Resp. pak ještě může být druhý model, kde bych měl nějakou „bázovou perzistentní třídu“, od které by ty třídy jako User, Product atd. byly odvozené a databázová logika by byla implementovaná přímo na nich.

Ale mně připadá lepší tu ukládací logiku dát na ty repozitáře, které ty business objekty jen přijímají a vracejí.
Taps
Profil
DavidOpp:
pro inspiraci si projdi http://mike.treba.cz/objekty-v-php5-navrh-databazove-tridy-dil-i-uvod-cile/ + navazující díly
Radek9
Profil
Joker:
Jasně, já to psal pro zjednodušení, protože je to nečastější případ použití repozitáře. ;-) V principu by díky té abstrakci ale mělo být samozřejmě jedno, kde se data vezmou.
DavidOpp
Profil *
Díky všem za odpověď i za link pro inspiraci, v OOP jsem začátečník a zatím to mám tak. Že zavolám metodu z DB ta mi inicializuje proměnné v třídě Request, vytvořím si metodu která mi vrací pole polí všech dat a ty pak vypisuju pomocí foreach s přídavným html pro výstup. V třídě request je i například metoda setNameProduct, v které se volá přímo sql pro update. Není to určitě 100% OOP a není to ani tak efektivní, ale věřím, že je to správný začátek se smyslem se více probírat tématikou OOP a získávat tak zkušenosti k přehlednějšímu programování. Všechny vaše odpovědi jsem již několikrát četl a procházím je googlem, jsem Vám moc vděčný za ochotu.
Jinak pořád nějak nemám ujasněné. Zda by měla být třída Database a té bych předával parametry co a kde a jak chci upravovat. Nebo jestli to mám být přímo v třídě Request když se to třeba týká konkrétně request ? Pokud chci upravit třeba název request požadavku v DB třeba s ID 5, tak SQL dotaz provedu v metodě setRequestName() ve třídě request ? Nebo to předám třídě DB ?
Moje logika spočívala v tom že mám například třídu User ta uchovává všechny informace o uživateli, kde ale mám inicializovat ty proměnné třídy User ? ve třídě DB ? Nějak v tom mám zmatek.... :-(


Kdyby mi někdo mohl pomoct tak ocením nabídky na bita.radek@seznam.cz , popřípadě nějaké dálkové doučování na pár hodin přes Skype a Team Viewer samozřejmě na ceně by jsme se dohodli. Děkuju zatím všem
Kubo2
Profil
DavidOpp:
Pokud chci upravit třeba název request požadavku v DB třeba s ID 5, tak SQL dotaz provedu v metodě setRequestName() ve třídě request ? Nebo to předám třídě DB ?
Dotaz na DB vykoná repozitár. Respektíve ten repozitár ťa úplne abstrahuje od konkrétneho úložišťa, ten repozitár môže dáta kľudne ukladať do súborov alebo posielať niekam do cloudu. Ty si len pekne krásne voláš jeho metódy a pracuješ s prepravkami na dáta User a Product (tieto iba napĺňaš dátami alebo z nich dáta ťaháš gettermi/settermi, pre uloženie/získanie sa dotazuješ repozitára).
DavidOpp
Profil *
Jojo dobře, díky moc.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: