Vista x64: SQL Server 2008 driver pro PHP na IIS7
IIS7 je výkonná platforma pro provozování nejenom ASP.NET aplikací, ale s FastCGI modulem také PHP skriptů. Při použití Windows serveru a IIS7 se rovněž nabízí použít jako databázi SQL Server 2008, namísto funkčně zaostalé MySQL 5.x.
PHP pro napojení na SQL Server používá dvě knihovny - mssql
a pdo_mssql
. Ani jedna z nich ovšem není dobrá a funkčně zůstávají někde v roce 1997.
Řešením pro PHP a SQL Server 2008 je nativní driver od Microsoftu - SQL Server 2005 Driver for PHP verze 1.0. Přestože má v názvu 2005, tak je postaven a funguje 100% i pro SQL Server 2008. K instalaci budete potřebovat i SQL Server Native Client, a to ve verzi 2005 (přestože máte instalovaný 2008 Server), 64bitová varianta je ke stažení zde.
Driver bohužel nenabízí nic, co by vám usnadnilo konverzi mezi UCS2LE (nativní kódování pro data v SQL Serveru, které ovšem pro změnu nepodporuje IE ani WebKit - Safari a Google Chrome) a UTF-8.
Buď vám budou stačit jednobajtová kódování jako je CP1250 anebo se musíte postarat o konverzi mezi UTF-16LE (s tímto kódováním pracuje PHP driver) a UTF-8 před uložením do databáze a po načtení dat.
Práce s SQL Server 2008 není v PHP tedy tak dobrá jako v .NET, kde si kódování snadno specifikujete, ale s troškou práce na datové vrstvě můžete tuto databázi používat de-facto na 100%.
Související: dokumentace pro SQL Server Driver for PHP na MSDN
Myslím, že než si přidávat práci a zdržovat scripty voláním iconv, tak je lepší používat pdo_mssql nebo se této databázi vyhnout úplně. Zlatá věštkyně :)
Na druhou stranu nechápu, jak dnes něco nemůže počítat s UTF-8. Zvlášť, když je to cíleno na web.
[1] pdo_mssql není řešení. Otestuj si je někdy v praxi...
[2] A co nastavit kódování MS SQL na UTF-8? Nejde?
Jo, MSSQL je na jednu stranu vcelku fajn databáze ale má i své stinné stránky. Asi nejpalčivějším problémem je z mého pohledu cena licence. Můj bývalý zaměstnavatel platil za licenci nějakých 120k, což rozhodně není málo. Druhá věc, která mi lezla na nervy, bylo stránkování. V MySQL použiju LIMIT. V MSSQL nic takového není/nebylo a řešili jsme to šíleným dotazem (díky bohu za procedury).
Pak je tu taky ta sranda s kódováním, různé oplétačky s datumem (IMO ale chyba PHP driveru) a taky celkem snadno bobtnající logy (5GB za noc nebylo výjimkou).
Každopádně "podpora" MSSQL v PHP je chabá. Ten driver stojí/stál za houby a nakonec jsem musel používat obchvaty přes jiná řešení, abych se z něj nezbláznil. Ale slušně jsem se namlsal na některé hodně promakané věci a rozumět tomu, tak už se snažím je zavést do MySQL :)
[1] Pokud je ten někdo Microsoft, tak nepočítání s něčím je zcela normální chování.
[3] vlastní MSSQL databázový engine pracuje jen se singlebyte collation (varchar) anebo Unicode (UCS2; nvarchar, ntext, nchar), a je to logické, v UTF-8 zabírá každý znak různý počet bajtů, s čímž se hodně špatně pracuje. UTF-8 je prostě pomalé.
Jsou dvě cesty jak to řešit - pracovat v UCS2 a před "vypuštěním" stránky ji převést celou na UTF-8, anebo na úrovni požadavků na databázi. Osobně jsem pro to jednodušší i rychlejší řešení - převod pomocí iconv() na celé stránce.
[4] na stránkování je snadno použitelné ROW_NUMBER().
[5] Zajímalo by mě tedy, proč jsi se rozhodl používat na webu MS SQL 2008, když ti to spíše hází klacky pod nohy. Na ten driver jsem se díval a taky to není žádná sláva, když to porovnám s tím, co nabízí Oracle. Je to jen kvůli dobré integraci s Windows Server 2008? Myslím, že kvůli MS SQL 2008 s PHP musíš dělat až moc kompromisů na to, aby se to dalo používat.
[4] MSSQL existuje i v edici Express, která je zdarma. Sám ji využívám na webu a vše je bez problémů. Dokonce existuje několik verzí. Jedna z nich obsahuje i fulltext, po doinstalování i s podporou češtiny.
Na stránkování se dá použít funkce ROW_NUMBER(), která je implementována od verze 2005 a stránkování je pak ďábelsky rychlé (i na pomalých strojích) i při velkém množství záznamů. Zkuste si zastránkovat tento výpis http://aquatab.net/system/prehled-druhu/...
[7] Předpokládám, že Express verze ale bude mít nějaká omezení, ať už po stránce technické (omezený počet databází, maximální velikost databáze...) nebo po stránce licenční (možnost používat jen k nekomerčním účelům, maximálně jeden CPU).
Já ani netuším jakou verzi jsme to vlastně měli. Staral se o to především kolega. On byl přes tu databázi machr. Vím jen, že jsem tehdy potřeboval stránkování a našel jsem na to snad přímo v dokumentaci nějaký šílený dotaz. Kolega pak napsal proceduru, kterou jsme následně používali všude.
Já se přes MSSQL dotal k pohledům a procedurám, které jsem pak začal využívat i v MySQL - omezeně, protože MySQL ještě pořád neumí co by měla/bych si přál. Konečně ale MySQL beztak používám jen na jednodušší projekty. Složitější věci mám na PostgreSQL nebo Firebirdu.
Pokusil jsem se přidat podporu do dibi (http://dibiphp.com ). Výhoda dibi je v tom, že umí transparentně převádět kódování. Bohužel nemám MS SQL server a nechce se mi stahovat 1 GB zkušební verze, takže pokud by se našel někdo ochotný to otestovat, budu rád za feedback.
Přípojit se lze takto:
dibi::connect(array(
'driver' => 'mssql2005',
'host' => '(local)',
'options' => array(
...
),
));
kde položky host a options odpovídají parametrům funkce sqlsrv_connect.
Par upresneni a oprav:
1) podpora sql 2008 timto driverem je prirozena a mozna proto, ze sql2008 je plne zpetne kompatibilni az k verze sql 2000 (vcetne nastaveni modu databaze). O samotnou komunikaci s sql 2008 se stejne stara SQL Server Native Client 2005
2)neznam detailne vnitrek PHP, ale nutnost konverze UTF-16LE na UTF-8 a zpet povazuji na chybu SQL driveru pro PHP.
Vsechny nativni a i prastare ODBC drivery tuto konverzi delaji/delali sami, a to i pro prastare technologie typu ASP.
Zkusil bych jeste zaexperimentovat s atributem "AutoTranslate" v conn.stringu k DB, jestli nedonuti PHP driver k nejake rozumenjsi automaticke konverzi kodovani. viz http://msdn.microsoft.com/en-us/library/cc296161...(SQL.90).aspx , resp.
http://msdn.microsoft.com/en-us/library/ms130822.aspx...
3) Rozhodne doporucuji ignorovat SQL collation (z mnoha duvodu) a vyhradne pozivat n-kove (nvarchar, ntext, ..) datove typy. S vyjimkou 0.1% kritickych aplikaci je vykon stejny, pri lepsim komfortu.
4) "... v .NET při použití ADO, kde si kódování snadno specifikujete..." - v ADO / ADO.NET se kodovani nespecifikuje. Vzdy se pracuje interne v UTF-8 (u textu).
Kodovani se specifikuje (volitelne) pri IO operacich (mimo ADO)
[6] to není o kompromisech, použití T-SQL značně urychlí celou aplikaci, kompromisní by bylo a vždy je použití MySQL
[10] konverze UTF-8 -- UTF-16LE není zjevně u SQL Serveru věc driveru, i když by mohla být, ale DB komponent. V .NET to nakonec také nedělá přímo "driver", ale komponenty. Škoda je, že nejde (nebo jsem nepřišel na to jak) specifikovat u driveru charset pro klienta, jako to má třeba Oracle. Překládat každý vstup/výstup na úrovni DB layeru se mi zdá jako zbytečná zátěž pro PHP.
Jinak je hezké, že odkazuješ na Connection String, ale v něm prostě specifikace charsetu pro překlad není.
Naopak přímo na MSDN se doporučuje "prasácká" metoda pomocí iconv: http://msdn.microsoft.com/en-us/library/cc626307(SQL.90).aspx.
Nicméně je to spíše detail, který by člověka neměl odradit. To mě spíše vytáčí Oracle 10g, který nemá AUTOINCREMENT / IDENTITY fields, a musí se to řešit přes sekvence a triggery.
[7] jen bych doplnil:
Microsoft® SQL Server® 2008 Express with Advanced Services
Tato edice je zdarma i pro komerční účely a ostrý běh (nejenom pro vývoj) a obsahuje nejen vlastní server, ale i slušné vývojářské nástroje (SQL Server Management Studio Express), za které se jinde platí... SQL Server 2008 je tedy v této edici zdarma a je výrazně lepší než MySQL. Dobře zpracovaná je i dokumentace na MSDN.
[5] UTF-16 je taky kódování s proměnlivým počtem bajtů na znak (konkrétně dva nebo čtyři bajty). UCS-2 naproti tomu ne - každý znak zabírá dva bajty, takže nejdou uložit znaky s kódem nad U+FFFF.
[12] jistě, zde je to trošku nutno upřesnit - SQL Server (nvarchar, ntext) používá interně UCS-2, nicméně PHP driver to prezentuje jako UTF-16LE. Neumí bohužel překlad na UTF-8. Mimochodem některé komponenty (XML) v SQL Serveru umí interně i UTF-16, aby to nebylo tak jednoduché :-)
Nebo jinak: z pohledu klientské aplikace mě UCS-2 příliš nezajímá, PHP driver pracuje výhradně s UTF-16LE.
[11] Radku, prosim cti pozorne: "Zkusil bych jeste zaexperimentovat s atributem "AutoTranslate"...".
tebou odkazovane MSDN jsem samozrejme cetl.
AutoTranslat a Auto Translate atributy v cnn.stringu jsou pro zapnuti/vypnuti Ansi/OEM konverze.
To byla odjakziva slusna alchymie a cerna dira, ktera se chovala zahadne, ale v dobe pred ADO.NET casto prepnuti na true ci false pomohlo.
Je to ciste experimentalni tip, ktery nemusi pomoci
[14] toto nemá vliv (otestováno), PHP driver pracuje natvrdo v UTF-16LE. Mohu samozřejmě ukládat klidně UTF-8, ale poté bude zlobit řazení, atd. v DB. AutoTranslate dělá totiž něco jiného - překlad ANSI -- UCS2 -- ANSI, aby se zajistilo, že veškeré znaky lze uložit a jsou "validní".