0

orm を使用した方がよいことはわかっており、将来的に使用する予定です。しかし今のところ、私は次のような構造で作業しています。

タイトルと日付を持つ Arcticle クラス データベース アクションの DataArticle クラス したがって、Article クラスではなく、別の Data クラスでデータベース アクションを実行します。

さて、すべての Data.. クラスで、コードを使用して次のようなデータベース アクションを実行しました。

public function getArticle($id){        
        $query = "SELECT title,date from articles where id = ?";          
        if ($stmt = $this->database->getConnection()->prepare($query)) {            
            $stmt->bind_param('i',$id);
            $stmt->execute();
            $stmt->bind_result($title,$date);   
            $stmt->store_result();
            $stmt->fetch();         
            if(($stmt->num_rows) == 1){
                $article = new Article();
                $article->title = $title;
                $article->date = $date;
                $stmt->close();             
                return $article;
            }else{
                $stmt->close();
                return null;
            }           
        }else{          
            throw new Exception($this->database->getConnection()->error);
        } 
    }

しかし、この方法で作業することは、データ クラスのすべての関数で、接続し、ステートメントを実行してエラーをスローすることを意味します。これは、ラッパーを使用して集中化できる多くの繰り返しコードです。

現在、すべてのデータベース処理を実行するデータベース ラッパー/ハンドラーを作成する際のアドバイス (関数で例外をスローするか、降下エラー処理を行う方法) に従っています。

そこで、PDO の使用を開始するためにこのクラスを作成しました。

<?php
class DatabasePDO
{
    private $connection;

    private $host = "";
    private $username = "";
    private $password = "";
    private $dbname = "";

    public function openConnection(){
        $this->connection = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username,$this->password);
        $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);     
    }

    public function getConnection(){
        return $this->connection;
    }

    public function closeConnection(){
        $this->connection = null;
    }

    public function insert($query, array $data){        
        $this->connection->prepare($query)->execute($data);     
        return $this->connection->lastInsertId();
    }

    public function update($query, array $data) {
        $stmt = $this->connection->prepare($query);
        $stmt->execute($data);
        return $stmt->rowCount();       
    }

    public function delete($query, array $data) {
        $stmt = $this->connection->prepare($query);
        $stmt->execute($data);
        return $stmt->rowCount();       
    }
    public function findOne($query, array $data = null){        
        $sth = $this->connection->prepare($query);
        if($data != null){
            $sth->execute($data);
        }else{
            $sth->execute();
        }       
        if($sth->rowCount() == 1){              
            return $sth->fetchObject();
        }else{
            return null;
        }
    }
    public function find($query, array $data = null){       
        $sth = $this->connection->prepare($query);
        if($data != null){
            $sth->execute($data);
        }else{
            $sth->execute();
        }
        if($sth->rowCount() > 0){
            while($res = $sth->fetchObject()){              
                $results[] = $res;
            }
            return $results;            
        }else{
            return null;
        }
    }
}
?>

しかし、いくつかの記事を読んだときに、PDO はすでにデータベース ラッパーであるため、これは適切な方法ではないことがわかりました。

ただし、by code は以前よりずっと読みやすくなっています。今はただ

public function getArticle($id){       
        $article = $this->database->find("select name, date from articles ?",array($id));       

        $article = new article($article->name, $article->date);
        return $article;
    }

このコードははるかに短く、すべてのデータベース ロジックは PDO ラッパー クラスで処理されます。そうしないと、すべての関数でラッパーのコードを繰り返す必要があり、コードが 1 つのラッパーではなく多くの場所に配置されることになります。

私のコードを使用するより良い方法はありますか、それとも私が使用している良い方法ですか。

4

2 に答える 2

1

なぜ質問するのか、どこから疑問を抱くのかはわかりませんが、SQL クエリを処理する唯一の適切な方法は、データベース ラッパー クラスを作成することです。

実装にはいくつかの改善が必要ですが、一般的なアイデアと使用法はほぼ優れています。はい、コードの量を画面全体から 1 行に減らすことは、このようなクラスの主な利点の 1 つです。

改善について言えば、PDO にはコードを短縮するための優れたトリックがいくつかあります。

public function find($query, array $data = null){       
    $sth = $this->connection->prepare($query);
    $sth->execute($data);
    return $sth->fetchAll(); 
}

あなたのバージョンとまったく同じように動作しますが、必要なコードは 3 分の 1 です。

PDO に基づいたこのようなクラスの作成の感性に関するコメントからの質問への回答:
ほら、PDO はすでにセミ DAL です。ご覧のとおり、mysqli に比べてすでに大幅な改善になっています。mysqli は、そのようなクラスを作成する必要があるように見えますが、PDO にはすぐに使用できる多くの必要な機能があります。したがって、生の PDO を実際に使用できます。そして、PDO で作成された多くのクラスは、実際には役に立ちません。それでも、PDO もいくつかの改善の恩恵を受けることができます。

確かに PDO コードを改善し、行数を 3 行に減らしましたが、mysqli ベースのバージョンは改善できず、数十行のコードすべてが必要です。つまり、3 行は 12 行よりも優れていますが、関数の1行は3 行よりもfind()優れていますね。それでも、さらに改善する余地は常にあります。タグ wiki のPDO が失敗するケースのリストからいくつかのアイデアを得ることができます。

于 2013-08-24T18:36:13.163 に答える
-1

データベース接続を格納するより良い方法は、シングルトン クラスです。

http://php.net/manual/de/language.oop5.patterns.php

<?php
class DatabasePDO
{
    private static $instance;

    private $connection;

    private $host = "";
    private $username = "";
    private $password = "";
    private $dbname = "";

    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new DatabasePDO();
        }

        return self::$instance;
    }

    public function openConnection(){
        $this->connection = new PDO("mysql:host=$this->host;dbname=$this->dbname",$this->username,$this->password);
        $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);     
    }

    public function getConnection(){
        return $this->connection;
    }

    public function closeConnection(){
        $this->connection = null;
    }

    public function insert($query, array $data){        
        $this->connection->prepare($query)->execute($data);     
        return $this->connection->lastInsertId();
    }

    public function update($query, array $data) {
        $stmt = $this->connection->prepare($query);
        $stmt->execute($data);
        return $stmt->rowCount();       
    }

    public function delete($query, array $data) {
        $stmt = $this->connection->prepare($query);
        $stmt->execute($data);
        return $stmt->rowCount();       
    }
    public function findOne($query, array $data = null){        
        $sth = $this->connection->prepare($query);
        if($data != null){
            $sth->execute($data);
        }else{
            $sth->execute();
        }       
        if($sth->rowCount() == 1){              
            return $sth->fetchObject();
        }else{
            return null;
        }
    }
    public function find($query, array $data = null){       
        $sth = $this->connection->prepare($query);
        if($data != null){
            $sth->execute($data);
        }else{
            $sth->execute();
        }
        if($sth->rowCount() > 0){
            while($res = $sth->fetchObject()){              
                $results[] = $res;
            }
            return $results;            
        }else{
            return null;
        }
    }
}
?>

このコードを使用すると、DatabasePDO::getInstance()->getConnection(); を呼び出して、どこからでもデータベース接続を取得できます。

public function getArticle($id){        
    $query = "SELECT title,date from articles where id = ?"; 

    $database = DatabasePDO::getInstance();

    if ($stmt = $database->getConnection()->prepare($query)) {            
        $stmt->bind_param('i',$id);
        $stmt->execute();
        $stmt->bind_result($title,$date);   
        $stmt->store_result();
        $stmt->fetch();         
        if(($stmt->num_rows) == 1){
            $article = new Article();
            $article->title = $title;
            $article->date = $date;
            $stmt->close();             
            return $article;
        }else{
            $stmt->close();
            return null;
        }           
    }else{          
        throw new Exception($database->getConnection()->error);
    } 
}
于 2013-08-24T18:34:37.613 に答える