0

2 つのメソッドを持つ PHP クラスがあります。1 つは出力用に MySQL データベースに接続し、もう 1 つは入力用に MySQL データベースに接続します。

私の質問は、両方の機能について、データベースに接続するためのコードを繰り返したことです。コードを 2 回繰り返すのではなく、クラスに 3 番目の関数を配置して DB に接続し、他の 2 つの関数を呼び出して接続を確立するより良い方法は何でしょうか? 私は OOP コーディングを改善しようとしている PHP n00b です。まったく同じコードを使用して、DB に 2 回接続したことに注目してください。

class output_mysql {
var $db_name = 'database';
var $db_username = 'name';
var $db_password = 'mypassword';

function print_table_cell($tbl_name, $colm_name, $array_index_num) {
    try {
        $pdo = new PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch (PDOException $e) {
        $error = 'Unable to connect to the database server.';
        include 'output_mysql_error.php';
        exit();
    }
    try {
        $sql = "SELECT $colm_name FROM $tbl_name";
        $result = $pdo->query($sql);
    }
    catch (PDOException $e) {
        $error = 'Error fetching content: ' . $e->getMessage();
        include 'output_mysql_error.php';
        exit();
    }
    while ($row = $result->fetch()) {
        $all_content[] = $row["$colm_name"];
    }
    echo $all_content[$array_index_num];
}

function update_content($tbl_name, $colm_name, $error_message_text, $id_num) {
    try {
        $pdo = new PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch (PDOException $e) {
        $error = 'Unable to connect to the database server.';
        include 'output_mysql_error.php';
        exit();
    }
    try {
        $sql = 'UPDATE website_content SET
            content = :content,
            date_added = CURDATE()
            WHERE id = :id';
    $s = $pdo->prepare($sql);
    $s->bindValue(':content', $error_message_text);
    $s->bindValue(':id', $id_num);
    $s->execute();
    }
    catch (PDOException $e) {
        $error = 'Error: ' . $e->getMessage();
        include 'output_mysql_error.php';
        exit();
    }
}
}
4

2 に答える 2

3

この質問には [oop] というタグが付けられていますが、その中のコードは OOP とはかけ離れています。

あなたの方法は、waaaaaaaaaaaaaay やりすぎです。あなたがすべきことは、データベース接続をoutput_mysqlクラスのコンストラクターに注入することです (これはひどい名前です)。

namespace App\Page;

class Content
{
    private $dbConnection;

    public function __construct(\PDO $dbConnection)
    {
        $this->dbConnection = $dbConnection
    }

    public update($id, $content)
    {
        $stmt = $this->dbConnection->prepare('UPDATE website_content SET content = :content, date_added = CURDATE() WHERE id = :id');
        $stmt->execute([
            'id' => $id,
            'content' => $content,
        ]);
    }

}

$dbConnection = new \PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$pageContent = new \App\Page\Content($dbConnection);
$pageContent->update(1, 'new content');

呼び出されたメソッドがある場合print_table_cell、おそらく OOP を間違って実行している可能性があります。これは、コードがやりすぎていることを意味し、単一責任の原則に違反している可能性があるためです。つまり、ほとんどすべての状況で、クラスが任意のテーブルの任意の列にアクセスできる必要は決してないということです。

于 2013-01-25T13:40:03.550 に答える
2
class Model
{
    protected $pdo;

    /**
     * Inject the pdo driver in the model.
     */
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function print_table_cell($tbl_name, $colm_name, $array_index_num)
    {
        // Use the pdo object $this->pdo
    }
}

// Create the connection
$dbName = '';
$dbUsername = '';
$dbPassword = '';

$pdo = new PDO("mysql:host=localhost;dbname=$dbName", $dbUsername, $dbPassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Create your model and inject the pdo object.
$model = new Model($pdo);
$model->print_table_cell() ...

上記のように、PDO は SQL インジェクションを防ぐ値をエスケープするため、準備済みステートメントを使用する必要があります。とにかく、すべての入力データをフィルタリングする必要があります。いくつかの基本的なフィルターhttp://php.net/manual/fr/function.filter-var.phpがあります。

モデル クラスはデータベースとのみやり取りする必要があり、何も出力しません。

出力をプライティングするために、モデルからデータを取得して表示する、いわゆる View クラスを使用できます。

class View
{
    protected $model;

    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    public function render()
    {
        echo $this->model->getData();
    }
}

class Model
{
    protected $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function getData()
    {
        // Do your query here with $this->pdo and prepared statement.
        // and return the data
    }
}

$pdo = new PDO(...);
$model = new Model($pdo);
$view = new View($model);
$view->render();
于 2013-01-25T13:42:51.600 に答える