1

一般的にmysqlへの接続と使用を簡単にするカスタムクラスを作成しています。多くの関数を作成しましたが、一部を除いてすべて正常に動作します。文字列が実際の文字列であるかどうか、またはそれがmysql関数であるかどうかを判断して、引用符を付けるかどうかを判断する方法を理解できないようです。2 つのパラメーターを渡すことができる関数をまとめて、データベースに挿入します。最初のパラメーターは挿入先のテーブルで、2 番目のパラメーターは列と値のペアの配列です。このコード例は、もう少し理解を深めるのに役立つかもしれません。注:私はすでにすべての文字列をエスケープしており、問題の単純さを示すためにそのコードを削除しました。

function insert($table,array $array){
    $table = "`".$table."`";
    $columns = "";
    $values = "";
    foreach($array as $key => $value){
        $columns = ($columns=="") ? "`".$key."`" : $columns.", `".$key."`";
        if($value===NULL || $value=="NULL"){
            $value = "NULL";
        } else {
            $value = "'".$value."'";
        }
        $values = ($values=="") ? "".$value."" : $values.", ".$value."";
    }
    $query = "INSERT INTO $table ($columns) VALUES ($values)";
    return $this->query($query);
}

以下は、2 つの異なる使用例と、それぞれの期待される結果です。

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>"2013-08-26"
);
$MyClass->insert("people",$data);

実行します

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','2013-08-26')

これは予想されますが、次の使用法:

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>"NOW()"
);
$MyClass->insert("people",$data);

として実行されます

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','NOW()')

引用符が含まれていると MySQL 関数が動作しないため、これは機能しません。キャッチされない場合、ユーザーからの機能が許可されるため、これは小さなセキュリティリスクである可能性があることを私は知っています。これを行うためのより良い方法はありますか、またはこのようなクラス挿入関数で MySQL 関数を許可しないでください。誰かが mysql 関数を見つけて許可するためにまとめた正規表現がある場合、それが解決策になる可能性があります。そのような正規表現が存在しない場合、1つの可能性は、私があまり得意ではないゼロから作成することです...

編集:

当面の間使用する別の解決策は、配列を形成するときに PHP で日付を取得することです。それでも可能であればMySQL関数を使用したいと思います。問題を解決する現在のコードは次のとおりですが、私が好む方法ではありません。

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>date('Y-m-d H:i:s'),
);
$MyClass->insert("people",$data);
4

2 に答える 2

2

数年前に Zend Framework 1.0 について説明していることを実行する機能を実装しました。

単純な文字列スカラーと文字列を含むオブジェクトを区別することで解決しました。

$data = array(
  "first_name"=>"John",
  "last_name"=>"Doe",
  "entry_date"=>new Zend_Db_Expr("NOW()")
);
$MyClass->insert("people",$data);

そうすれば、私のフレームワークは、SQL 文字列として扱われる (つまり、引用符で囲まれる) つもりの PHP 文字列と、オブジェクトにロールアップされた文字列との違いを知ることができます。

if($value===NULL || $value=="NULL"){
    $value = "NULL";
} else if ($value instanceof Zend_Db_Expr) {
    $value = $value->__toString(); // no quotes
} else {
    $value = "'".$value."'";
}

PS: エスケープされた変数を連結する代わりに、クエリ パラメーターを使用するようにアドバイスする人もいるかもしれません。私はその推奨事項に同意しますが、それはあなたの最初の質問とはほとんど関係がないので、それについては触れません. クエリ パラメータの使用に関する StackOverflow の質問は他にもたくさんあります。


あなたのコメントについて:

正規表現を使用して他のすべての MySQL 関数と一致NOW()させ、それらを特別に扱うことができますが、リテラル文字列 "NOW()" (その名前の関数の結果ではない) を挿入するにはどうすればよいでしょうか?

答え: できません。ちょうど、現在のコードにリテラル文字列 "NULL" を挿入できないのと同じです。これは、その単語を特殊なケースとして扱っているためです。

NOW()SQL 式と "NOW()"を区別する方法が必要です。現在、その文字列をデータベースに挿入する必要がないからといって、その機能が必要なくなるわけではありません。現在または将来の任意のテーブル に対して一般的に使用するために、この insert() 関数を設計していることを思い出してください。

あなたは実際にフレームワークを設計しています。

于 2013-08-26T20:30:43.797 に答える