Autor Zpráva
Jcas
Profil
Našel jsem si další seriál. (To už je asi pátý, co jsem bedlivě studoval) A víte kde jsem?
Stále na začátku.

Objekt je něco, co má nějaké vlastnosti a může se nějak chovat - tedy mít nějaké metody. Prima. Ty přirovnání na věci jsou krásné. Tam to je hezky vidět. Věc nějak vypadá a něco může dělat.
Ale jak se přenesu do PC světa, tak nevidím nic než jen část kódu, který udělá nějakou činnost.

Nyní jsem před úkolem, kdy budu z 10-ti tabulek v DB vybírat různá data. Budou se mi skládat různé kombinace dotazů(a nebude jich málo), dle toho, co uživatel bude chtít vytáhnout.
A tak mne napadlo, že třeba tohle by mohl být dobrý úkol pro testování oop.
Třída, která poskládá dotaz.

Jedna metoda nachystá sloupce, druhá tabulku, třetí podmínky.

Jenže, když se nad tím chci zamyslet. Má sql-dotaz nějaké vlastnosti? Žádné nevidím. Je to pořád dotaz na výběr z tabulek. Má třída nějaké chování? Vidím jedno jediné. Vrátí nachystaný dotaz.
Takže je to asi opět kravina?
Taps
Profil
Jcas:
pro inspiraci http://mike.treba.cz/objekty-v-php5-navrh-databazove-tridy-dil-i-uvod-cile/
juriad
Profil
V případě databází je to takové neprůhledné. Vytvářet nějakou nadstavbu nad databází je bez netriviálních zkušeností opravdu obtížné. Chce to velice dobře promyslet, abys nevytvořil něco extrémně složitého, ale aby to podporovalo vše, co od toho očekáváš.

Pro začátek bych začal sestavováním formulářů. Tam je krásně vidět, že konkrétní textové políčko je instancí třídy textInput, která je potomkem input.
Zkus si projít dokumentaci nette forms a pak příslušný zdrojový kód: https://github.com/nette/forms
Jcas
Profil
juriad:
Takže jako první testování oop navrhuješ sestavení formulářů. OK

Já právě nechci dělat komplet přístup k DB. Na to už koneckonců používám třídu $mysqli. Tam taky vidím jednotlivé její chování.
$mysqli->query()
$mysqli-fetch_assoc()
Vlastnosti moc nevidím. Jeden přístup k DB.

Já právě nyní přemýšlím pouze nad poskládáním dotazu SELECT - coč je asi už od začátku blbě, protože mám vždy jediný výsledek.
Ale jednou jsem to už dělal u tří tabulek a vzniklo mi z toho strašně velké množství kódu, který je strašně nepřehledný.

$sql = "SELECT ...."
if() {$sql .= AND...}
elseif() {$sql .= AND...}
atd
Tři tabulky mi při počtu kombinací udělali kód asi na 30 řádků.

Nicméně to jsou dvě věci. Jedna je co budu nyní dělat a druhá je pochopit to chápání objektů.
Tori
Profil
Jcas:
Třída, která poskládá dotaz.
Tohle má např. PrestaShop, viz: https://github.com/PrestaShop/PrestaShop/blob/1.6/classes/db/DbQuery.php (akorát je blbě pojmenovaná, protože se s ní dá poskládat akorát dotaz SELECT). Co se týká vlastností - mohly by tam např. být volitelné parametry dotazu ($dbQuery->useCache(boolean), $dbQuery->calcFoundRows()) nebo $dbQuery->addExplain(). Posílám ji jen pro představu, jak by mohla taková třída vypadat. Osobně ji v PS nepoužívám, příliš mnoho věcí mi v ní vadí.
Jcas
Profil
Tori:
Přesně něco takového mám celej den v hlavě. Takže to až taková blbost není (když jsem si vymyslel něco, co někdo jiný vymyslel přede mnou).
Medvídek
Profil
Takto se chová Active Records v Codeigniteru.

$this->db->select('*');
$this->db->from('blogs');
$this->db->join('comments', 'comments.id = blogs.id');
$this->db->limit(5);
$this->db->order_by('id', 'asc');
$this->db->where('id >', 5);
if(isset($to)){
    $this->db->where('id <', $to);
}
$query = $this->db->get();


$data = array(
               'title' => $title,
               'name' => $name,
               'date' => $date
            );

$this->db->where('id', $id);
$this->db->update('mytable', $data); 

Celkem pohodlný a hlavně univerzální skládání SQL, nehledě na použitém db driveru.
Alphard
Profil
A nějaká bližší identifikace skládaného dotazu? Něco jako
$select = $this->db->select('*');
$select->from(...);

Uvedený přístup se mi nezdá ideální, za pohodlné bych to neoznačoval.
Medvídek
Profil
Alphard:
Tak tohle je samozřejmě default nejjednoduší použití pro pochopení. Není problém pracovat jak je libo.

$db = $this->load->database('nejake_pripojeni');
$db->select(*);

$result = $this->db->select('title')->from('mytable')->where('id', $id)->limit(10, 20);

Pořád to vychází z http://www.phpactiverecord.org/
Jcas
Profil
Tak jsem si z důvodu trénování zkusil něco napsat.

- chtěl jsem zkusit i dědičnost a chtěl jsem tam nějak zahrnou rozdíl při definici sloupců
tabulka.sloupec vs pouze sloupec. To mě nic nenapadlo, tak jsem to nechal přímo ve volání metody a vložení další tabulky jsem mohl klidně nechat ve stejné třídě.

- s WHERE to bylo stejné. Napřed jsem si dal fc($sloupec, $hodnota, $operator). Ale pak jsem si uvědomil možnosti, které mohou být za klauzulí WHERE a opět jsem to nechal tak, že se předává jako parametr komplet podmínka.

- Další bod co jsem řešil bylo zachování správného pořadí klauzulí za sebou. To by se třeba mohlo řešit
$klauzule['SELECT'] = ......;. Ale zatím jsem to taky nechal v jedné mětodě, kde se to musí napsat ve správném pořadí.

Tak nevím, jestli to k něčemu bude. Ale je pravda, že si takto můžu v klidu projít "odeslaný formulář ve kterém budou hodnoty co vše a odkud chceme vybrat" a vklidu si mohu přidávat podmínky, řazení a případně si nachystat více dotazů.

Podobá se to už trochu OOP, nebo to jsou zase pouze zabalené funkce do třídy?

class QuerySelect {
    
    protected $tabulka;
    protected $sloupce = '*';
    protected $query = array();
    
    

// Definuje tabulku za výrazen FROM - pro všechny stejné
    public function __construct($tabulka) {
        $this->tabulka = '`'.$tabulka.'`';
    }

// $sloupce - array se sloupci pro výběr    
    public function definujSloupce($sloupce) {
        $this->sloupce = '`'. implode("`, `", $sloupce) .'`';    
    }
    
    public function vlozPodminku($podminka, $operator = "AND") {
        isset($this->podminka) ? 
        $this->podminka .= " ".$operator." ".$podminka : $this->podminka = $podminka;
    }
    
    protected function vytvorSql() {
        $this->query[] = 'SELECT';
        $this->query[] = $this->sloupce;
        $this->query[] = 'FROM';
        $this->query[] = $this->tabulka;
        
        if(isset($this->dalsiTabulka)) {
            foreach($this->dalsiTabulka as $var) {
                $this->query[] = $var;
            }
        }
        
        if(isset($this->podminka)) {
            $this->query[] = 'WHERE';
            $this->query[] = $this->podminka;
        }
        
        return $this->query;            
    }

// vrátí hodtový dotaz    
    public function vratQuery() {
        $this->sql = implode(" ", $this->vytvorSql());
        return $this->sql;
    }

}

class QuerySelectViceTabulek extends QuerySelect {
    
    public function __construct($tabulka) {
        parent::__construct($tabulka);         // definuje hlavní tabulku $this->tabulka
    }

    public function vlozTabulku($tabulka, $vazba="", $pripojeni="JOIN") {
        $this->dalsiTabulka[] = $pripojeni." ".$tabulka." ON ".$vazba;
    }
}
Joker
Profil
Jcas:
Tak nevím, jestli to k něčemu bude.
Právě proto to asi není dobré cvičení. Vlastní databázovou třídu jsem kdysi taky dělal, ale ono to nemá moc význam.

Když budu chtít úplně obecnou základní třídu pro komunikaci s databází, můžu použít nějakou už hotovou.
Na vyšší úrovni bude nějaká repository už pro konkrétní účel a další mezivrstva nebývá potřeba.
Tori
Profil
Jcas:
No to je otázka, jestli dotaz přes několik tabulek je potomkem dotazu přes jednu tabulku... Spíš by to asi byl nějaký obecný dotaz na práci s daty, který používá nějaké sloupce, nějaké tabulky, klíčová slova a podmínku where. Jeho specielní případy - čili potomci - by pak byly select, insertselect, insert, update, delete. Potomci by si pak doplnili další proměné, např. orderby, groupby nebo limit. Muselo by se ošetřit, že stejnou věc (např. výběr sloupců) lze zadávat několika voláními stejné metody (= automaticky doplňovat čárky mezi) apod.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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