2017-06-09 2 views
-1

私はクエリを格納するデータを扱う関数を持っています。私はすでに作成されたレコードを更新することで失われた。PHP:MY​​SQLのレコードを配列から更新する

function storeData($form_data, $table_name, $cxn){ 
    if(!is_array($form_data)){ 
     return false; 
     exit(); 
    } 
    //calls a function that cleans the data and returns it 
    $clean_data = washData($form_data); 
    $fields=implode(",", array_keys($clean_data)); 
    $values=implode('","', array_values($clean_data)); 


    $query = "INSERT INTO $table_name ($fields) VALUES (\"$values\")"; 

    if($result=mysqli_query($cxn, $query)){ 
     return true; 
    } 
    else{ 


     foreach ($clean_data as $key => $value) { 
      if ($key =="Username") { 
       echo $value; 
       $sql = "SELECT * FROM $table_name WHERE $key = $value"; 

       if($result=mysqli_query($cxn, $sql)) 
        $update = "UPDATE $table_name SET $key = $value"; 
      } 
     } 
    } 
} 

washdataのfucntion:

function washData($data){ 
    if(!is_array($data)){ 
     return false; 
     exit(); 
    } 
    foreach($data as $field => $value){ 
     $field_array[]=$field; 
     $value_array[]=strip_tags(trim($data[$field])); 
    } 

    return array_combine($field_array, $value_array); 
} 

この機能は明らかに動作しません。私は、オブジェクトを反復した後に捕まってしまいました。私はUsernameを探して、そのユーザー名に基づいてクエリを作成しようとしました。私は配列からこれらの値を取得し、それらをデータベースに設定する必要がありました。ユーザー名が変数に格納されていることを確認した後、オブジェクトを反復処理すると思っていましたか?私はそれを別の関数に分岐するつもりですが、if-statementsでは複雑になっています。

EDIT:提案された解決策を反映するstoreData機能を変更:

function storeData($form_data, $table_name, $cxn){ 
    if(!is_array($form_data)){ 
     return false; 
     exit(); 
    } 
    $types = str_repeat("s", count($form_data)); 
    $params = array(); 
    $params[] = &$types; 
    $keys = array_keys($form_data); 
    $values = array_values($form_data); 
    for ($i = 0; $i < count($values); $i++) { 
     $params[] = &$values[$i]; 
    } 

    $sql = "INSERT INTO $table_name (" . implode(',', $keys) . ") VALUES (" . 
     implode(',', array_fill(0, count($values), '?')) . ") 
     ON DUPLICATE KEY UPDATE "; 
    $updates = implode(',', array_map(function($col) { 
     return "$col = VALUES($col)"; 
    }, $keys)); 
    $sql .= $updates; 

    $stmt = mysqli_prepare($cxn, $sql); 
    call_user_func_array(array($stmt, 'bind_param'), $params); 
    return mysqli_stmt_execute($stmt); 
} 

を、私は戻って、このMSGを受けています:

警告
<b>Warning</b>: call_user_func_array() expects parameter 1 to be a valid callback, first array member is not a valid class name or object in <b>somepath/</b> on line <b>37</b><br /> 


を:mysqli_stmt_execute()にパラメータ1を期待mysqli_stmtである、ブール値somepath/ on line

+1

通常は適切なことをしないような関数として 'washData()'について気分が悪いです。 – tadman

+1

**警告**:mysqliを使用する場合は、[パラメータ化されたクエリ](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php)と['bind_param']( http://php.net/manual/en/mysqli-stmt.bind-param.php)を使用してクエリにユーザーデータを追加します。**重大な[SQLインジェクションのバグ](http://bobby-tables.com/)を作成したため、文字列の補間または連結を使用してこれを実行しないでください。 ** '$ _POST'、' $ _GET'、**任意の**ユーザデータを直接クエリーに入れないでください。誰かがあなたのミスを悪用しようとすると非常に危険です。 – tadman

+0

あなた自身のORMを書くための一歩前進として、[Doctrine](http://www.doctrine-project.org/)、[Propel](http://propelorm.org /)または[Eloquent](https://laravel.com/docs/5.4/eloquent)?これらはあなたが望むすべてのことを行い、さらに試行され、テストされ、十分に文書化されます。 – tadman

答えて

0

私はあなたがREPLACE INTO機能を探していると思います。これはINSERT INTO関数のように機能しますが、すでに何かが見つかった場合はそれを置き換えます。そこに何もなければ、それはそれを挿入する。

EDIT。 OPは部分的な情報を更新しようとしているので、REPLACEは必要なものではありません。そこにPHPの配列関数とよりエレガントコードのために作るかもしれないmysqliの多くの機能がありますが、私は、これはあなたが探しているものだと思うことを

$query = "INSERT INTO $table_name ($fields) VALUES (\"$values\")"; 
if($result=mysqli_query($cxn, $query)){ 
    return true; 
} else { 
    $query = "SELECT my_id FROM $table_name WHERE username='".$clean_data['username']."'"; 
    $result=mysqli_query($cxn, $query); 
    $a = mysqli_fetch_assoc($result); 
    $update = "UPDATE $table_name WHERE my_id=`".$a['my_id']."' SET "; 
    $set_array = array(); 
    foreach ($clean_data as $key => $value) { 
     if ($key =="Username") { continue; } 
     array_push($set_array, "$key = '$value'"); 
    } 
    $update .= implode(", ", $set_array).";"; 
} 
... 

注:このことを考えてみましょう。データ行が存在しない場合は、挿入します。存在する場合は、データセットに含まれるセルを更新します。

ここで、MYSQLのベストプラクティスの警察は、私がクエリを準備、パラメータ化、またはバインドしていないことをすぐに指摘し、Bealzebubが私たちの次元に突入するためのポータルを開設しました。彼らはもちろん正しいですが、彼らはあなたの質問にも答えていません。最初にあなたの質問に答えましょう。そして、重要であるため、あなたが話していることを理解することをお勧めします。

+0

古いデータには何が起こりますか?古いデータに2/5フィールドの値があり、新しいデータが1/5の場合、古いレコードが3/5に置き換えられますか? –

+0

'REPLACE'と' UPDATE'の違いは、 'REPLACE'は行全体を置き換え、' UPDATE'は個々のセルを置き換えることができることです。私は行全体を置き換えたいと思っていたのは、それがあなたのコードがやっていることだから(kindof)。データ構造と実際の目的に応じて、これを行う方法はいくつかありますが、これはもっと効率的ですが、データの行とテーブル構造の例を与える必要があります。 – JBH

+0

これが機能するには、データに一意のキー列が含まれている必要があります。それ以外の場合は、更新する行があるかどうかを判断できません。 – Barmar

1

ON DUPLICATE KEYのオプションをINSERT INTOに設定してください。

wash_data()機能ではなく、準備済みの文章とbind_paramも使用する必要があります。ダイナミックパラメータでこれを行うには、参照を使用して呼び出す必要があるため、少し複雑です。

function storeData($form_data, $table_name, $cxn){ 
    if(!is_array($form_data)){ 
     return false; 
     exit(); 
    } 
    $types = str_repeat("s", count($form_data)); 
    $params = array(); 
    $params[] = &$types; 
    $keys = array_keys($form_data); 
    $values = array_values($form_data); 
    for ($i = 0; $i < count($values); $i++) { 
     $params[] = &$values[$i]; 
    } 

    $sql = "INSERT INTO $table_name (" . implode(',', $keys) . ") VALUES (" . 
     implode(',', array_fill(0, count($values), '?')) . ") 
     ON DUPLICATE KEY UPDATE "; 
    $updates = implode(',', array_map(function($col) { 
     return "$col = VALUES($col)"; 
    }, $keys)); 
    $sql .= $updates; 

    $stmt = mysqli_prepare($cxn, $sql) or die(mysqli_error($cxn)); 
    call_user_func_array(array($stmt, 'bind_param'), $params); 
    return mysqli_stmt_execute($stmt); 
} 
+0

これは私よりも良い答えです! – JBH

+0

@Barmarので、洗濯データは有効ではありませんか?本質的に、bind_parmは疑わしいデータを整え、削除し、扱いますか?洗濯データ関数iveはPHP mysqlブックでそのように処理されています。たぶんその古いアプローチですか? –

+0

@ k.wigあなたは 'wash_data'で引用符のような特殊文字をエスケープしません。 'strip_tags'と' trim'はSQLインジェクションを防ぐために何もしません。 – Barmar

関連する問題