2017-09-01 8 views
0

私は壁に頭を向けて、このPDOの準備ができていない声明がうまくいかない理由を考え出しています。私が結論づけることができるのは、変数が空の場合INSERTは失敗しますが、これは問題なく何千も前にこれを実行したに違いないので、これは混乱しています。PDOで準備されたステートメントでMySQLに空の変数を挿入する

ここに私のコードです。すべての変数はPOST変数から設定されているため、ユーザーがこのデータを提供しなかった場合、それらのうちのいくつかは空白になる可能性があります。

$stmt = $db->prepare("INSERT INTO students 
    (id, classid, userid, firstname, surname, form, gender) 
    VALUES ('', :classid, :userid, :firstname, :surname, :form, :gender)"); 

    $stmt->execute(array(':userid' => $userid, ':classid' => $classid, ':firstname' => $firstname, ':surname' => $surname, ':form' => $form, ':gender' => $gender)); 

変数が空の場合、空のフィールドを挿入する方法はありますか?

編集:これは新しい声明ではありません。以前は準備ができていなかったMySQLiでINSERTしていましたが、このコードをPDOに更新するだけでした。

EDIT 2:私のスキーマ:

id int(11) NO PRI  auto_increment 
encryption int(1) NO    
classid int(11) NO    
googleclassroom varchar(50) NO    
userid varchar(50) NO    
firstname varchar(100) NO    
surname varchar(100) NO    
form varchar(10) NO    
gender varchar(10) NO    
colour_code varchar(10) NO    
col1 varchar(50) NO    
col2 varchar(50) NO    
col3 varchar(50) NO    
col4 varchar(50) NO    
col5 varchar(50) NO    
col6 varchar(50) NO    
col7 varchar(50) NO    
timestamp datetime NO 
+0

あなたは何をしていないのですか?何かエラーがありますか?あなたはSQL例外を記録できますか? –

+0

ユーザーがすべての値を入力したときに値を挿入することはできますか? – Billa

+0

行を挿入していません。エラーはありませんが、エラーを報告するように設定されているかどうかはわかりません。 – Rob

答えて

1

あなたは以下で確認することができます。

  1. idが主キーである場合は、クエリから削除し、すべての列がNULL
  2. を受け入れることを許可します。あなたはEDIT

AUTO_INCREMENTに設定することができます: idとして

スキーマ内の主キーである、あなたは「」に設定することはできません。また、すべての列はNULLを受け入れることができないようで、ユーザーが値を提供していないため、$formのような変数は未定義またはNULLになる可能性がありますので、INSERT文は実行されません。

EDIT 2:

は、正確なエラーを見つけるために試してみてください。それがSQLかPHPかに関わらず。

あなたは私はあなたが抱えている問題は、あなたのデータはbindParam()としてバインドを取得によるものだと思うlink

+0

これは解決策ではないと思う理由は、古いコードの同じMySQLクエリが正常に動作したことです。 idフィールドを追加または削除しても、このフィールドが機能するかどうかには影響しません。実行を停止するのは、空の変数をバインドする場合だけです。 NULL値を持つ何千もの行が前もって設定されているので、テーブルは確かにNULL値を受け入れます。 – Rob

+0

表示エラーを設定できますか?ここにリンクを設定する方法です http://www.phpreferencebook.com/tips/display-all-php-errors-and-warnings/ –

+0

未定義オフセット:12インチ... PATH ... on line 83 – Rob

1

を使用して表示エラーを設定することができます。 PHPのドキュメントによると。

文を準備するために使用されたSQL文で名前もしくは疑問符プレースホルダ 対応するPHP変数をバインドします。

だから、代わりにbindValue()を使用することをおすすめします。なぜ私はPHPマニュアルを参照しているのか説明する。 PDOStatementに異なり

:: bindValue()、変数)を参照 として結合されており、唯一のPDOStatementは::(実行時に評価されるであろう が呼び出されます。

だから私の答えは、

$stmt = $db->prepare("INSERT INTO students 
    (classid, userid, firstname, surname, form, gender) 
    VALUES (:classid, :userid, :firstname, :surname, :form, :gender)"); 

$stmt->bindValue(':classid',$classid);//If this is a must enter or not entered by user then you can use bindParam() 
$stmt->bindValue(':userid',$userid);//This as well if this is a must enter then you can use bindParam() 
if($firstname == "" || $firstname == NULL){ 
$stmt->bindValue(':firstname', NULL, PDO::PARAM_INT);//_NULL seems to give issues 
}else{ 
$stmt->bindParam(':firstname', $firstname); 
} 
$stmt->bindValue(':surname',$surname); 
$stmt->bindValue(':form',$form); 
$stmt->bindValue(':gender',$gender); 

$stmt->execute(); 
+0

ありがとう。私はそれを試みましたが、うまくいかないようでした。私はそれが助けられているかどうかを確認するために各行の前にif isset文を追加しましたが、それによってPHPが停止しました。理由を調べるためにさらに調査する必要があります。 – Rob

+0

これは、あなたが 'if ... else' [リンク](https://stackoverflow.com/questions/13627400/sending-empty-values-with-pdo-results-in-error) – Sand

+0

私は答えを更新して、私に知らせてください。値を切り替える必要があります。 – Sand

1

ロブだろう、これはあなたの質問への答えではありません!私はあなたのコメントを読んで、エラーレポート、プリペアドステートメント、例外処理を正しく使用する方法を示したかっただけです。

OOPまたは手続き型関数でコードを構造化することができます。しかし構造はここではあまり意味がありません。

私のアドバイス:あなたが使用している関数のドキュメントを常に読んでください。特に返される値。このようにして、エラーの起こりやすいすべての状況を適切に処理する方法を知ることができます。 PDOに関しては、これは必須のステップです;-)

幸運を祈る!

<?php 

/* 
* Set error reporting level and display the errors on screen. 
* -------------------------------------------------------------- 
* DON'T DISPLAY ERRORS ON PRODUCTION, DO IT ONLY ON DEVELOPMENT! 
* -------------------------------------------------------------- 
*/ 
error_reporting(E_ALL); 
ini_set('display_errors', 1); 

try { 
    /* 
    * Create a PDO instance as db connection. 
    */ 

    // Create PDO instance. 
    $connection = new PDO(
      'mysql:host=localhost;port=3306;dbname=yourDb;charset=utf8' 
      , 'yourDbUsername' 
      , 'yourDbPassword' 
    ); 

    // Assign driver options. 
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE); 
    $connection->setAttribute(PDO::ATTR_PERSISTENT, TRUE); 

    /* 
    * Prepare and validate the sql statement. 
    * 
    * -------------------------------------------------------------------------------- 
    * If the database server cannot successfully prepare the statement, PDO::prepare() 
    * returns FALSE or emits PDOException (depending on error handling settings). 
    * -------------------------------------------------------------------------------- 
    */ 
    $sql = 'INSERT INTO students (
       classid, 
       userid, 
       firstname, 
       surname, 
       form, 
       gender 
      ) VALUES (
       :classid, 
       :userid, 
       :firstname, 
       :surname, 
       :form, 
       :gender 
      )'; 

    $statement = $connection->prepare($sql); 

    if (!$statement) { 
     throw new UnexpectedValueException('The sql statement could not be prepared!'); 
    } 

    /* 
    * Bind the input parameters to the prepared statement. 
    * 
    * ----------------------------------------------------------------------------------- 
    * Unlike PDOStatement::bindValue(), when using PDOStatement::bindParam() the variable 
    * is bound as a reference and will only be evaluated at the time that 
    * PDOStatement::execute() is called. 
    * ----------------------------------------------------------------------------------- 
    */ 

    $bindings = array(
     ':classid' => $classid, 
     ':userid' => $userid, 
     ':firstname' => $firstname, 
     ':surname' => $surname, 
     ':form' => $form, 
     ':gender' => $gender, 
    ); 

    foreach ($bindings as $key => $value) { 
     $bound = $statement->bindValue(
       getInputParameterName($key) 
       , $value 
       , getInputParameterDataType($value) 
     ); 

     if (!$bound) { 
      throw new UnexpectedValueException('An input parameter could not be bound!'); 
     } 
    } 

    /* 
    * Execute the prepared statement. 
    * 
    * ------------------------------------------------------------------ 
    * PDOStatement::execute returns TRUE on success or FALSE on failure. 
    * ------------------------------------------------------------------ 
    */ 
    $executed = $statement->execute(); 

    if (!$executed) { 
     throw new UnexpectedValueException('The prepared statement could not be executed!'); 
    } 

    /* 
    * Get last insert id. 
    */ 
    $lastInsertId = $connection->lastInsertId(); 

    if (!isset($lastInsertId)) { 
     throw new UnexpectedValueException('The last insert id could not be read!'); 
    } 

    /* 
    * Close connection. 
    */ 
    $connection = NULL; 

    /* 
    * Print results. 
    */ 
    echo 'Provided data successfully added with the id: ' . $lastInsertId; 
} catch (PDOException $pdoException) { 
    echo $pdoException->getMessage(); 
    exit(); 
} catch (Exception $exception) { 
    echo $exception->getMessage(); 
    exit(); 
} 

/** 
* Get the name of an input parameter by its key in the bindings array. 
* 
* @param int|string $key The key of the input parameter in the bindings array. 
* @return int|string The name of the input parameter. 
*/ 
function getInputParameterName($key) { 
    return is_int($key) ? ($key + 1) : (':' . ltrim($key, ':')); 
} 

/** 
* Get the PDO::PARAM_* constant, e.g the data type of an input parameter, by its value. 
* 
* @param mixed $value Value of the input parameter. 
* @return int The PDO::PARAM_* constant. 
*/ 
function getInputParameterDataType($value) { 
    $dataType = PDO::PARAM_STR; 
    if (is_int($value)) { 
     $dataType = PDO::PARAM_INT; 
    } elseif (is_bool($value)) { 
     $dataType = PDO::PARAM_BOOL; 
    } 
    return $dataType; 
} 
0

すべてのコメントと回答ありがとうございました。複数の異なるユーザーがNULL値を許可することを提案しました。 @sand recommendedこれらの列のデフォルト値をNULLに設定しました。それは働いた

これは何ヶ月も幸せに(私は準備されていないMySQLiステートメントを使用して)働いていたとして困っていますが、これらのINSERTをPDOステートメントから受け入れることを拒否しました。

とにかく、@Sand、@Anshumanと@Lawrenceに対するすべてのクレジットはデフォルトの列の値をNULLに設定することですが、変数が空であるかどうかは気にしません。

関連する問題