環境
- CodeIgniter 3.1.11
- SQL Server 2016 SP2
発端
$sql = '
INSERT INTO user (id, name)
VALUES (
\'' . $id . '\',
N' . $this->db->escape($name) . '
)';
$this->db->query($sql);
Nプレフィックスが必要な箇所で毎回、上記のように自力でクエリを書きたくない。
$data = [
'id' => $id,
'name' => $name
];
$this->db->insert('user', $data);
クエリビルダを使った際にいい感じに Nプレフィックスを付与させたい。
対応方法
vendor\codeigniter\framework\system\core\Loader.php
内の database
メソッドを拡張する。
-
MY_Loader.php
を作成しdatabase
メソッドのコードをコピペで複製 - 拡張クエリビルダークラス読込処理を追記
application/core/MY_Loader.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Loader extends CI_Loader
{
/**
* Database Loader
*
* @param mixed $params Database configuration options
* @param bool $return Whether to return the database object
* @param bool $query_builder Whether to enable Query Builder
* (overrides the configuration setting)
*
* @return object|bool Database object if $return is set to TRUE,
* FALSE on failure, CI_Loader instance in any other case
*/
public function database($params = '', $return = FALSE, $query_builder = NULL)
{
// Grab the super object
$CI =& get_instance();
// Do we even need to load the database class?
if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
{
return FALSE;
}
require_once(BASEPATH.'database/DB.php');
+ require_once(BASEPATH.'database/DB_driver.php');
+
+ if (!isset($query_builder) or $query_builder === TRUE)
+ {
+ require_once(BASEPATH.'database/DB_query_builder.php');
+ if (!class_exists('CI_DB', FALSE))
+ {
+ $query_builder_path = APPPATH.'libraries/database/MY_DB_query_builder.php';
+ if (file_exists($query_builder_path))
+ {
+ require_once($query_builder_path);
+ }
+ }
+ }
if ($return === TRUE)
{
return DB($params, $query_builder);
}
// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$CI->db = '';
// Load the DB class
$CI->db =& DB($params, $query_builder);
return $this;
}
}
vendor\codeigniter\framework\system\database\DB_driver.php
内の escape
メソッドを拡張する。
- 拡張クエリビルダークラス
MY_DB_query_builder.php
を作成 - SQL server の際に Nプレフィックスを付与する処理を追記
application/libraries/database/MY_DB_query_builder.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB extends MY_DB_query_builder
{
}
class MY_DB_query_builder extends CI_DB_query_builder
{
/**
* "Smart" Escape String
*
* Escapes data based on type
* Sets boolean and null types
*
* @param string
* @return mixed
*/
public function escape($str)
{
if (is_array($str))
{
$str = array_map(array(&$this, 'escape'), $str);
return $str;
}
elseif (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))
{
+ if (substr($this->dsn, 0, 6) === 'sqlsrv')
+ {
+ return "N'".$this->escape_str($str)."'";
+ }
return "'".$this->escape_str($str)."'";
}
elseif (is_bool($str))
{
return ($str === FALSE) ? 0 : 1;
}
elseif ($str === NULL)
{
return 'NULL';
}
return $str;
}
}
以上で $this->db->insert()
や $this->db->update()
の際に Nプレフィックスが付与されるようになる。
$this->db->like()
を使用している場合は同じ要領で MY_DB_query_builder.php
内で _like
メソッドを拡張すれば良い。
参考
https://a-zumi.net/codeigniter3-querybuilder-extend/
https://stackoverflow.com/questions/33198127/codeigniter-add-n-in-sql-query-insert-unicode-text