0
0

More than 3 years have passed since last update.

CodeIgniter 3 のクエリビルダで Nプレフィックスを付与する

Posted at

環境

  • 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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0