2016-03-30 4 views
0

PHPでOOPベースのフォーラムを作成しようとしていますが、現在はデータベースクラスの作成に専念しています。具体的には、IamはDatatableクラスの汎用クラスの挿入クラス関数(PDO btwを使用)を作成します。データベースインサートクラス関数を作成するときにスタックする

class DB 
      { 
       private $dbconn; 

       public function __construct(){ 

       } 

       protected function connect($dbname, $dbhost='127.0.0.1', $dbuser='root', $dbpass=''){ 

        try{ 
        $this->dbconn = new PDO("mysql:host=$dbhost;dbname=$dbname;", $dbuser, $dbpass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); 
        } 

        catch(PDOException $e){ 
         echo 'Connection failed: '.$e->getMessage()."<br />"; 
        } 
       } 

       protected function disconnect(){ 
        $this->dbconn = null; 
       } 

       public function insert($dbname,){ 
        $this->connect($dbname); 

        try{ 
         # prepare 
         $sql = "INSERT INTO pdodemotable (firstname, lastname, age, reg_date) 
          VALUES (?, ?, ?, now())"; 
         $stmt = $dbconn->prepare($sql); 
         # the data we want to insert 
         $data = array($firstname, $lastname, $age); 
         # execute width array-parameter 
         $stmt->execute($data); 

         echo "New record created successfully"; 
        } 
        catch(PDOException $e){ 
         echo $sql . "<br>" . $e->getMessage(); 
        } 
       } 
      } 

挿入機能は未完成です。私は、どのように引数の任意の量、データベースの列とANYテーブルの任意の量に適応するために挿入関数を取得する把握することはできません。今のところ関数内のコードは、私が手続き型プログラミングを使用していた私の他のプロジェクトの1つから取られています。 OOPをデータベースで初めて使用する

私はOOPとPDOの初心者です。 Imが欠けているのを助けることができるある種の方法または機能がなければならない。私が今見ている唯一の解決策は、文字列処理とif文のridicoulusの量を使用することです。それは最高の解決策ではありません...より簡単な方法が必要です...

答えて

1

最初の通知 - あなたは代わりにそれがあるべき、Insertメソッドのコンストラクタのパラメータ$dbnameは必要ありません:insert方法として

class DB { 

    private $dbconn; 

    public function __construct($dbname, $dbhost='127.0.0.1', $dbuser='root', $dbpass='') { 
     // also don't catch the error here, let it propagate, you will clearly see 
     // what happend from the original exception message 
     $this->dbconn = new PDO("mysql:host=$dbhost;dbname=$dbname;", $dbuser, $dbpass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'")); 
    } 

    ... 

} 

を - まずそれがどのように使われるか想像してみてください。 例えば、それは次のようにすることができる:

$db = new DB('mydb'); 
$db->insert('mytable', array('firstname'=>'Pete', 'lastname'=>'Smith')); 

その後、メソッドにテーブル名とデータ(キー/値)を渡すことができ:

public function insert($table, $data) { 
    // again, no need to try/catch here, let the exceptions 
    // do their job 
    // handle errors only in the case you are going to fix them 
    // and not just to ingnore them and 'echo', this can lead to much worse problems 
    // see the explanation below regarding the `backtick` method 
    $table = $this->backtick($table); 
    $fields = array(); 
    $placeholders = array(); 
    $values = array(); 
    foreach($data as $key=>$value) { 
     $fields[] = $this->backtick($key); 
     // you can also process some special values like 'now()' here 
     $placeholders[] = '?'; 
    } 
    $fields = implode($fields, ','); // firstname, lastname 
    $placeholders = implode($placeholders, ','); // ?, ? 
    $sql = "INSERT INTO $table ($fields) values ($placeholders)"; 
    $stmt = $this->dbconn->prepare($sql); 
    $stmt->execute(array_values($data)); 
} 


public function update($table, $id, $data) { 
    $table = $this->backtick($table); 
    $fields = array(); 
    foreach($data as $key=>$value) { 
     $fields[] = $this->backtick($key) . " = ?"; 
    } 
    $fields = implode($fields, ','); // firstname=?, lastname=? 
    $sql = "UPDATE $table SET $fields where id=?"; 
    $stmt = $this->dbconn->prepare($sql); 
    $data['id'] = $id; 
    $stmt->execute(array_values($data)); 
    if ($stmt->execute(array_values($data)) === false) { 
     print 'Error: ' . json_encode($stmt->errorInfo()). PHP_EOL; 
    } 
    while ($row = $stmt->fetchAll()) { 
     print json_encode($row) . PHP_EOL; 
    } 
} 

private function backtick($key) { 
    return "`".str_replace("`","``",$key)."`"; 
} 

別の方法は、別のオブジェクトを作成することです1つのテーブル行(ActiveRecordパターン)を表します。このようなオブジェクトを使用しています コードは次のようになります。可能なSQLインジェクションの脆弱性

$person = new Person($db); 
$person->firstName = 'Pete'; 
$person->lastName = 'Smith'; 
$person->save(); // insert or update the table row 

アップデート私も可能SQLインジェクションを説明するためにupdatebacktickメソッドを追加しました。このようなSQL文につながる

$db->updateUnsafe('users', 2, array(
    "name=(SELECT'bad guy')WHERE`id`=1#"=>'', 
    'name'=>'user2', 'password'=>'text')); 

UPDATE users SET name=(SELECT'bad guy')WHERE`id`=1# = ?,name = ?,password = ? where id=? 

ので、代わりのユーザーのためのデータを更新 backtickがなければ、updateはこのようなもので呼び出される可能性がありますid 2の場合、ID 1のユーザーの名前が変更されます。 backtickメソッドのため、上記の文はUnknown column 'name=(SELECT'bad guy')WHERE id =2#' in 'field list'で失敗します。 Here is私のテストの完全なコード。

とにかく、おそらくSQLインジェクションから保護されないので、テーブル名やフィールド名などの既知のパラメータにユーザー入力を使用しないほうがずっと良いです。

$db->insert('mytable', $_POST)のようにする代わりに、$db->insert('mytable', array('first'=>$_POST['first']))を実行してください。

+1

[このコードは基本的にSQLインジェクションに対して脆弱です。](https://phpdelusions.net/pdo/lame_update) –

+0

@YourCommonSenseデータの '$ keys 'がユーザーから来ていると脆弱です'$ db-> insert( 'mytable'、$ _POST)'を実行し、 '$ _POST'配列全体をデータとして渡しますか?しかし、 '$ db-> insert( 'mytable'、array( 'first' => $ _ POST ['first']))'のようなことをすればOKです。またここで行うことができるのは引用だけですか?テーブル名とキーを安全にするために$ this-> dbconn-> quote()を追加することはできますか? –

+0

いいえ、識別子に文字列引用符を使用することはできません。構文エラーが発生します。少なくとも、識別子の書式を設定する必要がありますが、識別子をホワイトリストに登録する方がよいでしょう。 –

-1

引数を渡してみてください配列、次にメソッド挿入の内部でforeachを実行します。

のような何か:

$data['first_name'] = 'your name'; 
... 
$data['twentieth_name'] = 'twentieth name'; 

foreach($data as $key => $value) 
    $final_array[':'.$key] = $value; 

$stmt->execute($final_array);