tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

Vypočtené hodnoty z databáze jako property v entitě

před 5 lety

Etch
Člen | 404

Ahoj,

jde nějak jednoduše a pokud možno čistě v entitě nadefinovat vypočítávanou property. Například:

/**
 * @property int $id
 * @property string $name
 * @property-read int $rating
 * ...
 * ...
 * ...
 */

class User extends Entity{
}

Kde rating by se u takovéto entity počítal z mnoha různých parametrů v db. Jde takovouto věc nějak jednoduše vyřešit??

před 5 lety

jasir
Člen | 748

Možná tě nechápu, ale proč si nepřidáš jen metodu getRating() {return ...;} ?

před 5 lety

Etch
Člen | 404

Protože v getteru v entitě nelze přistoupit ani k „statementu“ ani ke connection, nelze aplikovat ani žádný „filtr“, protože daná property je basic typu a nemá žádnou „reálnou“ vazbu. Právě vytváření getteru, ve kterém by se volala nějaká statika jsem se chtěl ideálně vyhnout.

Editoval Etch (22. 11. 2014 12:30)

před 5 lety

Šaman
Člen | 2275

Metody getFoo() jsou plnohotné způsoby definování properties entit. Mají k dispozici všechny možnosti entity. Zápis v anotaci je spíš jen cukřík. Na vypočítanou hodnotu jsou přímo dělané. (Klasický příklad – mám entitu kružnice, poloměr je v databázi, tak ho pořeším přes anotaci, ale obvod a obsah budou gettery. Zvenku pak nepoznám rozdíl, kružnice bude mít tři property, z toho dvě read-only).

Píše se o tom v dokumentaci, jen nevím, jestli se mezitím nezměnily názvy některých nizkoúrovňových metod (getRow, getData, getRawData), @Tharos to za poslední rok docela upgradnul.

před 5 lety

Etch
Člen | 404

Ano to je pravda, že jsou na vypočítanou hodnotu jak dělané, jenže mi si krapet nerozumíme. Ten tvůj příklad s kružnicí totiž stojí na tom, že poloměr je nějaká reálná „vlastnost“ která je v DB (v podstatě v Row) a ty další věci vypočítáváš podle ní, jenže ten „rating“ je oproti tomu jen „virtuální“ věc.

Samotné nízkoúrovňové metody jsou v tomto případě též k ničemu, protože Row, RawData atd. neobsahují nic podstatného pro výpočet daného ratingu.

Trochu rozšířím ten příklad:

Entita User

/**
 * @property int $id
 * @property string $name
 * @property-read int|null $rating
 */

class User extends Entity{
}

Entita Item

/**
 * @property int $id
 * @property-read User[] $users m:belongsToMany m:filter(calculateRating)
 */

class Item extends Entity{
}

Pseudo filtr

public function calculateRating($statement){
    $conn = $statement->connection;
    // ...
    // ... Nějaké SQL dotazy a nějaké výpočty
    // ...
    $rating = /* ... */

    $statement->select($rating)->as('rating');
}

Rating přes entitu Item (Tady rating bude fungovat normálně „vypočítá ho filtr“)

foreach ($item->users as $user) {
    echo 'ID: '.$user->id.', Rating: '.$user->rating;
    echo  '<br><br>';
}

/**

Výstup:

    ID: 1, Rating: 395
    ID: 2, Rating: 791
    ID: 3, Rating: 0
*/

Rating přímo přes entitu User (Zde již bude rating NULL, protože na danou „virtuální“ property nelze poslat filter, z důvodu toho, že se jedná o basic type)

foreach ($userRepository->findAll() as $user) {
    echo 'ID: '.$user->id.', Rating: '.$user->rating;
    echo  '<br><br>';
}

/**

Výstup:

    ID: 1, Rating: null
    ID: 2, Rating: null
    ID: 3, Rating: null
*/

Editoval Etch (24. 11. 2014 1:02)