備忘錄_20160105(定位) 修改 回首頁

程式 2026-06-04 11:37:30 1780544251 100
資料庫常用類別設計 MySQL,MariaDB,PHP 修正版

資料庫常用類別設計 MySQL,MariaDB,PHP 修正版


<?php

  // modified:2026-06-04 11:31:00
  
  // $oMySQL=new CMySQL();
  
  
  // $oR=$oMySQL->insUpdDel("default", "insert into test(i1,vc1) select 1,'馬蓋仙' union all select 140,'老人家'");
  // echo '<pre>';
  // var_dump($oR);
  // echo '</pre>';
  
  // echo '<hr>';
  
  // $oR=$oMySQL->bigQuery("default", "select 'q1',i1,vc1 from test where i1<=39; select 'q2',i1,vc1 from test where i1>39;");
  // echo '<pre>';
  // var_dump($oR);
  // echo '</pre>';
  
  class CMySQLSQLResult_unit
  {
    public $straFieldName=array();
    public $booaTextType=array();
    public $iRows=0;
    public $iCols=0;
    public $aryRawData=array();
    
    public function getVal($iRow, $strFieldName)
    {
      $iCol=array_search($strFieldName, $this->straFieldName);
      if($iCol===false) { return 'field name not found!'; }
      if($iRow>=$this->iRows) { return 'row index out of range!'; }
      return $this->aryRawData[$iRow][$iCol];
    }
  }
  
  class CMySQLSQLResult
  {
    public $booInsUpdDel=false; // 增修刪=true, 大查詢=false
    
    public $booSuccess=false;
    public $strErrorMessage='';
    
    // 增修刪↓
    public $iAffectedRows=0;
    
    // 大查詢↓
    public $iResultAmount=0;
    public $aryResult=array(); // 裝載 CMySQLSQLResult_unit 的陣列,用 array_push()
  }
  
  class CMySQL
  {
    
    public function getAryConnection($strWho)
    {
      // [customvalue]
      if($strWho=='another') { return array('ip1','username1','password1','database1',3306,'utf8mb4'); }
      else                   { return array('127.0.0.1','root','a/6u3u;35/4','dbChildmo',3306,'utf8mb4'); }
    }
    
    // 參數正規化,避免 SQL Injection
    public function getStrNum($value) { return strval(floatval($value)); }
    public function getStrNormalizedString($value) { return str_replace("'","''",$value); }
    public function getStrAnsiTxt($value) { return "'" . $this->getStrNormalizedString($value) . "'"; }
    public function getStrUniTxt($value) { return "'" . $this->getStrNormalizedString($value) . "'"; }
    public function getStrAnsiLikeTxt($value) { return "'" . '%' . $this->getStrNormalizedString($value) . '%' . "'"; }
    public function getStrUniLikeTxt($value) { return "'" . '%' . $this->getStrNormalizedString($value) . '%' . "'"; }
    public function getStrFreeText($value) { return $value; }
    
    public function insUpdDel($strWho, $strSQL)
    {
      $oR=new CMySQLSQLResult();
      $oR->booInsUpdDel=true;
      
      while(true)
      {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        
        // 連線到資料庫
        list($strIP, $strUID, $strPWD, $strDB, $iPort, $strEncoding)=$this->getAryConnection($strWho);
        $oConn=new mysqli($strIP, $strUID, $strPWD, $strDB, $iPort);
        if($oConn->connect_errno)
        {
          $oR->booSuccess=false;
          $oR->strErrorMessage='資料庫連線失敗!ErrMsg:' . $oConn->connect_error;
          break;
        }
        
        while(true)
        {
          // 設定編碼
          if($oConn->set_charset($strEncoding)==false)
          {
            $oR->booSuccess=false;
            $oR->strErrorMessage='設定(' . $strEncoding . ')編碼失敗!';
            break;
          }
            
          // 執行 SQL 指令劇本
          if($oConn->query($strSQL)==false)
          {
            $oR->booSuccess=false;
            $oR->strErrorMessage='資料庫異動失敗!ErrMsg:' . $oConn->error;
            break;
          }
          
          // 取得資訊
          $oR->booSuccess=true;
          $oR->iAffectedRows=$oConn->affected_rows;
          
          break;
        }
        
        // 釋放連線
        $oConn->close();
        break;
      }
      
      return $oR;
    }
    
    public function bigQuery($strWho, $strSQL)
    {
      $oR=new CMySQLSQLResult();
      $oR->booInsUpdDel=false;
      
      while(true)
      {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        
        // 連線到資料庫
        list($strIP, $strUID, $strPWD, $strDB, $iPort, $strEncoding)=$this->getAryConnection($strWho);
        $oConn=new mysqli($strIP, $strUID, $strPWD, $strDB, $iPort);
        if($oConn->connect_errno)
        {
          $oR->booSuccess=false;
          $oR->strErrorMessage='資料庫連線失敗!ErrMsg:' . $oConn->connect_error;
          break;
        }
        
        while(true)
        {
          // 設定編碼
          if($oConn->set_charset($strEncoding)==false)
          {
            $oR->booSuccess=false;
            $oR->strErrorMessage='設定(' . $strEncoding . ')編碼失敗!';
            break;
          }
            
          // 執行 SQL 指令劇本
          if($oConn->multi_query($strSQL)==false)
          {
            $oR->booSuccess=false;
            $oR->strErrorMessage='資料庫異動失敗!ErrMsg:' . $oConn->error;
            break;
          }
          
          // 逐個結果集檢視
          $oR->booSuccess=true;
          while(true)
          {
            // 讀取資料集
            $oResult=$oConn->store_result();
            if($oResult===false)
            {
              // 例如 set @x=1; 也會傳回查詢成功,但無結果集,僅做個記錄。放在 errormessage ,不破壞之前的結構。
              $oR->strErrorMessage=$oR->strErrorMessage . '(' . $oConn->connect_error . ')';
            }
            else
            {
              // 新增一個單元
              $oR->iResultAmount++;
              $oUnit=new CMySQLSQLResult_unit();
              
              $oUnit->iCols=$oResult->field_count;
              $oUnit->iRows=$oResult->num_rows;
              
              $oFieldInfo=$oResult->fetch_fields();
              for($i=0; $i<$oUnit->iCols; $i++)
              {
                $oUnit->straFieldName[]=$oFieldInfo[$i]->name;
                $oUnit->booaTextType[]=in_array($oFieldInfo[$i]->type, array(MYSQLI_TYPE_VAR_STRING,MYSQLI_TYPE_STRING,MYSQLI_TYPE_CHAR,MYSQLI_TYPE_TINY_BLOB,MYSQLI_TYPE_MEDIUM_BLOB,MYSQLI_TYPE_LONG_BLOB,MYSQLI_TYPE_BLOB));
              }
  
              while($oRow=$oResult->fetch_row())
              {
                $oUnit->aryRawData[]=$oRow;
              }
              
              $oR->aryResult[]=$oUnit;
              
              // 釋放資料集資源
              $oResult->free_result();
            }
            
            // 查看是否還有資料集
            if($oConn->more_results()==false) { break; }
            
            // 準備前往下一個資料集
            if($oConn->next_result()==false)
            {
              $oR->booSuccess=false;
              $oR->strErrorMessage=$oR->strErrorMessage . '。資料集往下失敗!ErrMsg:' . $oConn->connect_error;
              break;
            }
            
          }
          
          break;
        }
        
        // 釋放連線
        $oConn->close();
        break;
      }
      
      return $oR;
    }
    
  }
  
?>