0

私はMysqli(MySQLからの切り替え)に完全に慣れていないので、物事をシンプル、安全、安全に保つために、この万能関数を介してすべてのMysqliクエリを実行することは理にかなっていますか?

なぜまたはなぜそうではなく、どちらの方法でも長所と短所は何でしょうか?

function mysqli_prepared_query($link,$sql,$typeDef = FALSE,$params = FALSE){ 
  if($stmt = mysqli_prepare($link,$sql)){ 
    if(count($params) == count($params,1)){ 
      $params = array($params); 
      $multiQuery = FALSE; 
    } else { 
      $multiQuery = TRUE; 
    }  

    if($typeDef){ 
      $bindParams = array();    
      $bindParamsReferences = array(); 
      $bindParams = array_pad($bindParams,(count($params,1)-count($params))/count($params),"");         
      foreach($bindParams as $key => $value){ 
        $bindParamsReferences[$key] = &$bindParams[$key];  
      } 
      array_unshift($bindParamsReferences,$typeDef); 
      $bindParamsMethod = new ReflectionMethod('mysqli_stmt', 'bind_param'); 
      $bindParamsMethod->invokeArgs($stmt,$bindParamsReferences); 
    } 

    $result = array(); 
    foreach($params as $queryKey => $query){ 
      foreach($bindParams as $paramKey => $value){ 
        $bindParams[$paramKey] = $query[$paramKey]; 
      } 
      $queryResult = array(); 
      if(mysqli_stmt_execute($stmt)){ 
        $resultMetaData = mysqli_stmt_result_metadata($stmt); 
        if($resultMetaData){                                                                               
          $stmtRow = array();   
          $rowReferences = array(); 
          while ($field = mysqli_fetch_field($resultMetaData)) { 
            $rowReferences[] = &$stmtRow[$field->name]; 
          }                                
          mysqli_free_result($resultMetaData); 
          $bindResultMethod = new ReflectionMethod('mysqli_stmt', 'bind_result'); 
          $bindResultMethod->invokeArgs($stmt, $rowReferences); 
          while(mysqli_stmt_fetch($stmt)){ 
            $row = array(); 
            foreach($stmtRow as $key => $value){ 
              $row[$key] = $value;           
            } 
            $queryResult[] = $row; 
          } 
          mysqli_stmt_free_result($stmt); 
        } else { 
          $queryResult[] = mysqli_stmt_affected_rows($stmt); 
        } 
      } else { 
        $queryResult[] = FALSE; 
      } 
      $result[$queryKey] = $queryResult; 
    } 
    mysqli_stmt_close($stmt);   
  } else { 
    $result = FALSE; 
  } 

  if($multiQuery){ 
    return $result; 
  } else { 
    return $result[0]; 
  } 
} 
?> 

Example(s): 
For a table of firstName and lastName: 
John Smith 
Mark Smith 
Jack Johnson 
Bob Johnson 

<?php 
//single query, single result 
$query = "SELECT * FROM names WHERE firstName=? AND lastName=?"; 
$params = array("Bob","Johnson"); 

mysqli_prepared_query($link,$query,"ss",$params) 
/* 
returns array( 
0=> array('firstName' => 'Bob', 'lastName' => 'Johnson') 
) 
*/ 

//single query, multiple results 
$query = "SELECT * FROM names WHERE lastName=?"; 
$params = array("Smith"); 

mysqli_prepared_query($link,$query,"s",$params) 
/* 
returns array( 
0=> array('firstName' => 'John', 'lastName' => 'Smith') 
1=> array('firstName' => 'Mark', 'lastName' => 'Smith') 
) 
*/ 

//multiple query, multiple results 
$query = "SELECT * FROM names WHERE lastName=?"; 
$params = array(array("Smith"),array("Johnson")); 

mysqli_prepared_query($link,$query,"s",$params) 
/* 
returns array( 
0=> 
array( 
0=> array('firstName' => 'John', 'lastName' => 'Smith') 
1=> array('firstName' => 'Mark', 'lastName' => 'Smith') 
) 
1=> 
array( 
0=> array('firstName' => 'Jack', 'lastName' => 'Johnson') 
1=> array('firstName' => 'Bob', 'lastName' => 'Johnson') 
) 
) 
*/ 
4

3 に答える 3

9

申し訳ありませんが、それはひどい考えだとは思いません。

優れた関数/メソッドは、要点まで短く、1つのことと1つのことだけをうまく実行するように設計されている必要があります。また、可能な場合は分岐ロジックを回避するようにしてください(ifステートメントとswitchステートメントの数を最小限に抑えてください)。このような機能は、比較的少ない労力で内部の仕組みを把握できるため、わかりやすくなっています。

関数が長ければ長いほど、プログラマーはそれがどのように機能するかについて頭を抱えなければならないため、理解が難しくなります。関数に含まれるif/switch / try / catch / throwステートメントが多いほど、実行が関数をどのように流れるかを変更するため、理解が難しくなります。npathの複雑さ(関数が実行できる可能性のある方法の数)として知られているものを考慮に入れる必要があります。追加するたびに、npathの複雑さが2倍になります。純粋にifを数えることに基づいて、私は64の複雑さを得ましたが、これは高すぎます!ループはnpathの複雑さも増す可能性があるため、関数の実際の複雑度メトリックはおそらくそれよりもはるかに高くなります。

与えたような関数を変更することは、小さな単純な関数のコレクションである場合よりもはるかに多くの作業になります。これは、不要なノックオン効果を持たずに意図した新しい動作を実現するために特定の変更を行うことが非常に難しいためです。 。もちろん、単体テストを使用してこれが発生しないことを確認できますが、npathの複雑さが高い場合、関数の機能が完全にカバーされていることを確認するために作成する必要のあるテストの数は非常に多くなります。

一般的な経験則:

  • 関数の本体が画面に収まらない場合は、おそらく頭にも収まりません。エディタウィンドウより長い関数は避けてください。関数全体を表示するためにスクロールする必要はありません。
  • 関数ごとに2つのifを取得します。それ以上になると、npathの複雑さが管理不能になり始める可能性があります。
  • 関数は1つのことをうまく行う必要があります。すべての取引のジャックになろうとする関数は、すべての場合に正しくない可能性があります。さらに、機能が引き受けようとする責任が多ければ多いほど、機能が持つすべての責任を果たすことが難しくなります。
  • 小さな関数は再利用可能ですが、大きな関数は再利用できません。
  • 聖なるものすべての名において、あなたのコードにコメントしてください!他の誰かがあなたの関数を見て、それが何を意味するのかを理解することはほとんど不可能です。それを分解して以前のガイドラインに従うことはかなり役に立ちますが、それでもコンピュータコードは普通の英語よりも他の人間にアイデアを表現するほど良くはありません。コメントは、一見明確ではないかもしれない点を明確にし、コードを設計および実装しているときに別のプログラマーが頭の中に何があったかを理解するのに役立ちます。実行時間の面で費用がかからないので、コメントしない言い訳はありません。このコードをそのままにして、1年後にもう一度見直すと、書いたときに何を考えていたのかわからなくなることを保証できます。

より良い解決策は、一連のメソッドとして必要なサービスを提供するクラスを実装することです。

さらに良い解決策は、このPHPの組み込み機能を介してどれだけのことができるかを確認することです。私はあなたの関数を本当に理解できないので、PHPがこの関数に必要なことをすでに実行できるかどうかはわかりませんが、私の疑いは、そのかなりの部分がすでにPHPに実装されていることです。

于 2012-05-17T12:02:08.323 に答える
4

なぜ車輪の再発明をするのですか?MySQLiにはすでに使用するクラスがあります。

http://us2.php.net/manual/en/class.mysqli.php

このリンクから始めて、適切に使用を開始してください。

于 2012-05-17T11:52:27.203 に答える
1

1つのサイズがすべてに適合するということは、必然的に、1つの特定の状況にのみ対処し、すべての操作に適用されるわけではないコードがいくつか(場合によっては多数)存在することを意味します。関数内に邪魔になるコードがあります。また、コードが考慮しないエッジケースもおそらく多くあります。それらを見つけると、コードをデバッグしようとする多くの頭痛の種になります。

これに対する簡単な答えは「使用しないでください」です。効率が低下し、他の開発者を混乱させるコードになる可能性があります。

MySQLiを正しく使用する方法を学びます。それはそれほど難しいことではなく、長期的には大きな利点があります。

于 2012-05-17T11:50:10.437 に答える