Solution
Use ODBC
instead of dblib
, which provides the full functionality of PDO.
Note that there is two possible configurations of ODBC: standalone ODBC and FreeTDS with ODBC driver. From my experience, to set the character set for a connection, it must be done through FreeTDS using the ODBC driver, making the combined configuration preferable.
ODBC Setup
I searched through many different StackOverflow posts and various documentation sources on the web on how to properly install ODBC. I pulled my solution from a mixture of the following three references:
Below is the list of steps I used to configure ODBC
using FreeTDS
on a Debian based system.
TDS 8.0 supports prepared statements.
NOTE: Will not support SET NAMES a
or SET CHARSET a
on a connection; character sets need to be defined using the combined config by setting a FreeTDS attribute. Using the standalone ODBC driver defaulted the charset to ASCII
, which gave odd results. See my other post for examples of possible issues.
Install require packages:
sudo apt-get install freetds-bin freetds-common unixodbc tdsodbc
php5-odbc
freetds-bin
provides FreeTDS, as well as tsql
and isql
(used for debugging later).
freetds-common
was already installed on the system, but does not include the two debugging tools. Installing freetds-bin
at a later date after a config was defined cause no issue.
unixodbc
is the ODBC driver
tdsodbc
provides the TDS protocol for ODBC
php5-odbc
is the php module to used ODBC drivers. Note that your php version may differ from mine.
Configure Standalone unixODBC
ODBC driver settings in /etc/odbcinst.ini
:
[odbc]
Description = ODBC driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
UsageCount = 1
Create a system wide datasource name configuration in /etc/odbc.ini
:
[datasourcename]
Driver = odbc
Description = Standalone ODBC
Server = <IP or hostname>
Port = <port>
TDS_Version = 8.0
Configure unixODBC and FreeTDS:
ODBC driver settings in /etc/odbcinst.ini
:
[odbc]
Description = ODBC driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
UsageCount = 1
Create a system wide datasource name configuration in /etc/odbc.ini
:
[datasourcename]
Driver = FreeTDS_odbc
Description = Uses FreeTDS configuration settings defined in /etc/freetds/freetds.conf
Servername = datasourcename
TDS_Version = 8.0
Add the ODBC datasource name config to FreeTDS in /etc/freetds/freetds.conf
:
[datasourcename]
host = <IP or hostname>
port = <port>
client charset = UTF-8
tds version = 8.0
text size = 20971520
encryption = required
IMPORTANT: make sure that the odbc files are readable by the process
that will be reading them. If you are running your webserver using a
www-data
user, they must have the proper permissions to read those
files!
You can now set the connection character set in freetds.conf
and connect to the database with PDO as
$pdo = new PDO('odbc:datasourcename');
Testing:
Use tsql
to check that FreeTDS is configured and can connect to the database.
tsql -S datasourcename -U username -P password
Use isql
to check that ODBC is connecting properly.
isql -v datasourcename username password
Link ODBC with PHP:
Add ODBC PHP module to php.ini
by adding the following:
extension = odbc.so
Note that your php.ini
location will depend on what webserver you are using.
Use <?php phpinfo(); ?>
and view it through the webserver to find its location.
Restart Apache
EDIT:
Added information regarding character set capabilities of the driver, as I ran into issues with the standalone ODBC configuration where it would ignore any attempt to change the connection's character set.