Nette + Dibi + connect přes PDO driver kvůli MSSQL

před 6 lety

wb2009
Člen | 125
+
0
-

Zdravím,

nějak s tím bojuji, ale potřeboval bych nastavit config.neon, abych se mohl připojit přes Dibi PDO driver na náš MSSQL server.

v PHP jsem se připojoval přes dibi takto:

$options = array(
    'driver' => 'pdo',
    'pdo' => new PDO("sqlsrv:Server=IPSERVERU;Database=CCA", 'user', 'pass')
);
$connection = new DibiConnection($options);

no a teď bych potřeboval něco podobného v nette s ím, že v budoucnu se budu připojovat na více databází, takže nejlepší bude abych využil config.neon. Co jsem si prohlížel forum, tak tady sice pár věcí je, ale nedokázal jsem to podle toho zprovoznit, navíc ne všechno řešení tu mi připadalo jako nejlepší. Takže ocením jakýkoliv správný postup, radu co mám mít v configu, co v bootstrapu, budu rád. Předem píši, že odkazy typu Netted/database vs. Dibi apod. již mám pročtené.

před 6 lety

Filip Procházka
Moderator | 4693
+
0
-
$pdo = new PDO("sqlsrv:Server=IPSERVERU;Database=CCA", 'user', 'pass');

$dibi = new DibiConnection(array(
    'driver' => 'pdo',
    'resource' => $pdo
));

před 6 lety

wb2009
Člen | 125
+
0
-

hm, díky, v podstatě si upravil můj předchozí kód, ale žádné info k tomu si nenapsal, co s tím, super help :)

před 6 lety

Filip Procházka
Moderator | 4693
+
0
-

@wb2009: Ty ses s tím info taky nepředal ;) Tvůj kód jsem opravil, protože jsem myslel, že ho máš špatně.

Takže chceš tohle?

services:
    db:
        class: DibiConnection({host: localhost, password: root, username: root})

    dbSecond:
        class: DibiConnection({host: localhost, password: root, username: root})
        autowired: false

    dbThird:
        class: DibiConnection({host: localhost, password: root, username: root})
        autowired: false

před 6 lety

wb2009
Člen | 125
+
0
-

Jop :), to je přesně ono a ještě potřebuji vědět, jestli je potřeba něco v bootstrapu? Resp. co potřebuji udělat, abych např. v presenteru mohu udělat:

$db->query(...);

Jinak knihovnu dibi mám klasicky nahranou v libs.

před 6 lety

Filip Procházka
Moderator | 4693
+
0
-

Bestpractise je předávat si závislosti do presenterů/modelů pomocí typehintu. Nette pak pozná, že třída v konstruktoru chce DibiConnection a předá ji.

Ideálně si tedy vytvoř nějaké modelové třídy a ty nakonfiguruj takto

services:
    articles: App\Articles(@db)
    users: App\Users(@dbSecond)

Potom si je v presenteru vyžádáš pomocí inject, nebo trošky magie.

před 6 lety

wb2009
Člen | 125
+
0
-

Díky, vyzkouším :)

před 6 lety

xxxmisko
Člen | 140
+
0
-

Ahoj!

Dnes som skúsil premigrovanie db z postgresu do mssql 2008, avšak mám problém s pripojením dibi do databázy. Najskôr ladenka hučala, že žiaden mssql driver nie je k dispozícii, po prečítaní fóra som nainštaloval do wamp servera ovládače pre mssql, konkrétne som tam povolil:

extension=php_sqlsrv53_ts_vc9.dll
extension=php_pdo_sqlsrv53_ts_vc9.dll

teraz mám sqlsrv aj v phpinfo, ale neviem, ako to rozbehať s dibi. Skúšal som nejaké kombinácie, v config.neon mám:

database:
            driver: pdo
            host: 127.0.0.1
            username: miso
            password: miso
            database: test
            lazy: TRUE
            profiler:
                run: true

a v bootstrap.php mám

dibi::connect($container->parameters['database']);

Prosím o pomoc, ako to rozbehať a takisto, či som postupoval správne.

Ďakujem každému.

před 6 lety

jiri.pudil
Člen | 856
+
0
-
database:
    driver: pdo
    dsn: ...
    username: miso
    password: miso
    (...)

Jak vypadá DSN pro MSSQL najdeš tu.

před 6 lety

xxxmisko
Člen | 140
+
0
-

@jiri.pudil

upravil som to takto:

database:
            driver: pdo
            dsn: 'pdo:server=localhost;database=test'
            username: miso
            password: miso
            database: test
            lazy: TRUE

a teraz ladenka vypisuje:

could not find driver

Kurňa, som na správnej ceste? Funguje dibi s mssql bez problémov? :(

před 6 lety

nanuqcz
Člen | 844
+
0
-

xxxmisko napsal(a):

database:
          driver: pdo
          dsn: 'pdo:server=localhost;database=test'
          username: miso
          password: miso
          database: test
          lazy: TRUE

ten dsn bude určitě začínat ‚sqlsrv:‘, pokud používáš sqlsrv driver ;-)

před 6 lety

xxxmisko
Člen | 140
+
0
-

@nanuqcz

prepísal som v dsn pdo na sqlsrv a teraz ladenka vypisuje chybku:

PDO or driver does not support applying limit or offset

File: ...\libs\dibi\drivers\pdo.php   Line: 382

throw new DibiNotSupportedException('PDO or driver does not support applying limit or offset.');

Treba ešte niečo upraviť, alebo by to v takomto stave malo fungovať?
:(

před 6 lety

nanuqcz
Člen | 844
+
0
-

Tak už ti to asi funguje :-) Problém je, že v MS SQL neexistuje příkaz LIMIT, jak ho znáš z MySQL. Takže ani driver pro Nette ho nemůže podporovat. Viz google

EDIT: Zkus tedy použít nějaký jednoduchý SELECT dotaz, bez příkazu LIMIT, mělo by to fungovat.

Editoval nanuqcz (9. 4. 2013 16:54)

před 6 lety

xxxmisko
Člen | 140
+
0
-

@nanuqcz

problém je, že ja nikde limit a ani offset nepoužívam :D Konkrétne toto mi vypisuje po prihlásení užívateľa. Podľa quickstartu som postupoval :( Neviem, prečo ja mám vždy s niečím problém, keď iným to funguje korektne :D

před 6 lety

xxxmisko
Člen | 140
+
0
-

@nanuqcz

zistil som niečo takéto:

https://forum.dibiphp.com/…seni-pre-pdo

Vraj je tam problém s fetch a fetchSingle pri použití PDO. Dá sa to nejako vyriešiť? Zrejme tam bude ten problémik s tým limitom.

před 6 lety

Milo
Nette Core | 1148
+
0
-

@xxxmisko Postni sem kód, kde ten fetch používáš. Podle jakého Quick startu jdeš? Nette nebo Dibi?

Anebo si zkus upravit DibiPdoDriver, metodu applyLimit().

case 'odbc':
case 'mssql':
case 'sqlsrv': // přidat
if ($offset < 1) {
    $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ')';
    break;
}

Editoval Milo (10. 4. 2013 10:49)

před 6 lety

xxxmisko
Člen | 140
+
0
-

@milo

budeme si písať tu? :D

takže kód som zmenil, teraz mi ukazuje chybu:

SQLSTATE[42000]: [Microsoft][SQL Server Native Client 10.0][SQL Server]Incorrect syntax near ')'

pdo.php
126:                    throw new DibiDriverException("SQLSTATE[$err[0]]: $err[2]", $err[1], $sql);

Vygenerovaný select:

"SELECT TOP 1 * FROM ( SELECT login_heslo, id_login FROM login WHERE login_meno='admin')"

spúšťam ho takto:

return $this->db->select('login_heslo, id_login')->from('login')->where('login_meno=%s', $username)->fetch();

Quick start som myslel v nette, pričom dibi sa mi úspešne podarilo rozchodiť pri mysql, pqsql, ale mssql ešte váha :D

Editoval xxxmisko (10. 4. 2013 11:14)

před 6 lety

Milo
Nette Core | 1148
+
0
-

Před chvilkou jsem poslal Pull request do dibi. Koukni na ty commity, měly by pomoct.

před 6 lety

Milo
Nette Core | 1148
+
0
-

Jo a pardon. Můžeme pokračovat na dibi fóru, tam to téma zapadne lépe.

před 6 lety

xxxmisko
Člen | 140
+
0
-

@milo

Môžeme ešte tu, nakoľko sa to bude týkať nette.

Tie tvoje pull requesty som si nahodil, už mi to skladá pekný select, avšak mám problém s dátami. Vygeneruje sa mi takýto select:

SELECT TOP 1 * FROM ( SELECT login_heslo, id_login FROM [login] WHERE login_meno='admin') t

Avšak, dibi akoby nepoznalo pripojenie. Skúšal som tento select spustiť v sql management studio, nešiel. Zistil som, že treba pred table pripojiť [nazov_db].[dbo].[tabulka]. Potom som v management studiu nastavil, aby sa user defaultne nastavil do db, a select zbehol. Avšak v configu, neviem, ako zapísať nejaký Initial Catalog.

Môj config je takýto:

database:
    driver: pdo
    dsn: 'sqlsrv:server=localhost;database=test'
    username: miso
    password: miso
    database: test
    lazy: TRUE
    profiler:
        run: true

Keď som skúsil do dsn napísať Initial Catalog=test namiesto database, dostal som chybu. Prosím o radu, verím, že toto bude už všetko, čo treba :D

před 6 lety

Milo
Nette Core | 1148
+
0
-

Ne nesouvisí s Nette ani dibi. Nastav uživateli defaultní schema na dbo. http://msdn.microsoft.com/…s189462.aspx

EDIT:
A pokud se připojuješ k databázi test a pak selectuješ z databáze abcd, musíš provést USE abcd po connectu.

Editoval Milo (10. 4. 2013 13:29)

před 6 lety

xxxmisko
Člen | 140
+
0
-

@milo

schému dbo mám nastavenú pre užívateľa správne. Pripájam sa k databáze test, potom selektujem z tabuľky login, pričom v sql server management studio ju vidím ako dbo.login, používa schému dbo

Prosím, kde by som mal v tých príkazoch nastaviť use dajme tomu moju tabuľku?

Editoval xxxmisko (10. 4. 2013 14:47)

před 6 lety

xxxmisko
Člen | 140
+
0
-

už som zistil, kde je chyba, ale neviem, ako ju vyriešiť :(

$dsn = ‚sqlsrv:server=localhost;database=test;‘;

dibi::connect(array(
‚driver‘ ⇒ ‚pdo‘,
‚pdo‘ ⇒ new PDO($dsn),
‚database‘ ⇒ ‚test‘,
‚host‘ ⇒ ‚localhost‘,
‚username‘ ⇒ ‚miso‘,
‚password‘ ⇒ ‚miso‘
));

toto ma prosím pekne pripojí a dokonca získam aj dáta. A teraz otázka, ako to zapísať do nette. Database config je o post vyššie, pripojenie v bootstrap.php je :

dibi::connect($container->parameters['database']);

ĎAKUJEM KAŽDÉMU ZA POMOC!!!

před 6 lety

Milo
Nette Core | 1148
+
0
-

Příkazem USE nastavuješ databázi, ne tabulku.

Do config.neon si přidej:

services:
    dibi: DibiConnection([
        driver: 'pdo'
        dsn: 'sqlsrv:server=localhost;database=test'
        username: 'miso'
        password: 'miso'
    ])

A v prezenteru pak můžeš namísto statického dibi:: používat:

$db = $this->context->dibi;
$db->query('SELECT ....')->fetch();

a pokud používáš dev verzi z githubu, najdi si tady na fóru něco o injectXxxx() metodách v prezenteru.

Editoval Milo (11. 4. 2013 10:15)

před 6 lety

nanuqcz
Člen | 844
+
0
-

No, pokud byl problém v tom, že z

dsn: 'sqlsrv:server=localhost;database=test'

bylo potřeba udělat

dsn: new PDO('sqlsrv:server=localhost;database=test')

tak config.neon by měl vypadat takto:

services:
    pdo: PDO('sqlsrv:server=localhost;database=test')
    dibi: DibiConnection([
        driver: 'pdo'
        dsn: @pdo
        username: 'miso',
        password: 'miso',
    ])

Zbytek jak píše Milo.

Editoval nanuqcz (10. 4. 2013 20:15)

před 6 lety

Milo
Nette Core | 1148
+
0
-

@nanuqcz: Funguje to, ale úplně z jiného důvodu, a to, aby se existující připojení dalo obalit do Dibi. Nevidím důvod, proč to tak dělat, navíc se ani nepoužije zadané heslo a username takže je to akorát matoucí. Takže takhle ne.

Editoval Milo (10. 4. 2013 19:40)

před 6 lety

nanuqcz
Člen | 844
+
0
-

Jo, už to vidím, napsal jsem blbost :-) Omlouvám se a původní příspěvek zaškrtávám.

před 6 lety

xxxmisko
Člen | 140
+
0
-

@Milo

zajtra to vyskúšam, pôjdem tvojou cestou.

čo sa týka použitia dibi, normálne si ho injectujem:

public function inject(Namespace\Repository $db){
$this->db = $db;
}

a repositary ho má takto:

/** @var \DibiConnection */
protected $db;

public function __construct(\DibiConnection $connection)
{
    $this->db = $connection;
}

používam dibi fluent príkazy v štýle

$this->db->select(*)->from('clovek')->where('[vyska]=%i', $vyska)->fetchAll();

Čo v podstate zmenia tie riadky, keď ich pridám do configu? Tie nastavenia database tam môžem nechať bez problémov?
Ďakujem, zajtra ráno píšem a dám vedieť, ako som dopadol!

před 6 lety

xxxmisko
Člen | 140
+
0
-

Chlapi, ono to naskočilo a ide to. Ešte mám nejaké drobné problémiky s príkazmi, ale vyriešim to. Ešte otázka, čo keby som celý postup spísal a niekde nahodil? Možno by to niekomu v budúcnosti mohlo pomôcť.

před 6 lety

wb2009
Člen | 125
+
0
-

Všechny zdravím,

ještě bych potřeboval poradit:

v součastné chvíli my vše funguje a config nenon mám takto:

production < common:
#   parameters:
#       # nastavení databází pro produkci
#       database:



development < common:
    parameters:
        # nastavení databází pro development
        database:
            driver: 'pdo'
            dsn: 'sqlsrv:server=SERVER;database=DATABASE'
            user: 'user'
            password: 'pass'

a v bootstrapu:

$db = $container->parameters['database'];

jak ale o proměnné db dám vědět presenteru, nebo modelu? Resp. to si to musím zaregistrovat jako službu? Mě se to ale líbí tak jak to je, tedy nastavení pro production a develpment… nějaké best řešení a nejrychlejší?

před 6 lety

Milo
Nette Core | 1148
+
0
-

@wb2009: Nejsi nucen vytvářet služby přes config.neon. V prezenteru si můžeš udělat např:

public function getDatabase()
{
    return new DibiConnection($this->context->parameters['database']);
}

Každopádně přes službu v config.neon je to pohodlnější:

common:
    services:
        dibi: DibiConnection(%database%)

        # nebo víc ukecaně
        dibi: DibiConnection([
            driver: %database.driver%
            dsn: %database.dsn%
            username: %database.driver%
            password: %database.username%
        ])

production < common:
    parameters:
        database:
            driver: 'pdo'
            dsn: '...'
            username: '...'
            password: '...'

development < common:
    parameters:
        database:
            driver: 'pdo'
            dsn: '...'
            username: '...'
            password: '...'

ale na tohle téma je toho na fóru kvantum…

před 6 lety

wb2009
Člen | 125
+
0
-

Hele díky, já o tom věděl a několikrát četl, ale nešlo mi to rozchodit, nakonec jsem idiot, protože jsem to v tom neonu měl ještě něco navíc, ale já si toho všiml až teď :)

Paráda funguje, snad to alespoň pomůže třeba někomu v budoucnu, připojení i na více db je easy… :)

    services:
        dibi: DibiConnection(%database%)
        dibi2: DibiConnection(%database2%)
....
production < common:
    parameters:
        # nastavení databází pro produkci
        database:
            driver: 'pdo'
            dsn: 'sqlsrv:server=SERVER;database=DATABASE'
            user: 'user'
            password: 'pass'

development < common:
    parameters:
        # nastavení databází pro development
        database:
            driver: 'pdo'
            dsn: 'sqlsrv:server=SERVER;database=DATABASE'
            user: 'user'
            password: 'pass'
        database2:
            driver: 'pdo'
            dsn: 'sqlsrv:server=SERVER;database=DATABASE'
            user: 'user'
            password: 'pass'
...

a v bootstrapu:

$db = $container->parameters['database'];
$db2 = $container->parameters['database2'];

a pak jen např v presenteru:

$this->context->dibi...
$this->context->dibi2...

Editoval wb2009 (11. 4. 2013 10:42)

před 6 lety

xxxmisko
Člen | 140
+
0
-

Čaute chlapi.

Tak a som tu znova.

Píšem príkazy cez dibi fluent, ale pri použití offset sa vygeneruje zlý dotaz.

Pri mssql by mal generovať niečo ako …rows BETWEEN 5 AND 10, ak je použitý limit a offset.

Prosím, nemáte niekto upravenu dibi, kde funguje korektne mssql?

PS: asi by som potreboval iba podmienky v súbore pdo.php. Zajtra sa do toho pustím, ale ak to má niekto spravené, podeľte sa :D

Ďakujem

Editoval xxxmisko (24. 4. 2013 21:06)

před 6 lety

wb2009
Člen | 125
+
0
-

Co znamená zlý dotaz?

Dibi pracuje korektně s MSSQL. Je potřeba říct, že MSSQL a MySQL nemají úplně stejnou syntaxi SQL dotazů, takže když my jsme migrovali pod MSSQL museli jsme spoustu dotazů upravovat, nebo předělávat, MySQL je trochu benevolentní oproti MSSQL. Poznaš to hlavně u group by funkce.

Takže ti asi nezbyde nic jiného než třeba ty funkce, které si používal v MySQL vyhledat v googlu, jak se zapisují v MSSQL(např. místo now() getDate() apod.) případně napiš, co ti nejde…

před 6 lety

xxxmisko
Člen | 140
+
0
-

@wb2009

Problém mám takýto:

Potrebujem použiť limit – funguje.
Potrebujem použiť offset – not implemented
Potrebujem použiť limit a a offset – detto.

Ja som upravoval pdo.php, potrebujem tam pridať úpravu toho selectu, aby správne vygeneroval iba potrebné hodnoty.

riadok, ktorý som pridal do pdo.php:

case 'sqlsrv':
            if ($offset < 1) {
                $sql = preg_replace('/SELECT/', 'SELECT TOP '. (int) $limit .' ', $sql, 1);
                break;
            }

ak by si vedel pomôcť, bol by som veľmi rád.