Microsoft Drivers for PHP for SQL Server Team Blog – All about the Microsoft Drivers for PHP for SQL Server, SQL Server and PHP (SQLSRV and PDO_SQLSRV)より、Microsoft SQL Server 2005 Driver for PHP v1.0 のリリースが案内された。ドキュメントはこちら→SQL Server 2005 Driver for PHP Documentationphp_mssql.dllとは異なりntwdblib.dllは不要。Windows環境のPHPからMS-SQLへの接続ならこちらが便利と思われる。

早速、CakePHPで使えるようにしてみた。ドライバを適宜インストール後、php.iniも書き換え 以下をAPP/models/datasources/dbo/dbo_sqlsrv.phpとして保存し、APP/config/datables.phpで 'driver' => 'sqlsrv' とすると無事接続できた。細かなテストはこれからする。

<?php

uses('model' . DS . 'datasources' . DS . 'dbo' . DS . 'dbo_mssql');

class DboSqlsrv extends DboMssql {

    var $description = "SQL Server 2005 Driver for PHP";

    var $_baseConfig = array(
        'persistent' => true,
        'host' => 'localhost',
        'login' => 'root',
        'password' => '',
        'database' => 'cake',
    );

    function __construct($config)
    {
        if (!function_exists('sqlsrv_connect')) {
            trigger_error($this->description  . " is not installed, cannot continue.", E_USER_ERROR);
        }
        return DboSource::__construct($config);
    }

    function connect()
    {
        $this->connection = sqlsrv_connect($this->config['host'], array(
            'Database' => $this->config['database'],
            'ConnectionPooling' => $this->config['persistent'] ? 1 : 0,
            'UID' => $this->config['login'],
            'PWD' => $this->config['password'],
        ));
        $this->connected = false;
        if ($this->connection !== false){// && sqlsrv_query($this->connection, 'USE ' . $this->config['database'])) {
            $this->connected = true;
        }
    }

    function disconnect()
    {
        @sqlsrv_free_stmt($this->results);
        $this->connected = !@sqlsrv_close($this->connection);
        return !$this->connected;
    }

    function _execute($sql)
    {
        return sqlsrv_query($this->connection, $sql);
    }

    function begin(&$model)
    {
        if (parent::begin($model)) {
            if (sqlsrv_begin_transaction($this->connection)) {
                $this->_transactionStarted = true;
                return true;
            }
        }
        return false;
    }

    function commit(&$model)
    {
        if (parent::commit($model)) {
            $this->_transactionStarted = false;
            return sqlsrv_commit($this->connection);
        }
        return false;
    }

    function rollback(&$model)
    {
        if (parent::rollback($model)) {
            return sqlsrv_rollback($this->connection);
        }
        return false;
    }

    function lastError()
    {
        if (($errors = sqlsrv_errors()) != null) {
            $msg = '';
            foreach($errors as $e) {
                $msg .= "SQLSTATE: " . $e['SQLSTATE'] . "  ";
                $msg .= "CODE: " . $e['code'] . "  ";
                $msg .= "MESSAGE: " . $e['message'] . "    ";
                break;
            }
            return $msg;
        }
        return null;
    }

    function lastAffected()
    {
        if ($this->_result) {
            $cnt = sqlsrv_rows_affected($this->_result);
            if ($cnt < 0) $cnt = 0;
            return $cnt;
        }
        return null;
    }

    function lastNumRows()
    {
        if (is_resource($this->_result)) {
            $cnt = -1;
            $stmt = sqlsrv_query($this->connection, 'SELECT @@ROWCOUNT AS cnt');
            if (sqlsrv_fetch($stmt)) {
                $cnt = sqlsrv_get_field($stmt, 0);
            }
            return $cnt;
        }
        return null;
    }

    function resultSet(&$results)
    {
        $this->results =& $results;
        $this->map = array();
        $meta = sqlsrv_field_metadata($results);
        $num_fields = count($meta);
        $index = 0;
        $j = 0;

        while ($j < $num_fields) {
            $column = $meta[$j]['Name'];
            if (strpos($column, '__')) {
                if (isset($this->__fieldMappings[$column]) && strpos($this->__fieldMappings[$column], '.')) {
                    $map = explode('.', $this->__fieldMappings[$column]);
                } elseif (isset($this->__fieldMappings[$column])) {
                    $map = array(0, $this->__fieldMappings[$column]);
                } else {
                    $map = array(0, $column);
                }
                $this->map[$index++] = $map;
            } else {
                $this->map[$index++] = array(0, $column);
            }
            $j++;
        }
    }

    function fetchResult()
    {
         if (sqlsrv_fetch($this->results)) {
            $resultRow = array();
            foreach (sqlsrv_field_metadata($this->results) as $index => $field) {
                list($table, $column) = $this->map[$index];
                $resultRow[$table][$column] = sqlsrv_get_field($this->results, $index);
            }
            return $resultRow;
        } else {
            return false;
        }
    }

}
?>