2

私はこれの上に髪を引っ張っています-うまくいけば、それは簡単な見落としです。

jQueryAJAX関数を使用してこのPHPファイルに多数の変数を送信することを計画しています。すべての$_POST変数をphp変数に割り当てるために、このセクションを作成しました。

foreach($_POST as $key => $value){
    $$key = $value;
}

次のように変数を操作できるため、機能しているようです。

echo 'name: ' . $name . '<br>';
echo 'main_pic: ' . $main_pic . '<br>';
echo 'product_pic: ' . $product_pic . '<br>';
echo 'more_pic: ' . $more_pic . '<br>';
echo 'paypal_code: ' . $paypal_code . '<br>';
echo 'category_id: ' . $category_id . '<br>';
echo 'price: ' . $price . '<br>';
echo 'description: ' . $description . '<br>';
echo 'product_color: ' . $product_color . '<br>';
echo 'design_color: ' . $design_color;

それで、それらを持っているので、テーブルに挿入したいと思います-

$qry = $pdo->prepare("INSERT INTO inventory (name, main_pic, product_pic, more_pic, paypal_code, category_id, price, description, product_color, design_color) 
                                            VALUES (:name, :main_pic, :product_pic, :more_pic, :paypal_code, :category_id, :price, :description, :product_color, :design_color)");

    $qry-> bindParam(':name', $name);
    $qry-> bindParam(':main_pic', $main_pic);
    $qry-> bindParam(':product_pic', $product_pic);
    $qry-> bindParam(':more_pic', $more_pic);
    $qry-> bindParam(':paypal_code', $paypal_code);
    $qry-> bindParam(':category_id', $category_id);
    $qry-> bindParam(':price', $price);
    $qry-> bindParam(':description', $description);
    $qry-> bindParam(':product_color', $product_color);
    $qry-> bindParam(':design_color', $design_color);
    $qry-> execute(); 

これは実行されません-そして、理由を確認するためにエラーをログに記録する最良の方法がわかりません。変数を手動で割り当てて、以前の$ _POSTシェナニガンをコメントアウトすると、すべてが機能しているように見え、INSERTは正常に実行されます。

手がかりはありますか?データベースが特定の変数タイプを予期しているためかもしれないと思いましたが、私はそれを十分に調査したと思います。

変数を手動で割り当てることは機能するが、$ _ POSTから変数を取得することは機能しない理由を知っている人はいますか?

編集:これらの提案に従って、エラーメッセージSQLSTATE [23000]が表示されます:整合性制約違反:1062キー1のエントリ「0」が重複しています

了解しました。この挿入を試しているときに、一意の主キーを割り当てていません。PDOがそれを処理することを前提としていました。一意の主キーの割り当てを処理するための最良の方法は何ですか?ユーザーが手動で割り当てることは避けたいです。

4

5 に答える 5

3

これは答えではありませんが、コメントよりも見栄えが良くなります。なぜあなたは次のことをしているのですか?

foreach($_POST as $key => $value){
    $$key = $value;
}

これは、グローバルをもう一度登録することです(一種の)。上記のコードを使用すると、ローカル変数を簡単に上書きして予期しない結果をもたらしたり、さらに悪いことにセキュリティの脆弱性をもたらしたりする可能性があります。

投稿した場合はどう$_POST['is_admin'] = 1なりますか?いずれにせよ、あなたはその考えを理解していると思います。あなたがしたことは悪く、危険な場合があります。

于 2013-03-02T17:06:39.990 に答える
2

@PeeHaaのように、これは答えではありませんが、彼についての私のコメントを拡張するためです。疑似レジスタグローバル機能を削除します。フィールドのホワイトリストを選択し、投稿されたものと名前を調整します。

$fields = ['name', 'age', 'sex'];

$query = $pdo->prepare(sprintf('INSERT INTO `table` (%s) VALUES (%s)', 
    implode(',', $fields), 
    implode(',', array_map(function($field) {
        return ":{$field}";
    }, $fields))));

foreach($fields as $field) {
    $query->bind(":{$field}", $_POST[$field]);
}

$query->execute();

明らかに、これにはさらに検証、empty()チェックなどが必要ですが、あなたはその考えを理解します。さらに、コールバックルックアップを使用して検証/サニタイズを追加できます。

$sanitizers = [
    'sex' => function($value) {
        $value = strtolower($value);
        return in_array($value, ['male', 'female', 'unknown']) 
            ? $value : 'unknown';
    },
];

foreach($sanitizers as $field => $sanitizer) {
    if (isset($_POST[$field])) {
        $_POST[$field] = $sanitizer($_POST[$field]);
    }
}

投稿に「性別」の「性別なし」が含まれている場合は、代わりに「不明」になります。


より完全な例:

// whitelist keys and sanitizer values
$fields = [
    // limit to 255 
    'name' => function($value) {
        return substr($value, 0, 255);
    }, 
    // you can't be that old
    'age' => function($value) {
        return min(max((int) $value, 0), 100);
    },
    // starfish need not apply
    'sex' => function($value) {
        $value = strtolower($value);
        return in_array($value, ['male', 'female', 'unknown']) 
            ? $value : 'unknown';
    },
];

// build ye' old query
$query = $pdo->prepare(sprintf('INSERT INTO `table` (%s) VALUES (%s)', 
    implode(',', array_keys($fields)), 
    implode(',', array_map(function($fields){
        return ":${$field}";
    }, array_keys($fields)))));

// loop dee doop to sanitize and bind
foreach ($fields as $key => $sanitizer) {
    if (is_callable($sanitizer)) {
        $query->bind(":{$field}", $sanitizer($_POST[$field]));
        continue;
    }
    $query->bind(":{$field}", $_POST[$field]);
}

// fire the cannons!
$query->execute();
于 2013-03-02T17:21:48.603 に答える
1

データベーステーブルを空にして、それが機能するかどうかを確認します...上書きしようとしているdbテーブルに主キーがある可能性があります。

を使用して、dbテーブルも確認してくださいEXPLAIN inventory

于 2013-03-02T16:58:49.107 に答える
1

必要に応じて、自動インクリメントされた主キーを使用できます。mysqlを使用するとします:http: //dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

于 2013-03-02T17:01:12.267 に答える
1

OPは次のよ​​うに述べています。 申し分なく、この挿入を試みているときに一意の主キーを割り当てていません。PDOがそれを処理することを前提としていました。一意の主キーの割り当てを処理するための最良の方法は何ですか?ユーザーが手動で割り当てることは避けたいです。

この部分またはあなたの質問に対処するだけです-引用符で囲まれていない0を使用するだけです

insert into table (id, name) values (0, 'Bob');

しかし、あなたが言うように、それが正しく自動インクリメントされているIDである場合はそうする必要はありません。

Mysqlの古いバージョン(<5)では、空の文字列を使用できました。これは、これを読んでいる人が以前に文書化されていない機能に反した場合に備えて、5.0がリリースされたときに爆発しました。

于 2013-03-02T17:19:51.470 に答える