<?php
/**
* @version EC-CUBE4系
* @copyright 株式会社 翔 kakeru.co.jp
*
* 2021年12月05日作成
*
* app\Customize\Service\SqlService.php
*
* SQL文を作成する
*
* このクラスを変更する場合は株式会社 翔の許可を取ってください
* 2021/12/07修正 WHERE句 AS句 スペースを修正
* 2021/12/07 AS句 スペースを修正
* 2022/08/18 IN区 パラメーター化
*
* ≡≡≡┏(^o^)┛
*****************************************************/
namespace Lm\Service\Db;
use Lm\Service\Cache\CacheService;
use Lm\Service\Cache\LmCacheTrait;
class SqlService
{
use LmCacheTrait {
LmCacheTrait::__construct as __traitConstruct;
}
const READ = true;
const WRITE = false;
const AS_SYMBOL = 'T'; #Tableの簡略化名 AS句
const AS_PATAN = '/^[T0-9]+\./';
#初期値
const DEF = '';
#戻り値
const RE = null;
const SELECT = self::AS_SYMBOL . '.* ';
const ParamKIgo = ':P_';
protected static $_Connect = [];
#DB接続
protected $Connect; #Object;
protected $Stmt; #object
protected $Table_;
protected $Select_ = '';
protected $Selects_ = [];
protected $Set_ = [];
protected $Sql_;
protected $Values_ = [];
protected $Where_ = [];
protected $WhereLogical = [];
protected $Param_ = [];
protected $Order_ = [];
protected $OrderBy_;
protected $Join_ = [];
protected $Limit_;
protected $OffSet_;
protected $Group_;
protected $ConName;
protected $Num = 0;
protected $ForeignKey_ = 1;
protected $Column_ = [];
#SQl分をエコーで表示する パラメーターは配列
protected $ViewFlg;
/**
* コンストラクト
* DBの接続
*/
function __construct()
{
$cacheService = new CacheService();
//
$this->__traitConstruct($cacheService);
//
$this->Connect = $this->ConnectDB(false);
}
function ConnectDB($forceReconnect = false)
{
if ($forceReconnect || empty(self::$_Connect)) {
$dbManagerRead = new DbManager([], self::READ);
$dbManagerWrite = new DbManager([], self::WRITE);
self::$_Connect[self::READ] = $dbManagerRead->get();
self::$_Connect[self::WRITE] = $dbManagerWrite->get();
return self::$_Connect;
} else {
return self::$_Connect;
}
}
/**
* 初期化
* SQL 発行後変数の初期化します
*/
protected function Initialize()
{
$this->Table_ = null;
$this->Select_ = '';
$this->Selects_ = [];
$this->Set_ = [];
$this->Where_ = [];
$this->WhereLogical = [];
$this->Param_ = [];
$this->Order_ = [];
$this->OrderBy_ = [];
$this->Join_ = [];
$this->Limit_ = null;
$this->OffSet_ = null;
$this->Group_ = null;
$this->Values_ = [];
$this->Sql_ = null;
$this->Num = 0;
$this->ViewFlg = false;
$this->Stmt = null;
$this->Column_ = [];
if (0 == $this->ForeignKey_) {
$this->ForeignKey_ = 1;
}
$this->ForeignKey_ = null;
}
/**
* getter
*
* @return string
*/
public function getSql()
{
return $this->Sql_;
}
/**
* シングルの連想配列を返す
* @param int $ViewFlg $ViewFlg 1 #SQl分をエコーで表示する パラメーターは配列 2 exit 付き
*
* @return array 無ければ NULLを返す
*/
public function Find($ViewFlg = 0)
{
$this->ViewFlg = $ViewFlg;
#Select分 の作成
$this->MakeSelect();
$Value = $this->Fetch();
return $Value ? $Value : self::RE;
}
/**
* リストとして連想配列で返す
* @param int|bool $Flg $ViewFlg 1 #SQl分をエコーで表示する パラメーターは配列 2 exit 付き
*
* @return array 無ければ NULLを返す
*/
public function FindAll($Flg = false)
{
#Select分 の作成
$this->MakeSelect();
return $this->FetchAll($Flg);
}
/**
* リストとして連想配列で返す
* @param int|bool $Flg 1 #SQl分をエコーで表示する パラメーターは配列 2 exit 付き
*
* @return array 無ければ 配列を返す
*/
public function FindArr($Flg = false)
{
$Re = $this->FindAll($Flg);
return $Re == self::RE ? [] : $Re;
}
/**
* SQL文を実行し想配列で返す
* @param int|bool $Flg 1 #SQl分をエコーで表示する パラメーターは配列 2 exit 付き
*
* @return array 無ければ NULLを返す
*/
public function Finds($Flg = false)
{
$this->ViewFlg = $Flg;
#Select分 の作成
$this->MakeSelect();
return $this->FetchAll($Flg);
}
/**
* 最大値を返すリ
*
* @param int|bool $Flg
* @param string $Column
* @return int
*/
public function Max($Flg = false, $Column = null)
{
if (!$Column = isset($Column) ? $Column : (isset($this->Column_[0]) ? $this->Column_[0] : '')) {
return 0;
}
$this->Select_ = "MAX(" . self::SetAs($Column) . ') AS Value';
$this->Column_ = [];
#Select分 の作成
$Max = $this->Find($Flg);
return isset($Max['Value']) ? $Max['Value'] : 0;
}
/**
* 最小値値を返すリ
*
* @param int|bool $Flg
* @param string $Column
* @return int
*/
public function Min($Flg = false, $Column = null)
{
if (!$Column = isset($Column) ? $Column : (isset($this->Column_[0]) ? $this->Column_[0] : '')) {
return 0;
}
$this->Select_ = "MIN(" . self::SetAs($Column) . ') AS Value';
$this->Column_ = [];
#Select分 の作成
$Min = $this->Find($Flg);
return isset($Min['Value']) ? $Min['Value'] : 0;
}
/**
* カウントする
*
* @param int|bool $Flg
* @param string $Column
* @return int
*/
public function Count($Flg = false, $Column = null)
{
if (!$Column = isset($Column) ? $Column : (isset($this->Column_[0]) ? $this->Column_[0] : '')) {
$this->Select_ = "COUNT(*) AS Value";
} else {
$this->Select_ = "Count(" . self::SetAs($Column) . ') AS Value';
}
$this->Column_ = [];
$Count = $this->Find($Flg);
return isset($Count['Value']) ? $Count['Value'] : 0;
}
/**
* UPDATE する
*
* @param int|bool $Flg
* @param array $Values
* @return bool|null
*/
public function Update($Flg = false, $Values = [])
{
$this->ViewFlg = $Flg;
if ($Values) {
$this->Values($Values);
}
#Update文の作成
$this->MakeUpdate();
return $this->Exec();
}
/**
* @param int|bool $Flg
* @param array $Values
* @param int $lastInsertId
* @return bool|null
*/
public function Insert($Flg = false, $Values = self::DEF, &$lastInsertId = null)
{
$this->ViewFlg = $Flg;
if ($Values) {
$this->Values($Values);
}
$this->MakeInsert();
if ($Num = $this->Exec()) {
//
$lastInsertId = $this->Connect[self::WRITE]->lastInsertId();
}
return $Num;
}
/**
* 2020/06/03
* 有ればUP 無ければINSERT
* @param int|bool $Flg
* @return bool|null
*/
public function Inserts($Flg = false)
{
$this->ViewFlg = $Flg;
$this->MakeInserts();
return $this->Exec();
}
/**
* @param int|bool $Flg
* @return bool|null
*/
public function Delete($Flg = false)
{
$this->ViewFlg = $Flg;
$this->MakeDelete();
return $this->Exec();
}
/**
* TRUNCATE DATA の初期化
*
* @param int|bool $Flg
* @return void
*/
public function Truncate($Flg = false)
{
if (!$this->Table_) {
return;
}
$this->ViewFlg = $Flg;
$this->Sql_ = 'TRUNCATE ' . $this->Table_;
$this->Exec();
return;
}
/**
* ForeignKey
* 外部キーのチェックを無効にする
*
* @return $this
*/
public function ForeignKey()
{
$this->ForeignKey_ = 0;
return $this;
}
/**
* カラムの表示
*
* @param int|bool $Flg
* @return array|null
*/
public function ShowColumns($Flg = false)
{
$this->Sql_ = "SHOW COLUMNS FROM {$this->Table_} ";
$Arr = $this->FetchAll();
if (!$Flg) {
return $Arr;
}
foreach ($Arr as $i => $Val) {
$Re[$Val['Field']] = $Val;
}
return $Re;
}
/**
* テーブルの表示
*
* @param int|bool $Flg
* @return array|null
*/
public function ShowTable($Flg = false)
{
$this->Sql_ = "SHOW TABLE STATUS";
$Arr = $this->FetchAll();
if (!$Flg) {
return $Arr;
}
foreach ($Arr as $val) {
$Re[$val['Name']] = $val;
}
return $Re;
}
/**
* バージョンの表示
*
* @return mixed
*/
public function VerSion()
{
$this->ConName;
$this->Sql_ = 'select version()';
$Re = $this->Fetch();
return $Re['version()'];
}
/**
* 自動採番の値の変更
*
* @param int $Num
* @return bool|null
*/
public function Auto_Num($Num = 1)
{
$this->Sql_ = "ALTER TABLE {$this->Table_} AUTO_INCREMENT={$Num}";
return $this->Exec();
}
/**
* テーブルのの定義
*
* @param string $Table
* @return $this
*/
public function Table($Table)
{
$this->Table_ = $Table;
return $this;
}
/**
* SELECTの定義
*
* @param string Select
* @return $this
*/
public function Select($Select = '')
{
if (!$Select) {
return $this;
}
$this->Select_ = $Select;
return $this;
}
/**
* Whereの設定
*
* @param $Where string WHERE文
* @param $Logical string 理論演算子
* @return $this
*/
public function Where($Where, $Logical = 'AND')
{
$this->Where_[] = $Where;
$this->WhereLogical[] = $Logical;
return $this;
}
/**
* Paramsの設定
*
* @param string $Param
* @param string $Value
* @return $this
*/
public function Param($Param, $Value)
{
$this->Param_[$Param] = $Value;
return $this;
}
/**
* Paramsの一括設定
*
* @param array $params
* @return $this
*/
public function Params(array $params)
{
foreach ($params as $Param => $Value) {
$this->Param($Param, $Value);
}
return $this;
}
/**
* Sql文の設定
* @param string $Sql
* @return $this
*/
public function Sql($Sql)
{
$this->Sql_ = $Sql;
return $this;
}
/**
* Parameの設定
* @param array $Values
* @return $this
*/
public function Values(array $Values)
{
$this->Values_ = $Values;
return $this;
}
/**
* Setの定義 And でつなぐ
*
* @param string $Column
* @param string $Value 値
* @param string $Math 四則 =,!=,<,<=,>,>=,NULL等
* @param array $Param 未使用
* @return $this
*/
public function Set($Column, $Value, $Math = '=', array $Param = [])
{
$Math = isset($Math) ? $Math : '=';
$this->Set_[] = array_merge(['Column' => $Column, 'Value' => $Value, 'Math' => $Math], $Param);
return $this;
}
/**
* Joinの定義
* @param string $Table
* @param string $On
* @param string $Join
* @return $this
*/
public function Join($Table, $On, $Join = 'LEFT')
{
$this->Join_[] = ['Table' => $Table, 'On' => $On, 'Join' => $Join];
return $this;
}
/**
* OrderBYの取得
* @param string $Column
* @param string $Sort 初期値 ASC DESC
* @return $this
*/
public function Order($Column, $Sort = 'ASC')
{
$this->Order_[] = ['Column' => $Column, 'Sort' => $Sort];
return $this;
}
/**
* OrderBYの取得
* @param string $Column
* @return $this
*/
public function OrderBy($OrderBy)
{
$this->OrderBy_ = $OrderBy;
return $this;
}
/**
* GroupByの取得
* @param string $Group
* @return $this
*/
public function GroupBy($Group)
{
$this->Group_ = $Group;
return $this;
}
/**
* Selectsの取得
* @param string Selects
* @return $this
*/
public function Selects($Column)
{
$this->Selects_[] = $Column;
return $this;
}
/**
* Columnの取得
* @param string $Column
* @return $this
*/
public function Column($Column)
{
$this->Column_[] = $Column;
return $this;
}
/**
* Limitの設定
* @param $Limit int
* @param $Limit2 int
*/
public function Limit($Limit, $Limit2 = '')
{
$this->Limit_ = $Limit;
if ($Limit2){
$this->Limit_.= ','.$Limit2;
}
return $this;
}
/**
* Limitの設定
* @param int $OffSet
* @return $this
*/
public function Offset($OffSet)
{
$this->OffSet_ = $OffSet;
return $this;
}
/**
* SELECT SQL文の作成
*
* @return $this
*/
protected function MakeSelect()
{
#SELRCT句の作成
$this->Sql_ = 'SELECT ' . $this->SetSelect() . ' ';
#FROM句の作成
$from = 'FROM ' . self::SetAsTable($this->Table_);
#Join句の作成
$join = $this->SetJoin();
#Where句の作成
$where = $this->SetWhere();
#GroupBy句の作成
$groupby = self::SetGroupBy($this->Group_);
$this->Sql_ .= $from . $join . $where . $groupby;
#OrderBY句の作製
$this->Sql_ .= $this->SetOrder();
#Limit句の作成
$this->Sql_ .= self::SetLimit($this->Limit_);
#OffSet句の作成
$this->Sql_ .= self::SetOffSet($this->OffSet_);
return $this;
}
/**
* UpDate の SQL文の作成
*
* @return $this
*/
protected function MakeUpdate()
{
$this->Sql_ = 'UPDATE ' . self::SetAsTable($this->Table_);
$this->Sql_ .= ' SET ';
$this->Sql_ .= $this->SetValues();
$this->Sql_ .= $this->SetWhere();
return $this;
}
/**
* Insert の SQL文の作成
*
* @return string
*/
protected function MakeInsert()
{
$this->Sql_ = 'INSERT INTO ' . $this->Table_;
$this->Sql_ .= ' SET ';
$this->Sql_ .= $this->SetValues(false);
}
/**
* Inserts の SQL文の作成
*
* @return string
*/
protected function MakeInserts()
{
$this->Sql_ = "INSERT INTO {$this->Table_} ";
$this->Sql_ .= '(' . implode(',', array_keys(current($this->Values_))) . ')';
$this->Sql_ .= ' VALUES ';
$i = 0;
foreach ($this->Values_ as $Values) {
$Re = [];
foreach ($Values as $Column => $Value) {
$Param = ':' . $Column . '_' . $i;
$Param = $this->SetValue($Value, $Param);
$Re[] = $Param;
}
$i++;
$this->Sql_ .= '(' . implode(',', $Re) . '),';
}
$this->Sql_ = trim($this->Sql_, ',');
# ON DUPLICATE KEY UPDATE の設定
if (count($this->Column_) > 0) {
$Keys = [];
foreach ($this->Column_ as $Column) {
$Columns[] = preg_match('/\=/', $Column) ? $Column : "{$Column} = VALUES({$Column})";
}
$this->Sql_ .= " ON DUPLICATE KEY UPDATE " . implode(',', $Columns);
}
}
protected function MakeDelete()
{
$this->Sql_ = 'DELETE FROM ' . $this->Table_;
$this->Sql_ .= $this->SetWhere(false);
}
/**
* SELECT 文に AS句を付ける
* @return string
*/
protected function SetSelect()
{
$Re = [];
if (Count($this->Column_) > 0) {
$this->Select_ .= ($this->Select_ ? ',' : '') . implode(',', $this->Column_);
}
$Selects = $this->Select_ ? explode(',', $this->Select_) : [];
$Selects = array_merge($Selects, $this->Selects_);
if (count($Selects) < 1) {
return self::SELECT;
}
foreach ($Selects as $Select) {
$Re[] = self::SetAs($Select);
}
return implode(',', $Re);
}
/**
* 外部連結を作成する
*
* @return string $Join
*/
protected function SetJoin()
{
$Joins = '';
foreach ($this->Join_ as $i => $Join) {
$As = $i + 1;
// TODO: BETWEEN ANDの対応
$Ons2 = preg_split('/\s+(AND|OR)\s+/i', $Join['On'], -1, PREG_SPLIT_DELIM_CAPTURE);
$Ons3 = [];
foreach ($Ons2 as $On2) {
// TODO: 括弧付きの複雑な式の対応
if (in_array(strtoupper($On2), [
'AND',
'OR',
])) {
$Ons = $On2;
} else {
// TODO: INの対応
// TODO: ISの対応
// $Ons = explode('=', $On2);
// for ($i = 0; $i <= 1; $i++) {
// $Ons[$i] = trim((isset($Ons[$i]) ? $Ons[$i] : ''), ' ');
// $Ons[$i] = self::SetAs($Ons[$i], ($i ? $As : ''));
// }
// $Ons = $Ons[0] . ' = ' . $Ons[1];
$Ons = preg_split('/(!=|=|<>|<|>)/', $On2, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
foreach (array_chunk($Ons, 3) as $OnChunk) {
foreach ($OnChunk as $i => $On) {
if (($i + 1) % 2 === 0) {
$delim = $On;
} else {
$Ons[$i] = trim((isset($Ons[$i]) ? $Ons[$i] : ''), ' ');
$Ons[$i] = self::SetAs($Ons[$i], ($i ? $As : ''));
}
}
$Ons = "{$Ons[0]} {$delim} {$Ons[2]}";
}
}
$Ons3 = array_merge($Ons3, (array)$Ons);
}
$Table = self::SetAsTable($Join['Table'], $As);
$Joins .= ' ' . strtoupper($Join['Join']) . ' JOIN ' . $Table . ' ON ' . implode(' ', $Ons3);
}
return $Joins;
}
/**
* 配列の値をセットする
* @param int|bool $Flg
* @return string
*/
protected function SetValues($Flg = true)
{
$Sql = '';
$Values = [];
foreach ($this->Values_ as $Column => $Value) {
$Param = ":{$Column}";
#値を パラメーターに設定する
$Param = $this->SetValue($Value, $Param);
$Values[] = ($Flg ? self::SetAs($Column) : $Column) . ' = ' . $Param;
}
return implode(',', $Values);
}
/**
* 値のセットをする
*
* @param string $Value
* @param string $Param
* @return mixed|string
*/
protected function SetValue($Value, $Param)
{
switch (true) {
case preg_match('/^(NOW\(\)|NOW)$/i', trim($Value)):
$Param = 'NOW()';
break;
default:
$this->Param_[$Param] = $Value;
break;
}
return $Param;
}
/**
* WHERE句を作成する
*
* @Param int|bool $Flg
* @return string $Where
*/
protected function SetWhere($Flg = true)
{
$Where = '';
foreach ($this->Set_ as $i => $Set) {
#論理記号を入れる ここで変更することは可能
$Logical = 'AND';
$Where .= $Where ? " {$Logical} " : ' WHERE (';
#演算子のセット
$Where .= $this->MakeWhere($Set, $Flg);
}
#$this->Set_を閉じる
$Where .= $Where ? ')' : self::DEF;
foreach ($this->Where_ as $i => $Wheres) {
//* 要確認:下記の判定があると、WhereLogical に設定した値が入らずSQL構文エラーとなるため削除
//******** if ($Wheres === reset($this->Where_)) {
$Where .= $Where ? ' ' . $this->WhereLogical[$i] : ' WHERE ';
//******** }
$Where .= ' ( ' . $Wheres . ' ) ';
}
return $Where;
}
protected function MakeWhere($Set, $Flg = true)
{
#カラムの設定
$Column = $Flg ? self::SetAs($Set['Column']) : $Set['Column'];
$Param = self::ParamKIgo . preg_replace(self::AS_PATAN, '', $Column) . '_' . $this->Num++;
$Math = $Set['Math'];
$Value = $Set['Value'];
switch (true) {
case 'IN' == $Math:
$Math = "IN ( " . self::SetIn($Value,$Param) . " ) ";
$Param = '';
break;
case 'NOT IN' == $Math:
$Math = "NOT IN ( " .self::SetIn($Value,$Param) . " ) ";
$Param = '';
break;
case preg_match('/NOT NULL|NOTNULL|IS NOT NULL/i', $Value):
case preg_match('/NOT NULL|NOTNULL|IS NOT NULL/i', $Math):
$Math = 'IS NOT NULL';
$Param = '';
break;
case is_null($Value);
case preg_match('/NULL|IS NULL/i', $Value):
case preg_match('/NULL|IS NULL/i', $Math):
$Math = 'IS NULL';
$Param = '';
break;
case preg_match('/NOT LIKE/i', $Math):
case preg_match('/\%NOT LIKE\%/i', $Math):
$Math = 'NOT LIKE';
$this->Param_[$Param] = '%' . $Value . '%';
break;
case preg_match('/\%NOT LIKE/i', $Math):
$Math = 'NOT LIKE';
$this->Param_[$Param] = '%' . $Value;
break;
case preg_match('/NOT LIKE\%/i', $Math):
$Math = 'NOT LIKE';
$this->Param_[$Param] = $Value . '%';
break;
case preg_match('/LIKE/i', $Math):
case preg_match('/\%LIKE\%/i', $Math):
$Math = 'LIKE';
$this->Param_[$Param] = '%' . $Value . '%';
break;
case preg_match('/\%LIKE/i', $Math):
$Math = 'LIKE';
$this->Param_[$Param] = '%' . $Value;
break;
case preg_match('/LIKE\%/i', $Math):
$Math = 'LIKE';
$this->Param_[$Param] = $Value . '%';
break;
case preg_match('/BETWEEN/i', $Math):
$separator = preg_match('/\-/', $Value) ? '-' : ',';
$Betweens = explode($separator, $Value);
$this->Param_[$Param . '_f'] = isset($Betweens[0]) ? $Betweens[0] : 0;
$this->Param_[$Param . '_e'] = isset($Betweens[1]) ? $Betweens[1] : 0;
$Param = $Param . '_f AND ' . $Param . '_f';
break;
case 'EXISTS' == $Math:
$As = '';
$Param = '';
$Column = $Math . ' ' . $Column;
break;
default:
$this->Param_[$Param] = $Value;
break;
}
return $Column . ' ' . $Math . ' ' . $Param . ' ';
}
/**
* WHERE句 INの設定
* @param $Value string | array()
* @param $Param srting
* @return string
*/
protected function SetIn($Value,$Param)
{
if (!is_array($Value)) {
$Value = explode(',', $Value);
}
$Re=[];
foreach($Value as $i=>$Val){
$Params = $Param . '_' .$i;
$this->Param_[$Params] = $Val ;
$Re[] = $Params;
}
return implode(',',$Re);
}
/**
* Order()の設定
* OrderBy()の設定
*
* @return string $ReOrder
*/
protected function SetOrder()
{
$ReOrder = '';
if ($this->OrderBy_) {
$ReOrder = ' ORDER BY ';
foreach (explode(',', $this->OrderBy_) as $OrderBy) {
$Orders[] = self::SetAs($OrderBy);
}
$ReOrder .= implode(',', $Orders);
}
if (count($this->Order_) < 1) {
return $ReOrder;
}
if (!$ReOrder) {
$ReOrder = ' ORDER BY ';
}
$Orders = [];
foreach ($this->Order_ as $Order) {
$Orders[] = self::SetAs($Order['Column']) . ' ' . $Order['Sort'];
}
$ReOrder .= implode(',', $Orders);
return $ReOrder;
}
/**
* GroupByの設定
*
* @param string $Group
* @return string GroupBy句
*/
protected static function SetGroupBy($Group)
{
if (!$Group) {
return self::DEF;
}
$Re = [];
foreach (explode(',', $Group) as $Column) {
$Re[] = self::SetAs($Column);
}
return ' GROUP BY ' . implode(',', $Re);
}
/**
* Limitの設定
*
* @param int $Limit
* @return string Limit句
*/
protected static function SetLimit($Limit)
{
if (!$Limit) {
return self::DEF;
}
return ' Limit ' . $Limit;
}
/**
* OffSetの設定
*
* @param int $OffSet
* @return string OffSet句
*/
protected static function SetOffSet($OffSet)
{
if (!$OffSet) {
return self::DEF;
}
return ' OFFSET ' . $OffSet;
}
/**
* カラムのアズ句を管理する
* Table,SELECT,
*
* @param string $Column
* @param string $As
* @return string $Column
*/
protected static function SetAs($Column, $As = '')
{
#既にAS句がある
$Column = trim($Column);
if (preg_match(self::AS_PATAN, $Column)) {
return $Column;
}
#括弧等の記号が有る
if (preg_match('/\(|\)|\.|:/', $Column)) {
return $Column;
}
#カラム名でない(文字列リテラル)
if (preg_match('/^[\'"].*[\'"]$/', $Column)) {
return $Column;
}
#カラム名でない(数値)
if (preg_match('/^[0-9]/', $Column)) {
return $Column;
}
return self::AS_SYMBOL . $As . '.' . $Column;
}
/**
* TABLのアズ句を管理する
* Table,SELECT,
*
* @param string $Table
* @param string $As
* @return string $Table
*/
protected static function SetAsTable($Table, $As = '')
{
#既にAS句がある
if (preg_match('/ AS /', $Table)) {
return $Table;
}
return $Table . ' AS ' . self::AS_SYMBOL . $As;
}
/**
* 1以上Sql分を表示する パラメーターは配列で表示
* =2 exit付き
*/
protected function ViewSql()
{
if (!$this->ViewFlg) {
return;
}
echo $this->Sql_;
print_r($this->Param_);
if (2 == $this->ViewFlg) {
exit;
}
}
/*
http://dozo.matrix.jp/pear/index.php/PECL/pdo/fetch.html
execute() 準備したprepareに入っているSQL文を実行
prepare() 値部分にパラメータを付けて実行待ち
query() prepareを使わずにSQL文を実行
PDOException エラーを投げる
bindParam 与えられた変数を文字列としてパラメータに入れる
bindValue 与えられた変数や数値を型を指定してパラメータに入れる※1
PDO::PARAM_STR 変数の値を文字列として扱う
PDO::PARAM_INT 変数の値を数値として扱う
PDO::PARAM_BOOL
PDO::PARAM_NULL (integer)
:nameなど パラメータ(:の後に任意の文字)
PDO::FETCH_ASSOC 連想配列として取得します。※2
PDO::ATTR_ORACLE_NULLS
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindValue(':value', 1, PDO::PARAM_INT);
$stmt->bindValue(":value", null, PDO::PARAM_NULL); NULL を入れる
*/
/**
* クエリを実行し、結果をすべて取得
*
* @param int|bool $Flg $ViewFlg 1 #SQl分をエコーで表示する パラメーターは配列 2 exit 付き
* @return array
* 空の戻り値がbArrayを返す を DEF 初期値 に統一
*/
public function FetchAll($Flg = false)
{
if ($Flg) {
$this->ViewFlg = $Flg;
}
if (!$this->Sql_) {
return self::RE;
}
$this->ViewSql();
$label = [
'Sql_' => $this->Sql_,
'Param_' => $this->Param_,
];
try {
return $this->getCached(function () {
$Re = [];
if (count($this->Param_) > 0) {
#PDOStatementの取得
$this->Stmt = $this->Connect[self::READ]->prepare($this->Sql_, [\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY]);
#パラメーターのセット
$this->SetParameter();
$this->Stmt->execute();
} else {
$this->Stmt = $this->Connect[self::READ]->query($this->Sql_);
}
$Re = $this->Stmt->fetchAll(\PDO::FETCH_ASSOC);
return Count($Re) > 0 ? $Re : self::RE;
}, $label);
} finally {
$this->Initialize();
}
}
/**
* クエリを実行し、結果を1行取得
*
* @param int|bool $Flg
* @return array
*
* 空の戻り値がboolean =falseを返す FetchAllと統一
*/
public function Fetch($Flg = false)
{
if ($Flg) {
$this->ViewFlg = $Flg;
}
if (!$this->Sql_) {
return self::RE;
}
$this->ViewSql();
if (count($this->Param_) > 0) {
$stmt = $this->Connect[self::READ]->prepare($this->Sql_, [\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY]);
foreach ($this->Param_ as $Param => $Value) {
$stmt->bindValue($Param, $Value, \PDO::PARAM_STR);
}
$stmt->execute();
} else {
$stmt = $this->Connect[self::READ]->query($this->Sql_);
}
$this->Initialize();
$Value = $stmt->fetch(\PDO::FETCH_ASSOC);
return $Value;
}
protected function FOREIGN_KEY($Flg = 0)
{
$this->Stmt = $this->Connect[self::WRITE]->prepare("SET FOREIGN_KEY_CHECKS={$Flg};");
$this->Stmt->execute();
}
public function Exec($Flg = false)
{
if ($Flg) {
$this->ViewFlg = $Flg;
}
if (!$this->Sql_) {
return self::RE;
}
#外部キーリレーションシップの解除
if (!is_null($this->ForeignKey_)) {
$this->FOREIGN_KEY($this->ForeignKey_);
}
$this->ViewSql();
$this->Stmt = $this->Connect[self::WRITE]->prepare($this->Sql_, [\PDO::ATTR_CURSOR => \PDO::CURSOR_FWDONLY]);
#パラメーターのセット
$this->SetParameter();
#実行
$Num = $this->Stmt->execute();
#初期化
$this->Initialize();
return $Num;
}
/**
* パラメーターをセットする
* @param $this->Param_
* @param $this->Stmt
*/
protected function SetParameter()
{
foreach ($this->Param_ as $Param => $Value) {
//echo gettype($Value);
switch (gettype($Value)) {
case 'NULL':
$this->Stmt->bindValue($Param, null, \PDO::PARAM_NULL);
break;
case 'boolean':
$Value = $Value ? 1 : 0 ;
case 'integer':
if (preg_match('/^0+[0-9]+$/', $Value)){ #頭が0の数字は 文字として判断
$this->Stmt->bindValue($Param, $Value, \PDO::PARAM_STR);
break;
}
$this->Stmt->bindValue($Param, $Value, \PDO::PARAM_INT);
break;
case 'double':
case 'string':
default:
$this->Stmt->bindValue($Param, $Value, \PDO::PARAM_STR);
break;
}
}
}
/**
* トランザクション: 開始
*
* @return bool
*/
public function beginTransaction()
{
return $this->Connect[self::WRITE]->beginTransaction();
}
/**
* トランザクション: コミット
*
* @return bool
*/
public function commit()
{
return $this->Connect[self::WRITE]->commit();
}
/**
* トランザクション: ロールバック
*
* @return bool
*/
public function rollBack()
{
return $this->Connect[self::WRITE]->rollBack();
}
}