otazky zacatecnika, obecne MVC, prace s db,

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
LovecAnimuk
Člen | 9
+
0
-

Zdravim lidicky, poslednich par dnu jsem operoval s myslenkou udelat novy projekt pod objektovym php, nakonec tedy s vyuzitim frameworku, konkretni volba pak byl nette :)
Ze zacatku to sice vypadalo, ze tuto oblast kompletne opustim, kdyz jsem se stval s uvodnim tutorialem (nemyslim, ze za vsechny chyby jsem mohl nutne ja, ale to je v tuto chvili jedno :) )
Kazdopadne konkretne k dotazum, profesi jsem databazista, ale s vecma jako oop apod. se do styku dostavam, avsak to oop mysleni mi jeste uplne nejde :)

Potreboval bych na strance zobrazit nahodne 2 ruzne uzivatele z tabulky uzivatelu.
Tudiz ocekavam, ze by to mohlo vypadat nasledovne

Sablona: zobrazeni nicku uzivatele pomoci promenne
Prezenter: zavolani metody z modelu, kde bude podminka, ktereho uzivatele nevracet (pouzitelnost pro oba uzivatele)
model: samotny select do databaze (reseno formou dvou modelu, manager a trida typu radku tabulky)

jak to ale napsat? :) zatim mam neco takoveho:

sablona:

{block content}
<table>
    <tr><th>fighterA</th><th>fighterB</th></tr>
    <tr>
        <td n:foreach="$fighterA as $avatar">{$avatar->name}</td>
        <td n:foreach="$fighterB as $avatar">{$avatar->name}</td>
    </tr>
</table>

Presenter:

<?php

final class FightPresenter extends BasePresenter
{

        private $fightManager = NULL;

      public function actionShowFighters()
      {
        $this->template->fighterA = $this->model->findAvatar($where = array(
            'id' => 1,
        )); //nyni fixne, v modelu resit random
        $this->template->fighterB = $this->model->findAvatar($where = array(
            'id' => 2,
        ));
      }

/*
      public function renderShowFighters()
      {
        //$this->template->message = 'We hope you enjoy this framework!';
      }
*/
      public function getModel()
      {
         if(!isset($this->fightManager))
            $this->fightManager = new FightManager;

         return $this->fightManager;
      }

}
?>

Modely:

<?php
class FightManager
{
    public function findAvatar($where = NULL)
    {
        return dibi::query(
            'SELECT * FROM [avatars]',
            '%if', isset($where), 'WHERE %and', isset($where) ? $where : array(), '%end'
        )->setRowClass('Avatar');
    }
}
?>
<?php
class Avatar extends DibiRow
{
    public function __construct($arr = array())
    {
        parent::__construct($arr);
    }
}
?>

Je to aspon naznak spravnym smerem? Jak predat parametr funkci findAvatar jake id ma prvni volany uzivatel a ktereho uz tudiz nevybirat?

Dekuji za pomoc, snad se to da po m pochopit ;)

regiss
Člen | 61
+
0
-

Ahoj nevim jestli jsem te uplne pochopil, toz navrhnu jak bych to udelal ja.

Osvedcilo se mi pouzivat BaseModel(kde nastavim spojeni) a pak ostatni modely dedi od nej.

<?php
//file BaseModel.php
use Nette\Object;

abstract class BaseModel extends Object {

    private static $connection;

    public function getConnection() {
        if (self::$connection == NULL) {
            self::$connection = new DibiConnection(\Nette\Environment::getConfig()->database);
        }

        return self::$connection;
    }
}
?>
<?php
//file DB_Avatar.php
use Nette\Object;

class DB_Avatar extends BaseModel
{
    public function getRandomUser()
    {
        return $this->connection->select('*')
                ->from('Users')
		->where('some condition')
		->orderBy("rand()")
                ->limit(2);
    }
}
?>

Pak to vytahnes v presenteru

$query = new DB_Avatar();
$this->template->avatars = $query->getRandomUser()->fetchAll();

A predas do sablony

{foreach $avatars as $avatar}
  {$avatar}
{/foreach}

Doufam, ze jsem tam nenasekal moc chyb :)

LovecAnimuk
Člen | 9
+
0
-

diky za nastin moznosti, vyuziti BeseModelu jako predka jsem tu taky zkousel.
V tomto reseni dat kontrolu, aby nebyl vybran stejny uzivatel na prezenter nebo do modelu?
A jak pripadne vybrat hodnotu drive vybraneho uzivatele?
diky za pomoc

edit: ted jsem se podival poradne a vidim, ze rovnou tahas 2 uzivatele z db, to je taky moznost, ale asi by bylo vhodnejsi z logiky aplikace je tahat zvlast

Editoval LovecAnimuk (16. 12. 2010 9:05)

LovecAnimuk
Člen | 9
+
0
-

Jeste bych tedy upresnil co aktualne bych potreboval zodpovedet, pokud by mel nekdo cas :)
1] v ramci MVC/MVP kam davat vypocty apod. do presenteru nebo do modelu? (vypocty jsou myslene operace nad daty z db apod.)
2] nejake tutorialy(literatura) o praci v nette, kde by nebyly funkce jen pro volani dat z db, ale i nejaka logika? (trochu navazuje na minulou otazku, v ramci nette jde o ciste objektove phpko nebo je jeste nejak upravene?)

Vychazi to z toho uvodniho prikladu o zobrazeni dvouch ruznych nahodnych uzivatelu z tabulky.
Kdyby slo o normalni phpko neni co resit, zavolam funkci na vyhledani prvniho uzivatele v db(vyberu jich treba vice a randomem vyberu jednoho z nich), ulozim si id do promenne, zobrazim ho, vyhledam druheho uzivatele s vyloucenim id prvniho a zobrazim.
V nette a obecne MVC nevim kam tuhle logiku dat a jak ji napsat :)

diky za pripadny help a nasmerovani.

Šaman
Člen | 2635
+
0
-

Obecně, jestli nemáš zkušenosti s MVC-MVP ani s Nette, tak bych doporučoval začít bez modelu (první aplikace, seznámíš se s frameworkem).

Budeš mít jen presenter (zařizuje kompletní aplikační logiku) a pohledy (šablony a zobrazovací logika). Pak je jasné, že SQL půjde do presenteru.

A až se trochu rozkoukáš, tak začneš řešit problémy jako: potřebuji načítat uživatele podle ID, podle loginu, potřebuji všechny uživatele z jedné firmy, potřebuji dva náhodné uživatele – nebylo by dobré vytvořit si třídu Users a načítat vše na jednom místě? A začne ti vznikat model.

A pak můžeš jít ještě dál – načítací metody vrátí buď objekt MyUser (bo User je už zabraný Nette) nebo kolekci objektů. Kolekce (class Users) je třída potomků ArrayObject a umí řadit a filtrovat. (Takže řazení výsledků z různých dotazů se provádí jednotně.) Potom ještě zjistíš že je velmi praktické mít servisní vrstvu modelu a budeš s modelem tam co já teď.

Nebo ti ani to nebude stačit a třeba přijdeš na chuť pětivrstvému modelu


Proč jsem se tak rozepsal? Protože není jednoznačný návod jak na model. Vše, od prasení SQL do presenteru až po komplexní model o mnoha vrstvách je možné a za určitých podmínek i vhodné. Takže radši začni od nejjednoduššího (a taky od nejpodobnějšího s procedurálním programováním) a až zjistíš proč mít složitější model, tak na něj přejdi.

LovecAnimuk
Člen | 9
+
0
-

Diky za info, mas pravdu, ze takhle to bude idealni, proste do modelu vytesnovat postupne veci tykajici se db apod.
Akorat jeste otazecka, nejaky pripadny link na literaturu, ukazkove priklady apod. tutorialy zde na nette mam projite.
Nebo se pak jedna v podstate o ciste objektove php? a hledat tedy literaturu tykajici se toho? s tim, ze nette pak pomuze s tou rozsirnou architekturou na MVP
diky

Šaman
Člen | 2635
+
0
-

Nette ti pomůže s řízením celé aplikace a pokud budeš vycházet ze Skeletonu (teď je to tuším Sandbox) a tutoriálů, tak tě navede na správné oddělení aplikační a zobrazovací logiky.

Na databázi prý dneska vyšel commit který přidává přímo do Nette (zatím experimentálně) práci s db. Nicméně doteď bylo k dispozici Dibi, což je Davidova databázová vrstva která si s Nette super rozumí.

Já osobně používám obecnou SQL syntax a Dibi používám jen na rychlejší a objektové volání dotazu. Samozřejmě se hodí pár dalších fičurek které dotaz zpřehlední a celý zápis zjednoduší. Akorát si nastuduj možnosti jak upravit výsledek dotazu (metody fetch, fetchAll, fetchSingle a fetchAssoc) to je hodně killer fičurka.
Možností dibi je ale více, např. objektové skládání dotazu viz. dokumentace.

Další možností je použít notORM. Vypadá to, že Nette\Database bude vycházet z obou výše uvedených knihoven.

Možností je spousta (v doplňcích jsou tuším dva ORMy pro Nette, někdo doporučuje Doctrine) ale Dibi a notORM budou zřejmě Nette provázet dále.

S objektovostí či neobjektovostí si hlavu nelámej. Všechno v Nette se snaží být objektové ale pokud nezačneš používat nějaký ORM tak se změní jen zápis jak zavolat SQL dotaz. Rozhodně na to abys používal Dibi nepotřebuješ vědět o OOP skoro nic.

Editoval Šaman (16. 12. 2010 13:50)

LovecAnimuk
Člen | 9
+
0
-

Opet diky za info. Osobne s dibi problem nemam, kdyz vezmu v potaz, ze kdyz jsem naposled delal vetsi projekt, tak jsem si vsechny funkce pripravoval sam, tak tohle je velka uleva :)

Spise se musim prehodit z proceduralnio mysleni na oop, at uz na urovni prezenteru nebo modelu :)