あなたの質問はあまり具体的ではなく、あなたの具体的な問題が何であるかをあなたは本当に知らないと感じています。あなたはすでにあなたにいくつかのコードを与える答えを受け入れましたが、それはあなたの根本的な問題を解決せず、コードを浪費するのであなたを間違った方向に導きます。
PHPのmysqli拡張機能のオブジェクト指向インターフェースを利用して利益を得る場合に最初に知っておくべきことは、Mysqli
クラスがデータベース接続(手続き型アプローチにちなんで名付けられた「リンク」)をすでに表していることです。
require('inc/dbc.php');
$dbConnection = new Mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
もう終わりです。確かに、ここでエラー処理を使用することをお勧めします。
if ($dbConnection->connect_error)
{
throw new Exception(
sprintf('(#%d) %s', $dbConnection->connect_errorno,
$dbConnection->connect_error)
);
}
例外ハンドラーを簡単に作成できるため、例外をスローするのではなくdie('message')
、例外をスローします。これにより、例外ハンドラーを簡単に作成できるため、例外的なエラーケースが発生するたびに(実際にはその場所で)処理するのではなく、中央の場所からユーザーに対してより有用な応答を表示できます。どこdie
になりますか)。
バックトレースをログに記録してメールで送信することもできるため、問題をより簡単に修正できます。当然、例外を使用する必要はありませんが、経験則では、die
たとえば1週間で破棄するスクリプトでのみ使用することであり、オブジェクト指向設計ではうまく機能しません。
データベース接続が必要になるすべての場所でこのコードが必要になるため、独自の接続オブジェクトを作成して、これらのパーツが一緒に属しているときにそれらをまとめることができます。
class DatabaseException extends Exception
{
}
class DatabaseConnection extends Mysqli
{
public function __construct($host, $user, $password, $database = "", $port = NULL, $socket = NULL) {
parent::__construct($host, $user, $password, $database, $port, $socket);
$this->throwConnectionExceptionOnConnectionError();
}
private function throwConnectionExceptionOnConnectionError() {
if (!$this->connect_error) return;
$message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);
throw new DatabaseException($message);
}
}
使用法は実際には非常に単純で、ほとんど同じです。クラスの名前だけが異なり、その定義をロードする必要があります。
require('inc/dbc.php');
require('inc/database.php');
$dbConnection = new DatabaseConnection(DB_HOST, DB_USER, DB_PASS, DB_NAME);
記述されているように、接続オブジェクトはすでにデータベース接続を表しています。したがって、それを必要とするアプリケーションのすべての部分は、それを要求する必要があります。サンプル関数を確認してみましょう。
function getOption($id, $db_link)
{
// $db_link = $this->db_link;
$res = mysqli_query($this->db_link,"SELECT * from config where id='1'");
$row = mysqli_fetch_array($res);
return $row['option'];
}
関数の名前を変更し、最初の行にコメントを付けました。これでも必要な場合があります。実際、その関数がオブジェクトの一部である場合、次のように機能する可能性があります。DatabaseConnection
class DatabaseConnection extends Mysqli
{
...
public function getOption($id) {
$statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
$statement->bind_param('i', $id);
$statement->execute();
$statement->bind_result($option);
$statement->fetch();
$statement->close();
return $option;
}
この例が示すように、データベース接続はすでに存在しています。ただし、これはお勧めできません。あなたが選択肢を持っているだけでなく、これとあれとそのようなものとそれ以上のものを持っていると想像してください。1つのクラスで次々に関数を作成します。うまく機能するかもしれない小さなアプリケーションには適していますが、ますます想像してみてください。あなたは多くのことを担当する1つの非常に大きなクラスを得るでしょう。$this
したがって、ステートメントの準備にすでに使用できる場合でも、これを行うのは悪いことです。
また、ステートメントを準備する必要があることに注意してください。これはここで何度も答えられています、もしあなたがそれに慣れていないなら、それについて読んでください、それは一行の価値があります。オブジェクト指向にステップインしている間、コードを繰り返さないためのより良い方法があります(DRY:自分自身を繰り返さないでください)(すでに手続き型でこれを行う必要があります)。
これをすべて1つのクラスにまとめることが問題になるように、代わりにそれを独自のクラスに入れます。
class DatabaseModelBase
{
protected $connection;
public function __construct(Connection $connection) {
$this->connection = $connection;
}
protected function prepare($query) {
$connection = $this->connection;
$statement = $connection->prepare($query);
if (!$statement) {
throw new DatabaseException(
sprintf('(%s) %s', $connection->error, $connection->errno)
);
}
return $statement;
}
}
class Option extends DatabaseModelBase
{
public function find($id) {
$statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
$statement->bind_param('i', $id);
$statement->execute();
$statement->bind_result($option);
$statement->fetch();
$statement->close();
return $option;
}
}
ほとんどの場合、SQLクエリで間違いが発生するため、これには拡張エラー処理が含まれています。ご覧のとおり、特定のデータをフェッチする個々の関数は、独自のクラスに配置されています。このようなクラスを使用して、特定のデータ型のフェッチと更新をグループ化できます。
完全な使用法:
$dbConnection = new Connection(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$option = new Option($dbConnection);
$optionValue = $option->find(1);
echo $optionValue; # value for option with ID1
オブジェクトの名前はOption
おそらくうまくいきません。私は例を軽量に保つようにしましたが、ある程度の分離も提供しました。他のシナリオでは、db接続にアクセスする別の種類の方法を選択することをお勧めします。これは、db接続がOption
コンストラクターを介して注入されOption
、データベース接続が作成される方法の詳細を処理しなくなるためです。
たとえば、データベース接続オブジェクトをよりスマートにして、prepareまたはqueryを実際に使用するときに初めてデータベースに接続することができます。そのため、データベース接続を必要としないWebサイトへの要求は、不必要にデータベースに接続することはありません。
他の質問でさらに多くの例を見つけ、依存性注入について学びたいと思うかもしれません。また、常に物事を互いに離しておく必要があるため、互いに軽く接続されているだけのオブジェクトがいくつかあります。