プログラミングで飯を食え。腕をあげたきゃ備忘録!

PHP、JavaScript、HTML5、CSS3などWEB系言語を中心に基本テク、備忘録をまとめます。Android、Iphoneアプリ開発についても!

PHPで配列からselect系のSQLを自動生成する関数!

サクウェブTVはコチラ↓↓↓
サクウェブTV

データベースからデータを抽出したり、検索したりする場合のselect文。

条件を色々と指定したり、テーブルを結合したりと毎回書いていると結構面倒くさいものです。

また、SQLSQLの文法に従いますからPHPという言語の中でSQLという別の言語を用いることは、ソースとして美しいものではありません。

当然、可読性もさがります。

 

そこで、配列で指定した条件通りにselect文を生成して返す関数をclassに定義しておいたり、単純に関数として定義して別ファイルからインクルードして使用するような方法がスマートでしょう。

 

まず、関数を以下に示します。

コピペして使用して下さい。あとで使用方法を説明します。

    function mkSQL($conditions){
		$sql = "";
		
		$bind = array();//結合のforeign key配列を格納
		if(isset($conditions["bind"])){
			$bind = $coditions["bind"];
			unset($conditions["bind"]);
		}
		
		if(!empty($conditions)){
			$column = "";
			$join = "";
			$where = "";
			$junnbann = "";
			$seigenn = "";
			if(count($conditions)==1){//bindがない場合
				if(!isHash($conditions)){//テーブル名のみならば
					$sql = "SELECT * FROM {$conditions[0]};";
				}else{//テーブル名以下設定があれば
					$sql = "SELECT \n";
					foreach($conditions as $tbl => $item){
						$condition = $item["conditions"];//
						$order = isset($item["order"])?$item["order"]:"";
						$limit = isset($item["limit"])?$item["limit"]:"";
						$fields = isset($item["fields"])?$item["fields"]:"";//
						$num = 0;
						if(!empty($fields)){//fieldsがあれば
							foreach($fields as $field){//fieldsを設定
								if($num == count($fields)-1){//最後の要素
									$sql .= $field."\n";
								}else{//それ以外
									$sql .= $field.",\n";
									$num++;
								}
							}
						}else{//fieldsの設定がなければ
							$sql .= "*\n";
						}
						$sql .= "FROM\n";
						$sql .= $tbl."\n";
						if(!empty($condition)){//conditionsがあれば
							$sql .= "WHERE\n";
							$num = 0;
							foreach($condition as $fie => $con){
								if(!is_array($con) && strpos($fie,"?")==false){//当てはめ?無しで且つ値での指定の場合
									if($num == count($condition)-1){//最後の要素
										$sql .= $fie."=".(is_string($con)?"'".$con."'":$con)."\n";
									}else{//それ以外
										$sql .= $fie."=".(is_string($con)?"'".$con."'":$con)." AND\n";
										$num++;
									}
								}elseif(is_array($con)){//配列指定の場合(当てはめ?必須)
									//$chgd = str_replace("?", "%s", $fie);
									$fie_arr = explode("?",$fie);
									$comp_str = "";
									for($i=0;$i<count($fie_arr);$i++){
										$comp_str .= $fie_arr[$i];
										if(isset($con[$i])){
											if(is_string($con[$i])){
												$comp_str .= "'".$con[$i]."'";
											}else{
												$comp_str .= $con[$i];
											}
										}
									}
									if($num == count($condition)-1){//最後の要素
										$sql .= $comp_str."\n";
									}else{//それ以外
										$sql .= $comp_str." AND\n";
										$num++;
									}
								}else{//当てはめ?に値を指定してある場合
									$chgd = str_replace("?", "%s", $fie);
									if($num == count($condition)-1){//最後の要素
										$sql .= sprintf($chgd,(is_string($con)?"'".$con."'":$con))."\n";
									}else{//それ以外
										$sql .= sprintf($chgd,(is_string($con)?"'".$con."'":$con))." AND\n";
										$num++;
									}
								}
							}
						}//
						if(!empty($order)){//orderがあれば
							$sql .= "ORDER BY\n";
							$num = 0;
							foreach($order as $by => $jun){
								if($num == count($order)-1){//最後の要素
									$sql .= $by." ".$jun."\n";
								}else{//それ以外
									$sql .= $by." ".$jun.",\n";
								}
							}
						}//
						if(!empty($limit)){//limitがあれば
							$sql .= "LIMIT {$limit}\n";
						}
					}
					$sql .= ";";
				}
			}elseif(count($conditions)>1){//bindがある場合
				if(!isHash($conditions)){//テーブル名のみならば
					$sql = "SELECT * FROM \n";
					$num = 0;
					foreach($conditions as $tbl){
						if($num==0){//最初の要素
							$first_table = $tbl;
							$sql .= $tbl." \n";
							$num++;
						}elseif($num==count($conditions)-1){//最後の要素
							$sql .= "LEFT JOIN ".$tbl." ON (".$first_table.".id=".$tbl.".".$first_table."_id);";
						}else{//それ以外
							$sql .= "LEFT JOIN ".$tbl." ON (".$first_table.".id=".$tbl.".".$first_table."_id) \n";
							$num++;
						}
					}
				}else{//テーブル名以下設定があれば
					//個別に変数に格納し
					$fie_count = 0;
					$conditions_count = 0;
					$order_count = 0;
					$limit_count = 0;
					$tbl_count = 0;
					
					$fie_count_chk = 0;
					$conditions_count_chk = 0;
					$order_count_chk = 0;
					$limit_count_chk = 0;
					foreach($conditions as $tbl => $item){
						$condition = $item["conditions"];//
						$order = $item["order"];
						$limit = $item["limit"];
						$fields = $item["fields"];//
						if(!empty($fields)){//fieldsがあれば
							$fie_count_chk++;
						}						
						if(!empty($condition)){//conditionsがあれば
							$conditions_count_chk++;
						}
						if(!empty($order)){
							$order_count_chk++;
						}
						if(!empty($limit)){//limitがあれば
							$limit_count_chk++;
						}
					}
					foreach($conditions as $tbl => $item){
						$condition = $item["conditions"];//
						$order = $item["order"];
						$limit = $item["limit"];
						$fields = $item["fields"];//
						define("FIRST_TABLE", $tbl);
						$num = 0;
						
						if(!empty($fields)){//fieldsがあれば
							$fie_count++;
							foreach($fields as $field){//fieldsを設定
								if($num == count($fields)-1 && $fie_count == $fie_count_chk){//最後の要素
									$column .= $field."\n";
								}else{//それ以外
									$column .= $field.",\n";
									$num++;
								}
							}
						}elseif($count == count($conditions)-1 && $fie_count==0){//全てのテーブルにfieldsの設定がなければ
							$column .= "*\n";
						}
	
						//結合処理ここから
						
							if($tbl_count==0){//最初の要素
								$first_table = $tbl;
								$tbl_count++;
							}else{//それ以外
								$join .= "LEFT JOIN ".$tbl." ON (".$first_table.".id=".$tbl.".".$first_table."_id) \n";
								$tbl_count++;
							}

						//結合処理ここまで
							
						if(!empty($condition)){//conditionsがあれば
							//$where .= "WHERE\n";
							$conditions_count++;
							$num = 0;
							foreach($condition as $fie => $con){
								if(!is_array($con) && strpos($fie,"?")==false){//当てはめ?無しで且つ値での指定の場合
									if($num == count($condition)-1 && $conditions_count==$conditions_count_chk){//最後の要素
										$where .= $fie."=".(is_string($con)?"'".$con."'":$con)."\n";
									}else{//それ以外
										$where .= $fie."=".(is_string($con)?"'".$con."'":$con)." AND\n";
										$num++;
									}
								}elseif(is_array($con)){//配列指定の場合(当てはめ?必須)
									//$chgd = str_replace("?", "%s", $fie);
									$fie_arr = explode("?",$fie);
									$comp_str = "";
									for($i=0;$i<count($fie_arr);$i++){
										$comp_str .= $fie_arr[$i];
										if(isset($con[$i])){
											if(is_string($con[$i])){
												$comp_str .= "'".$con[$i]."'";
											}else{
												$comp_str .= $con[$i];
											}
										}
									}
									if($num == count($condition)-1 && $conditions_count==$conditions_count_chk){//最後の要素
										$where .= $comp_str."\n";
									}else{//それ以外
										$where .= $comp_str." AND\n";
										$num++;
									}
								}else{//当てはめ?に値を指定してある場合
									$chgd = str_replace("?", "%s", $fie);
									if($num == count($condition)-1 && $conditions_count==$conditions_count_chk){//最後の要素
										$where .= sprintf($chgd,(is_string($con)?"'".$con."'":$con))."\n";
									}else{//それ以外
										$where .= sprintf($chgd,(is_string($con)?"'".$con."'":$con))." AND\n";
										$num++;
									}
								}
							}
						}//
						
						if(!empty($order)){//orderがあれば
							//$sql .= "ORDER BY\n";
							$order_count++;
							$num = 0;
							foreach($order as $by => $jun){
								if($num == count($order)-1 && $order_count==$order_count_chk){//最後の要素
									$junnbann .= $by." ".$jun."\n";
								}else{//それ以外
									$junnbann .= $by." ".$jun.",\n";
								}
							}
						}//
						if(!empty($limit)){//limitがあれば
							//$sql .= "LIMIT {$limit}\n";
							$limit_count++;
							$seigenn = $limit;
						}
						$count++;
					}
					
					//最後に結合
					$sql = "SELECT\n";
					$sql .= $column;
					$sql .= "FROM\n";
					$sql .= FIRST_TABLE."\n";
					$sql .= $join;
					if($conditions_count!=0){
						$sql .= "WHERE\n";
						$sql .= $where;
					}
					if($order_count!=0){	
						$sql .= "ORDER BY\n";
						$sql .= $junnbann;
					}
					if($limit_count!=0){	
						$sql .= "LIMIT {$limit}\n";
						$sql .= $seigenn;
					}
					$sql .= ";";
				}
			}
		}	
		return $sql;
	}
    
    function isHash(&$array) {
		$i = 0;
		foreach($array as $k => $dummy) {
			if ( $k !== $i++ ) return true;
		}
		return false;
	}

長いので使用方法は>>次の記事<<