Nette + Dibi + connect přes PDO driver kvůli MSSQL
- wb2009
- Člen | 125
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é.
- Filip Procházka
- Moderator | 4668
$pdo = new PDO("sqlsrv:Server=IPSERVERU;Database=CCA", 'user', 'pass');
$dibi = new DibiConnection(array(
'driver' => 'pdo',
'resource' => $pdo
));
- Filip Procházka
- Moderator | 4668
@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
- Filip Procházka
- Moderator | 4668
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.
- xxxmisko
- Člen | 140
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.
- jiri.pudil
- Nette Blogger | 1029
database:
driver: pdo
dsn: ...
username: miso
password: miso
(...)
Jak vypadá DSN pro MSSQL najdeš tu.
- xxxmisko
- Člen | 140
@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ť?
:(
- nanuqcz
- Člen | 822
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)
- xxxmisko
- Člen | 140
@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.
- Milo
- Nette Core | 1283
@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)
- xxxmisko
- Člen | 140
@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)
- Milo
- Nette Core | 1283
Před chvilkou jsem poslal Pull request do dibi. Koukni na ty commity, měly by pomoct.
- xxxmisko
- Člen | 140
@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
- Milo
- Nette Core | 1283
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)
- xxxmisko
- Člen | 140
@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)
- xxxmisko
- Člen | 140
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!!!
- Milo
- Nette Core | 1283
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)
- nanuqcz
- Člen | 822
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)
- xxxmisko
- Člen | 140
@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!
- wb2009
- Člen | 125
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ší?
- Milo
- Nette Core | 1283
@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…
- wb2009
- Člen | 125
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)
- xxxmisko
- Člen | 140
Č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)
- wb2009
- Člen | 125
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…
- xxxmisko
- Člen | 140
@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.