Pripojeni k databazi MySQL

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

Dobry vecer, uz pres 3 hodiny se marne snazim pripojit k databazi (i kdyz to se mi uz mozna podarilo) MySQL a vypsat vsechny clanky z tabulky „test“. Prohledal jsem kompletne forum na ruzne fraze, prosel si priklad s deskami v slozce examples ale stale se mi nedari dosahnout vysledku.

Obracim se na Vas tedy s prosbou, zda nekdo nemate nejaky velmi jednoduchy priklad na:

  • pripojeni k db MySQL
  • vypis vsech dat z dane tabulky

jsem z toho uz opravdu zoufaly, snazim se nette pochopit ale zatim mi dela vice starosti nez uzitku :)

dekuji za ochotu a nebo nasmerovani na nejaky sikovny clanek (zde na foru to uz asi nema cenu, mam to projite snad vse).

s pozdravem Tom Nikl

_Martin_
Generous Backer | 679
+
0
-

Ahoj, nejprve otázka: jak pracuješ v PHP s DB? Používáš nějaké ORM? Nebo nějaký layer (třeba dibi)?

Pokud ti něco říká pojem MVC, tak MySQL spadá do části, které se říká model. Psaní modelů v Nette je ponecháno čistě na tvůrci aplikace. Většinou se k tomu využívají výše zmíněná ORM. Jsou-li modely jednodušší, lze si napsat vlastní modely bez použití cizích ORM (třeba s využitím již uvedeného dibi layeru).

tomasnikl
Člen | 137
+
0
-

k praci s db pouzivam dibi, jiz se mi podarilo dokonce pripojit k db coz jse necekal… vsude ovsem bylo psano ze nejlepsi je davat udaje do config.ini, ovsem to mi jaksi nefungovalo, tak jsem to vyresil jinym zpusobem.. pripojuju se takto v bootstrap.php (asi to neni vhodne ale to pozdeji vychytam, teprve se ucim a zkousim si co vse nette umi)..

dibi::connect(array(
    'driver'   => 'mysql',
    'host'     => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'nette',
    'charset'  => 'utf8',
));

dale kdyz do DefaultPresenter.php vlozim nasledujici kod:

$text = "I'm fine";
dibi::query('UPDATE `pavel` SET `text`=%s WHERE id=1', $text);

tak mi to v databazi aktualizje tak jak ma.. z cehoz jsem nadseny ze mi to funguje :).. ovsem nedokazu vypsat veskery obsah teto tabulky (ma pouze sloupce ID a TEXT).. takze nyni potrebuji poradit pouze s timto jak tak koukam…

kdybych si to psal po svem bez nejakeho frameworku tak je to pro mne otazka 3minut, ale vsude ctu ze frameworky usnadnuji praci tak si rikam, proc to nezkusit :o) a zjistuju ze misto 3minut je pro me vypis obsahu tabulky otazkou 3hodin :o))) snad to jednohodo dne pochopim :)

Editoval tomasnikl (23. 11. 2009 17:41)

Ondřej Mirtes
Člen | 1536
+
0
-

Udělej si BaseModel:

abstract class BaseModel extends Object {

    private static $db;

    public function getDb() {
        if (self::$db == NULL) {
            self::$db = new DibiConnection(Environment::getConfig('database'));
        }

        return self::$db;
    }
}

Díky tomuto modelu pak ve všech jeho potomcích budeš mocí přistupovat k instanci dibi přes $this->db.

Tento model počítá s takovýmto nastavením v config.ini (pokud se ti nedaří rozběhat config, napiš důvod, pomůžeme):

[common]
database.driver = mysqli
database.lazy = TRUE
database.charset = utf8
; dalsi nastaveni tvoji aplikace...

[development < common] ; vývojová mašina
database.host = localhost
database.database = db
database.username = user
database.password = ***

[production < common] ; produkční server
database.host = localhost
database.database = db
database.username = user
database.password = ***

Samotný model (třída pracující s databází) by mohla vypadat takto:

class TestModel extends BaseModel {

	public function getTest() {
		return $this->db->fetchAll('SELECT id, test FROM [table]');
	}

}

V Presenteru data předáš do šablony:

class DefaultPresenter extends BasePresenter {

	public function renderDefault() {
		$model = new TestModel;
		$this->template->data = $model->getTest();
	}

}

A v šabloně je vypíšeš:

<table>
	<tr><th>ID</th><th>Test</th></tr>
	{foreach $data as $row}
	<tr>
		<td>{$row->id}</td>
		<td>{$row->test}</td>
	</tr>
	{/foreach}
</table>
tomasnikl
Člen | 137
+
0
-

Dekuju za radu, uz to pomalu zacinam chapat..ale vyhazuje mi to chybu

Class ‚BaseModel‘ not found

File: C:\xampp\htdocs\test\nette\app\presenters\DefaultPresenter.php Line: 6

Line 6: $model = new TestModel;

DefaultPresenter.php mam nasledujici:

<?php

class DefaultPresenter extends /*Nette\Application\*/Presenter {

        public function renderDefault() {
                $model = new TestModel;
                $this->template->data = $model->getTest();
        }

}
?>

BaseModel.php (ve slozce models):

<?php
abstract class BaseModel extends Object {

    private static $db;

    public function getDb() {
        if (self::$db == NULL) {
            self::$db = new DibiConnection(Environment::getConfig('database'));
        }

        return self::$db;
    }
}
?>

TestModel.php (ve slozce models):

<?php
class TestModel extends BaseModel {

        public function getTest() {
                return $this->db->fetchAll('SELECT id, test FROM [nette]');
        }

}
?>

nevite kde by mohla byt chybka? nejspis jeste neco nekde musim definovat…

Diky za rady.

Tom Nikl

Editoval tomasnikl (23. 11. 2009 18:21)

Ondřej Brejla
Člen | 746
+
0
-

Promazal si temp adresář? Používáš RobotLoader?

Editoval Ondřej Brejla (23. 11. 2009 18:28)

tomasnikl
Člen | 137
+
0
-

Ondřej Brejla napsal(a):

Promazal si temp adresář? Používáš RobotLoader?

temp je kupodivu prazdny.. RobotLoader? predpokladam ze nepouzivam, k nette jsem se dostal teprve vcera a poradne ani nevim co RobotLoader je a nikde jsem nic nenastavoval.. ale co jsem tak prohlizel forum a rady, tak tusim ze robotLoader se zminoval v config.ini… prikladam tedy i config.ini zda v nem nenajdete nejakou chybku:

[common]
; PHP configuration
php.date.timezone = "Europe/Prague"
php.iconv.internal_encoding = "%encoding%"
php.mbstring.internal_encoding = "%encoding%"

; services
;service.Nette-Security-IAuthenticator = Model\Users

service.Nette-Loaders-RobotLoader.option.directory[] = %appDir%
service.Nette-Loaders-RobotLoader.option.directory[] = %libsDir%
service.Nette-Loaders-RobotLoader.run = TRUE

[common]
database.driver = mysqli
database.lazy = TRUE
database.charset = utf8

; vývojová mašina
[development < common]
database.host = localhost
database.database = nette
database.username = root
database.password =

; produkční server
[production < common]
database.host = localhost
database.database = nette
database.username = root
database.password =
Ondřej Brejla
Člen | 746
+
0
-

Nahráváš config.ini v bootstrapu?

tomasnikl
Člen | 137
+
0
-

Ondřej Brejla napsal(a):

Nahráváš config.ini v bootstrapu?

ano ano, zde je kod bootstrap.php

<?php

// Step 1: Load Nette Framework
// this allows Nette to load classes automatically so that
// you don't have to litter your code with 'require' statements
require_once LIBS_DIR . '/Nette/loader.php';

// načte konfiguraci (nezadám-le jméno souboru, výchozí je '%appDir%/config.ini')
Environment::loadConfig(APP_DIR . '/config.ini');

// Step 2: Enable Nette\Debug
// for better exception and error visualisation
Debug::enable();

// Step 3: Get the front controller
$application = Environment::getApplication();

// Step 4: Run the application!
$application->run();
?>

Editoval tomasnikl (23. 11. 2009 18:46)

tomasnikl
Člen | 137
+
0
-

aha, tak jsem to zksuil postavit na „skeleton“ prikaldu ktery je v archivu kdyz se to stahne… a vypada to ze jsem pokrocil o krok dal. nyni se mi to cele seklo na:

Notice: Undefined index: test in C:\xampp\htdocs\test2\app\temp\c-Nette.Template\_9e45da1783f500c64b85498978987100.default.phtml.php on line 26

zkousel jsem temp i promazat ale nepomohlo… zkusim se v tom jeste pohrabat, treba z toho neco vyleze :)

//edit:
tak uz to funguje jak ma :)… v posledni chybe byl nejaky problem se sloupcem v tabulce.. „Ondřej Mirtes“ si asi spatne precetl muj dotaz a misto sloupce „text“ psal „test“ :)

Editoval tomasnikl (23. 11. 2009 19:29)

Endrju
Člen | 147
+
0
-

Ondřej Mirtes napsal(a):

Udělej si BaseModel:

abstract class BaseModel extends Object {

    private static $db;

    public function getDb() {
        if (self::$db == NULL) {
            self::$db = new DibiConnection(Environment::getConfig('database'));
        }

        return self::$db;
    }
}

Díky tomuto modelu pak ve všech jeho potomcích budeš mocí přistupovat k instanci dibi přes $this->db.

Tento model počítá s takovýmto nastavením v config.ini (pokud se ti nedaří rozběhat config, napiš důvod, pomůžeme):

[common]
database.driver = mysqli
database.lazy = TRUE
database.charset = utf8
; dalsi nastaveni tvoji aplikace...

[development < common] ; vývojová mašina
database.host = localhost
database.database = db
database.username = user
database.password = ***

[production < common] ; produkční server
database.host = localhost
database.database = db
database.username = user
database.password = ***

Samotný model (třída pracující s databází) by mohla vypadat takto:

class TestModel extends BaseModel {

	public function getTest() {
		return $this->db->fetchAll('SELECT id, test FROM [table]');
	}

}

V Presenteru data předáš do šablony:

class DefaultPresenter extends BasePresenter {

	public function renderDefault() {
		$model = new TestModel;
		$this->template->data = $model->getTest();
	}

}

A v šabloně je vypíšeš:

<table>
	<tr><th>ID</th><th>Test</th></tr>
	{foreach $data as $row}
	<tr>
		<td>{$row->id}</td>
		<td>{$row->test}</td>
	</tr>
	{/foreach}
</table>

Ondro, prosim te, co zapricini, ze se vola metoda getDb() ve tride BaseModel? Nikde jsem si nevsiml, ze by se nekde volala a presto to bez teto funkce nemuze fungovat. vsude pak v dedenych Modelech pristupuji k promenne $this->db, ale kde jsem tuto promennou naplnil? Je dost mozne, ze mi unika neco zakladniho, ale vrta mi to hlavou a byl bych rad, kdyby se mi to nekdo pokusil objasnit. Dekuji moc!

mkoubik
Člen | 728
+
0
-

Ondro, prosim te, co zapricini, ze se vola metoda getDb() ve tride BaseModel? Nikde jsem si nevsiml, ze by se nekde volala a presto to bez teto funkce nemuze fungovat. vsude pak v dedenych Modelech pristupuji k promenne $this->db, ale kde jsem tuto promennou naplnil? Je dost mozne, ze mi unika neco zakladniho, ale vrta mi to hlavou a byl bych rad, kdyby se mi to nekdo pokusil objasnit. Dekuji moc!

To zařídí třída Object, kterou dědí BaseModel. Je to takovej pomocník, kterej dělá z php použitelnej objektovej jazyk. Pokud přistupuješ k private proměnné, pak se použije getter (pro čtení – getPromenna()) nebo setter (pro zápis – setPromenna($hodnota)). Je dobrý třídu, která by jinak nic nedědila podědit z Object, ulehčí ti to spoustu práce. Víc tady.

Endrju
Člen | 147
+
0
-

mkoubik napsal(a):

Ondro, prosim te, co zapricini, ze se vola metoda getDb() ve tride BaseModel? Nikde jsem si nevsiml, ze by se nekde volala a presto to bez teto funkce nemuze fungovat. vsude pak v dedenych Modelech pristupuji k promenne $this->db, ale kde jsem tuto promennou naplnil? Je dost mozne, ze mi unika neco zakladniho, ale vrta mi to hlavou a byl bych rad, kdyby se mi to nekdo pokusil objasnit. Dekuji moc!

To zařídí třída Object, kterou dědí BaseModel. Je to takovej pomocník, kterej dělá z php použitelnej objektovej jazyk. Pokud přistupuješ k private proměnné, pak se použije getter (pro čtení – getPromenna()) nebo setter (pro zápis – setPromenna($hodnota)). Je dobrý třídu, která by jinak nic nedědila podědit z Object, ulehčí ti to spoustu práce. Víc tady.

Ahaaaa, tak ted je mi to mnohem jasnejsi! Netusil jsem, ze to funguje jako getter a setter :).

Takze kdyz bych mel metodu getPromenna() a setPromenna(), ktera by nastavovala nejakou private promennou $xyz,

tak tuto promennou nastavuji tak za zavolam treba $this->promenna = neco (v tomto pripade se vola metoda setPromenna()) a naopak $neco = $this->promenna; (zde se zase vola metoda getPrommena()).

Je to presne tak nebo se mylim? (Znam to takto z .NET c#).

Jenom mi taky pak trochu nesedi, ze promenna $db je static a metoda, ve ktere k teto promenne pristupuji (tedy getDb()) static neni. Nevim jak to ma byt, ale tusim, ze tak jak jsem zvykly z .NET bych v non-static metode nemohl pristupovat ke static promennym. Kdyz tak me pls opravte pokud je to jinak, diky :)!

mkoubik
Člen | 728
+
0
-

Ahaaaa, tak ted je mi to mnohem jasnejsi! Netusil jsem, ze to funguje jako getter a setter :).

Takze kdyz bych mel metodu getPromenna() a setPromenna(), ktera by nastavovala nejakou private promennou $xyz,

tak tuto promennou nastavuji tak za zavolam treba $this->promenna = neco (v tomto pripade se vola metoda setPromenna()) a naopak $neco = $this->promenna; (zde se zase vola metoda getPrommena()).

Je to presne tak nebo se mylim? (Znam to takto z .NET c#).

Je to přesně tak.

Jenom mi taky pak trochu nesedi, ze promenna $db je static a metoda, ve ktere k teto promenne pristupuji (tedy getDb()) static neni. Nevim jak to ma byt, ale tusim, ze tak jak jsem zvykly z .NET bych v non-static metode nemohl pristupovat ke static promennym. Kdyz tak me pls opravte pokud je to jinak, diky :)!

To je pokud vím obráceně. Ze statické metody nemůžeš přistupovat k nestatické proměnné, ale z nestatické metody můžeš přistupovat ke statické proměnné (která je pro všechny instance třídy společná).

SyXcz
Člen | 75
+
0
-

Zdravím, at se znažim jak se snažim, pořát mi mysql nejede, hlásí mi

Class ‚DibiConnection‘ not found

neměl bych dibi.php načítat v bootstrapu v kroku 1 stejně jako loader.php ???

Editoval SyXcz (7. 3. 2010 11:40)

22
Člen | 1478
+
0
-

zkus to :-)

SyXcz
Člen | 75
+
0
-

hm teď mi zas hlásí „Configuration must be array, string or ArrayObject.“. File: C:\xampp\htdocs\syx_new\libs\dibi\libs\DibiConnection.php Line: 68

zřejmě mi nenačítádatabázi z config.ini

ale přitom ho načítam

<?php
// Step 1: Load Nette Framework
// this allows load Nette Framework classes automatically so that
// you don't have to litter your code with 'require' statements
require LIBS_DIR . '/Nette/loader.php';
require LIBS_DIR . '/dibi/dibi.php';



// Step 2: Configure environment
// 2a) enable Nette\Debug for better exception and error visualisation
Debug::enable();

// 2b) load configuration from config.ini file
new DibiConnection(Environment::getConfig('database'));
Environment::loadConfig();



// Step 3: Configure application
// 3a) get and setup a front controller
$application = Environment::getApplication();
$application->errorPresenter = 'Error';
//$application->catchExceptions = TRUE;
?>

atd.. atd…

neni tu někde funkční tutoriál k používání mysql? quick-start pořát neni a na fóru to každej používá jinak, a ať zkoušim jak zkoušim, nejede :(

Editoval SyXcz (7. 3. 2010 12:02)

SyXcz
Člen | 75
+
0
-

jaj už mi to asi jede, měl jsem to asi obráceně

<?php
// 2b) load configuration from config.ini file
Environment::loadConfig();
dibi::connect(Environment::getConfig('database'));
?>

už jen vyzkoušet v nějakym presenteru jestli s DB pracuje…

chemikus
Člen | 49
+
0
-

Tak a teď jsem suveréně v koncích. Mám

bootstrap.php

<?php
// Step 1: Load Nette Framework
// this allows load Nette Framework classes automatically so that
// you don't have to litter your code with 'require' statements
require LIBS_DIR . '/Nette/loader.php';
require LIBS_DIR . '/dibi/dibi.php';


// Step 2: Configure environment
// 2a) enable NDebug for better exception and error visualisation
NDebug::enable();

// 2b) load configuration from config.ini file
NEnvironment::loadConfig();
dibi::connect(NEnvironment::getConfig('database'));



// Step 3: Configure application
// 3a) get and setup a front controller
$application = NEnvironment::getApplication();
$application->errorPresenter = 'Error';
//$application->catchExceptions = TRUE;



// Step 4: Setup application router
$router = $application->getRouter();

$router[] = new NRoute('index.php', array(
	'presenter' => 'Homepage',
	'action' => 'default',
), NRoute::ONE_WAY);

$router[] = new NRoute('<presenter>/<action>/<id>', array(
	'presenter' => 'Homepage',
	'action' => 'default',
	'id' => NULL,
));

// Step 5: Run the application!
$application->run();
?>

Pak mám config

[production < common]
; common database connection
database.driver = mysql
database.database = hodnoti_cz
database.charset = utf8
database.lazy = TRUE
database.host = localhost
database.username = *******
database.password = *******


[development < common]
; database options in development mode
database.profiler = TRUE
database.host = localhost
database.username = root
database.password = newpwd

A jediný co mi to vypíše je

InvalidArgumentException

Configuration must be array, string or ArrayObject.

A když se podívám na argumenty, které se předávají

 dibi/dibi.php (191) source ►  DibiConnection-> __construct (arguments ▼)
$config

NConfig(4) ▼ {
   "profiler" => "1"
   "host" => "localhost" (9)
   "username" => "root" (4)
   "password" => "newpwd" (6)
}

Můžete mi někdo prosím sdělit, co a kde mám špatně?

EDIT

Problém vyřešen změnou jednoho řádku

<?php
dibi::connect(NEnvironment::getConfig('database')->toArray());
?>

btw. Určitě byste to měli změnit i v tutoriálu, protože se to vůbec neshoduje ;-) A hlavně, v nové verzi se používají už N… zatímco v tutoriálu je to bez N ;-)

Editoval chemikus (16. 9. 2010 13:04)