Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

PDO ORM diy - chainovanje metoda

[es] :: PHP :: PDO ORM diy - chainovanje metoda

[ Pregleda: 3730 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Zlatni_bg
Nikola S
Beograd

Član broj: 65708
Poruke: 4420
*.dynamic.sbb.rs.



+498 Profil

icon PDO ORM diy - chainovanje metoda10.04.2020. u 20:42 - pre 48 meseci
Pozdrav,

Poslednjih dana u ono mnogo slobodnog vremena sto ga ima gledam da na kreativan nacin ispunim prazninu... elem, resih da napravim neki MVC fw na osnovu svega onoga sto sam koristio do sada i prilagodjen ostalim tehnologijama koje koristim, uz sto manje overheada, da imam bukvalno boilerplate za aplikacije. Sredio sam neke pocetne stvari poput rutera, entry pointa, mapiranja nekih helpera, renderovanje view-ova uz sto manje PHPa a da ipak ne koristim templejting (bar ne trenutno).

Elem, stigoh do dela gde zelim da napravim ORM. Iako sam ranije u aplikacijama stalno koristio PDO kad je core php u pitanju, poslednji put kada sam pravio svoj fw (proslo 5+ god) sam koristio mysqli. Bilo kako bilo, vrlo sam upoznat sa PDO-om, ali bih zeleo da "extendujem" klasu, iliti ukratko da napravim ORM ili nesto najslicnije sto moze tome.

Osnovne funkcije su prilicno lake, modeli nemaju nikakav kod osim propertyja koji su ustvari redovi u tabeli i eventualno definicija tabele ako nije 1/1.

Problem:

Zelim da chainujem metode. Znam da svaka metoda koja se chainuje mora da vraca $this, sto negde nije problem, znam i zaobilaznice oko toga (tipa pozivanje metode preko funkcije) ali mi deluje nekako drljavo. Problem mi je da organizujem to chainovanje i iskreno voleo bih da cujem savete. Recimo (nije bukvalno ovako pisano ali za primer da jeste):

$collection = $this->db()->index(); // neka ovo bude SELECT *
$collection = $this->db()->index()->first(); // hvatanje prvog rezultata po recimo id-u

Takodje, masivni problemi mi dolaze kod joina, where-a, itd. Problematika nije mala ali ne bih da opterecujem forum vecim pitanjima, konkretno bih da se pozabavimo ovim primerom i najboljim resenjem istog.

Da li da mi sve metode mozda vracaju $this do neke finalne koja bi bila recimo get() (to je ono sto mi pada na pamet kao resenje ali bih skratio malo chainovanje) ili ima bolji nacin?
THE ONLY EASY DAY WAS YESTERDAY
 
Odgovor na temu

Deunan

Član broj: 338178
Poruke: 83
*.dynamic.isp.telekom.rs.



+21 Profil

icon Re: PDO ORM diy - chainovanje metoda10.04.2020. u 23:55 - pre 48 meseci
Ovo je poprilicno prost primer, ali cisto ideja u kojem smeru da ides:

Model:
Code:

class Product extends Model {

    protected $table = 'products';

}


Base model:
Code:

class Model {

    private $wheres = [];
    private $joins = [];

    public function where($param1, $operator, $param2)     {
        array_push($this->wheres, [$param1, $operator, $param2]);
        return $this;
    }
    public function join($table, $key1, $key2)     {
        array_push($this->joins, [$table, $key1, $key2]);
        return $this;
    }

    public function first()     {
        $joinSql = '';
        foreach ($this->joins as $join)     {
            $joinSql .= " JOIN $join[0] ON $join[1] = $join[2] ";
        }
        $whereSql = '';
        $params = [];
        foreach ($this->wheres as $i=>$where)     {
            if($i == 0)  {
                $whereSql .= ' WHERE ';
            }
            else    {
                $whereSql .= ' AND ';
            }
            $whereSql .= " $where[0] $where[1] ? ";
            array_push($params, $where[2]);
        }
        $sql = "SELECT * FROM $this->table $joinSql $whereSql LIMIT 1";
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        $user = $stmt->fetch();
        return $user;
    }
}


Koristis:
Code:

$product = (new Product())->join('prices', 'prices.product_id', 'products.id')
        ->where('id', '=', '1')
        ->join('filters', 'filters.product_id', 'products.id')
        ->where('name', '=', 'test')
        ->first();




 
Odgovor na temu

Zlatni_bg
Nikola S
Beograd

Član broj: 65708
Poruke: 4420
*.dynamic.sbb.rs.



+498 Profil

icon Re: PDO ORM diy - chainovanje metoda11.04.2020. u 00:24 - pre 48 meseci
Hvala ti na odgovoru :) S tim bas i nemam problema, kada je fiksno ono sto hocu nije problem da napravim kompleksan upit, ali ovde se radi o ORM-u ipak i moram da se vodim nepredvidivoscu. Imam dodavanje slogova u upit u svakoj metodi koja je u chainu koji posle izvrsavam metodom koja ne vraca $this i upisuje to u bazu, vraca lastInsertId, nekako mi je najlogicnije, mada cu videti jos oko toga.

Problem koji imam je da li ista metoda moze da bude i "finalna" a i ona na koju moze da se chainuje. Dakle da imam istu metodu koja moze da radi select *, a ukoliko je chainovana da dodaje slogove u upit, recimo "where".

U tvom primeru imamo recimo first() metodu koja izvrsava upit. Ja imam drugi problem, prva metoda u lancu bi nekad mogla da izvrsava upit, tipa index, a ona moze da dobije parametre za sortiranje, itd, ali i ne mora. Ako nema dodatnog chainovanja, index() bi trebalo i da odradi query i vrati rezultat a ne $this.

Znaci nije tesko resiti problem sa index()->first(); ili index()->query(); vec je problem resiti samo sa index(). Ne znam da li ovime krsim dobru praksu ili je neizvodljivo, ali je ono sto pokusavam da izvedem jer znatno smanjujem broj metoda u ORMu. Dovoljno je sto negde imam get() a negde getAll() mada nije strasno koji se od ta dva koristi (dokle god je drugi :D) ali bih da kompleksnost samog upita bude sto manja, ako se razumemo :)
THE ONLY EASY DAY WAS YESTERDAY
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
109.72.51.23



+1064 Profil

icon Re: PDO ORM diy - chainovanje metoda11.04.2020. u 01:15 - pre 48 meseci
Chainovanje podrazumeva da vracas neki objekt (ne mora obavezno isti), nad kojim ce se pozvati neki metod. To je pokupljeno iz funkcionalnog programiranja.
https://en.wikipedia.org/wiki/Currying
 
Odgovor na temu

Deunan

Član broj: 338178
Poruke: 83
*.dynamic.isp.telekom.rs.



+21 Profil

icon Re: PDO ORM diy - chainovanje metoda11.04.2020. u 01:23 - pre 48 meseci
A, nisam te razumeo.
Ne mozes da radis CHAIN na istu klasu ako nisi vratio $this. Ali, mozes da radis CHAIN na drugu klasu.

Odradis sve i zavrsis sa get(), ali ne vratis rezultat, vec klasu Collection.
Code:

...
public function get()   {
   ....
   $result = $stmt->fetch();
   return new Collection($result);
}


A u klasu Collection dodas manipulatore rezultata i implementiras Iterator:
Code:

class Collection implements Iterator  {

   private $result;
   private $pointer = 0;

    public function __construct($result)   {
        $this->result = $result;
    }

    public function toArray()  {
        // Uradis neke modifikacije koje zelis i vratis rezultat
       return $result;
   }

    public function current()    {
        return $this->result[$this->pointer];
    }

    public function next()    {
        $this->pointer++;
    }
    ....
}

Onda mozes:
$products = Product()->where(...)->get();
$array = $products->toArray();
a mozes i:
foreach($products as $product) {...}
 
Odgovor na temu

Zlatni_bg
Nikola S
Beograd

Član broj: 65708
Poruke: 4420
*.dynamic.sbb.rs.



+498 Profil

icon Re: PDO ORM diy - chainovanje metoda11.04.2020. u 20:57 - pre 48 meseci
Skapirao. Hvala puno na odgovorima. Imam malo lakse nacine za manipulaciju podacima, PDO mi dobacuje objekat, ili niz objekata, pa lako guram posle s tim, kontroler obradi sta treba pa baci u view kao parametar, a pointere nemam nesto potrebe da koristim. Tako imam u view-u mogucnost da mu pristupam kao objektu i direktno da citam propertyje i slicno. Nazalost nadao sam se da cu moci da ostavim opciju da ako nema sledece metode u lancu odradi i sam fetch, ali nema problema, napravicu par metoda za neparametarsko dobijanje date, ostale ce traziti chainovanje get() ili getAll() i to je to.

Pogledacu malo i kako je implementiran Eloquent, nisam par meseci radio nista u Laravelu pa mi je malo ostalo u secanju da ima neke metode koje mogu da budu finalne a mogu i da se chainuju, ako kojim slucajem nadjem nesto sto nismo znali... javljam :) I dalje je ovo relativno mlado.

Nego, kapiram da ce odgovor na ovo biti ne, ali opet da probam... je l' postoji nacin da metoda dobije info da li je poslednja u lancu ili jedina metoda koja se poziva? Ne znam sto ali odbijam da prihvatim najlakse resenje. Takodje, kako da organizujem sve ove metode? Extendovanje neke DB klase, extendovanje Model klase koja nasledjuje DB, traitovi? Znam da je sve to moj izbor, ali iz perspektive nekoga ko bi nekad naleteo na ovo i zeleo da primeni, gde biste voleli da vidite metode za interakciju sa db?

THE ONLY EASY DAY WAS YESTERDAY
 
Odgovor na temu

Branimir Maksimovic

Član broj: 64947
Poruke: 5534
109.72.51.23



+1064 Profil

icon Re: PDO ORM diy - chainovanje metoda11.04.2020. u 21:22 - pre 48 meseci
" je l' postoji nacin da metoda dobije info da li je poslednja u lancu ili jedina metoda koja se poziva?"

U principu ako ti treba tako nesto to znaci da moras da vracas razlicite tipove kako bi ozbezbedio da
ne moze doci do greske, ukoliko je redosled bitan. U svakom slucaju mozes cuvati i stanje objekta
pa proveriti.
 
Odgovor na temu

Zlatni_bg
Nikola S
Beograd

Član broj: 65708
Poruke: 4420
*.dynamic.sbb.rs.



+498 Profil

icon Re: PDO ORM diy - chainovanje metoda12.04.2020. u 00:21 - pre 48 meseci
Da... to sto si naveo bi mi znacilo da neko (verovatno samo ja jer cisto sumnjam da ce neko ovo koristiti kao fw) moze da mesa redosled chainovanja a da ne utice na upit. Verovatno cu ubaciti neki kontrolni niz kao promenljivu koju cu iscitavati pred izvrsavanje queryja da uzmem redosled.

A prvenstveno sam pitao da bih "prevario" php da ne vraca objekat uz pomoc if petlje, ali to mislim da nije izvodljivo, verujem da nece ni dopustiti chainovanje ako imam if pre return $this, ali probacu. Za sad mi rade osnovne funkcije svega sto bi mi zatrebalo, jedino razmisljam da pokusam da "ukradem" Laravelov fazon gde se tipa u klasi User definise metoda (recimo) cash(), pa onda pravim hasMany relaciju direktno u modelu i User moze da mi vrati vrednost iz te druge tabele putem $user->cash()->cash() i slicno. Opet, trudim se da ovo bude sto laganije moguce, cak razmisljam da ne koristim ni composer jer mi je imperativ na laksim/manjim stvarima da se koristi a da se opet postuje MVC, a za MVC u PHPu je neophodan bar ruter i kvazi-render viewova zbog separacije... pa nek ide i ovo uz to, sa jos nekim helper funkcijama, itd.

Trenutno sto se DB dela tice razmisljam da li da ubacim migracije (definisanje strukture kreiranja sql tabele) i neku CLI skriptu koja bi to sama odradila generisuci i model. Ne znam kakvi su vasi saveti za to, migracije nisam voleo dok nisam krenuo vise da koristim Laravel, sad ih ne bih menjao ni za sta.
THE ONLY EASY DAY WAS YESTERDAY
 
Odgovor na temu

VladaSu

Član broj: 31634
Poruke: 1099
*.tippnet.co.rs.



+218 Profil

icon Re: PDO ORM diy - chainovanje metoda20.04.2020. u 06:38 - pre 47 meseci
NIsam dugo gledao ali bilo je puno gotovih db klasa koje rade na ovakav nacin.
Ako neces neku metodu da chainujes onda ne vracas $this.
Ako ne zelis da ti je bitan redosled onda svaki lanac treba da ti se zavrsava npr se execute() gde ces sa predhodnim metodama samo setovati promenljive, sa execute kreirati sql, izvrsiti ga, resetovati setovane promeljive i na kraju vratiti rezultata.
Rezultat bi opet trebao da bude neki objekat gde ces moci uzeti npr first, last, count, total itd
[Ovu poruku je menjao VladaSu dana 14.06.2003. u 11:22 GMT+1]
 
Odgovor na temu

[es] :: PHP :: PDO ORM diy - chainovanje metoda

[ Pregleda: 3730 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.