ブラウザから得られた複数のパラメータをsql文に組み込む処理について
PHPで、ブラウザから得られたパラメータをSQL文に組み込む処理を作っています。
やりたい内容としては、
・ブラウザから得た変数をプリペアドステートメントに渡してSQLの条件式を作りたい
・予め用意した複数のSQL文にプリペアドステートメントを使って生成した条件式を組み込みたい
・ブラウザから得られる変数の数が増減するパターンにも対応できるようにしたい。
・サブクエリを多用しているので、サブクエリ内にも条件式を組み込めるようにしたい。
作成したクラスは動作はしていますが、機能を追加していくうちにメンテナンス性の非常に悪い代物になってしまいました。
プログラミングに関しては初心者なので、何か根本的な間違いをしているのかもしれません。
現状のプログラムでは、SQL文の末尾にWHERE文を付加させるだけしか出来ないのですが、文の途中にも条件文を挿入できるようにしたいと考えています。
一般的なプログラムでWHERE文やCASE式の条件を挿入する場合、どのようなクラスを作成するのでしょうか?
お手数ですが、ご教示頂けますでしょうか?
private static $query_arr =array(
'city_query'=>array(
'table_name'=>'city'
,'col_name'=>'select city_name,ruby,lat,lng'
,'result_type'=>self::RESULT_TYPE['array']
)
,'client_query'=>array(
'table_name'=>'client'
,'col_name'=>'select client_id,client_name,address'
,'where_arr'=>array(
array(
'col'=>'client_id'
,'val'=>null
,"type"=>PDO::PARAM_INT
,'editable'=>true
)
/*,ここへ二つ目以降の条件*/)
,'result_type'=>self::RESULT_TYPE['array']
) ,'staff_detail_history'=>array(////////staffごとの履歴を表示
'col_and_table'=>'select sales_date,clie.client_name,staff_name,content_text,client_pic_name,imp.text as imp_text,remarks,registration_datetime
from (select *,staff_id as sr_staff_id from sales_report) as sr
left join staff as st
on sr.staff_id=st.staff_id
left join content as con
on sr.content_id = con.content_id
left join impression as imp
on sr.impression_id = imp.impression_id
left join client as clie
on sr.client_id= clie.client_id'
,'where_arr'=>array(
array(
'col'=>'sr_staff_id'
,'val'=>null
,"type"=>PDO::PARAM_INT
,'editable'=>true)
,array(
'col'=>'sales_date'
,'val'=>null
,"type"=>PDO::PARAM_STR
,'editable'=>true)
)
,'order'=>'order by sales_date DESC,registration_datetime ASC'///colを追加して並べ替えの条件に指定
,'limit'=>'1000'//履歴を表示させるのは1000件まで
,'result_type'=>self::RESULT_TYPE['array']
)
);
class sql_element_wrapper_parent{
protected $element_arr=array();
function __CONSTRUCT($element_arr){
$this->element_arr=$element_arr;
}
public function bind_param($stmt){
foreach($this->element_arr as $element){
$stmt=$element->bind_param($stmt);
}
return $stmt;
}
public function edit_val($param_arr){//valを更新
foreach($param_arr as $param){
foreach($this->element_arr as $element){
$result=$element->edit_val($param);
if($result===true){break;}
}
}
}
}
class sql_element_wrapper extends sql_element_wrapper_parent{
const ELEMENT_NAME_ARR =array(
'WHERE'=>'sql_where_element'
,'');//class名を取得する際に使用
const CONJUNCTION_ARR = array(0=>'AND',1=>',');
private $element_class_name;//newする時に呼び出すclass名
public $element_arr = array();
function __CONSTRUCT($add_param_arr,$element_type){//elementをまず設定
$this->set_element_class_name($element_type);//$element_class_name を設定
if(isset($element_type)){
foreach($add_param_arr as $add_arr){
$this->add_element($add_arr); //複数の条件がある場合に使用
}
}
}
function add_element($add_arr){//$element_type省略可
$class_name=$this->element_class_name;
$this->element_arr[]=new $class_name($add_arr);//newするclass名を変数にて指定する。
}
private function set_element_class_name($element_type){
(isset(self::ELEMENT_NAME_ARR[$element_type]) && $this->element_class_name =self::ELEMENT_NAME_ARR[$element_type]);
}
function isset_val(){
$result_flg=true;
foreach($this->element_arr as $val){
($val->isset_val()?:$result_flg=false);
}
return $result_flg;
}
function get_sql_str($conjunction_num){
$sql_arr=array();
foreach($this->element_arr as $element){//element内の式を配列に格納
$sql_arr[]=$element->get_sql_str();
}
$str =implode(' '. self::CONJUNCTION_ARR[$conjunction_num] .' ',$sql_arr);
return $this->get_element_type() .' '.$str;
}
function get_element_type(){
$result=null;
if(isset($this->element_class_name)){
$class_name=$this->element_class_name;
$element_type='element_type';
$result=$class_name::$element_type;
}
return $result;
// return (isset($this->element_class_name)?///クラス名で呼び出し
// $this->element_class_name::element_type: null);
}
public function edit_val($param_arr){//valを更新
foreach($param_arr as $param){
foreach($this->element_arr as $element){
$result=$element->edit_val($param);
if($result===true){break;}
}
}
}
}
class sql_where_element extends sql_param_element{
public static $element_type='WHERE';
protected $comparison_operator=null;//比較演算子を設定
function __CONSTRUCT($set_arr){
parent::__construct($set_arr);
if(isset($set_arr['comparison_operator'])){
$param_com=$set_arr['comparison_operator'];
$this->comparison_operator=$param_com;
}else{$this->comparison_operator=null;}
}
function get_sql_str(){
$result=' '.$this->col.(isset($this->comparison_operator) ?' '.$this->comparison_operator.':':'=:').$this->col.' ';
return $result;
}
}
class sql_param_element{
public $col;
public $val;
public $type;////PDO::PARAM_STR,PDO::PARAM_INT
protected $editable =false;//編集可能かどうか。初期値false
// protected $comparison_operator=null;//比較演算子を設定
function __CONSTRUCT($set_arr){
$param_c=$set_arr['col'];
$param_v=$set_arr['val'];
$param_t=$set_arr['type'];
$this->col=$param_c;
$this->val=$param_v;
$this->type=$param_t;
if(isset($set_arr['editable'])){
$param_e=$set_arr['editable'];
$this->editable =$param_e;
}else{$this->editable =false;}
return $this;
}
public function isset_val(){
$result=(isset($this->col) && isset($this->val) && isset($this->type));
return $result;
}
public function bind_param($stmt){
$stmt->bindValue(':'.$this->col, $this->val, $this->type);
return $stmt;
}
public function edit_val($param){//valを更新
if($this->editable===true){
if(isset($param['col']) && isset($param['val'])){
$set_col=$param['col'];
$set_val=$param['val'];
if($set_col==$this->col){
$this->val=$set_val;
return true;
}
}
}else{return false;}
}
}