MySQL用PHPのORM、現実(パート1)

興味のあるphpライブラリを長時間検索した後、MySQLと連絡を取り、プロジェクトでの使用に最も適した独自のライブラリを作成しました。 このトピックでは、一連の短い記事を取り上げます。この記事は、プロのWebアプリケーション開発者だけでなく、初心者にも役立ちます。 ちなみに、私がkittyと呼ぶ、以下に示すORMライブラリは、多くの苦痛の結果であり、すべてのプロジェクトの必須ライブラリではないことに注意してください。

私の意見では、ライブラリには2つのファイルが必要です(少なくとも初期段階では)。


最後から始めましょう。 データベースイメージファイルには、名前がテーブルの名前に似ているクラスが含まれ、テーブルの列に応じたフィールドが含まれている必要があります。 つまり idauthorNameYear (Identifier、Name、Year of life)フィールドを持つauthorsテーブルがある場合、クラスは次のようになります。
class authors extends kitty { public $idauthor; public $Name; public $Year; } 

最初に識別子が続く必要があります。

通常、データベースイメージクラスには、kittyが自動的に生成するすべてのテーブルが含まれますが、後で(この記事ではすべてを説明しません)、kittyの後に接続します。 それでは、楽しい部分であるライブラリーを見てみましょう。

キティクラスプロパティ


kittyクラスは抽象クラスであり、2つの重要なプロパティを組み込んでいます(おわかりのとおり)。
  private static $db; //   private static $stack; //  

$ dbクラスのインスタンスは、拡張mysqliクラスを使用してデータベース接続を保存します。
$ stackクラスのインスタンスには、クエリのスタックと、 SplStackクラスを使用したクエリの結果が格納されます。
ここでプロパティが終了し、すべてがシンプルになりました。次に、お菓子に移りましょう。

キティクラスのメソッド


この記事では、クラスを構築する基本的な考え方を理解するために、クラスの主要なメソッドをいくつか見ていきます。 OOPには、メモリ内で1回宣言され、インスタンスを作成し、インスタンスが存続している間、インスタンスと共存するときにメモリ内に表示され、静的に変更されない静的メソッドがあります。
このライブラリの静的メソッドは一般化されており、データベースインスタンスには必要ありません。 非静的メソッドは、1つ以上のデータベースインスタンスの範囲をカバーします。

静的メソッド


データベースに接続するための重要な静的メソッドはセットアップです:
  static public function setup(mysqli $dbi,$enc = "utf8"){ if (is_object($dbi)){ self::$db = $dbi; self::$stack = new SplStack(); //  return self::setEncoding($enc); //   }else{ throw new Exception(" $dbi    mysqli", 1); return false; } } 

パラメータとして、mysqliクラスのインスタンスとエンコーディング(デフォルトではutf8 )を渡します。 初期化中に、MySQLiインスタンスとスタックが入力されます。 応答の結果はリクエストです。 正しい接続を確認してください。 行kitty :: setup(新しいmysqli)が唯一のライブラリ設定です。
エンコードは、 setEncoding要求によって設定されます 。 メソッドコードを以下に示します。
  static function setEncoding($enc){ $result = self::$db->query("SET NAMES '$enc'"); //  self::$stack->push("SET NAMES '$enc' [".($result ? "TRUE" : self::getError())."]"); return $result ? true : false; //  } 

エラーが発生した場合、リクエストとエラーをスタックにプッシュし、それに応じてfalseを返します
エラー受信機能は非常に簡潔です。
  static function getError(){ return self::$db->error." [".self::$db->errno."]"; } 

エラーテキスト(error)とエラーコード(errno)を返します。

各自尊心ORMライブラリには、スクリーニングが含まれている必要があります(Ph.D.、准教授V. Kovzhenkin)


mysqli_real_escape_string関数はこの機能を実装していますが、 長く 、2つのパラメーターを取ります。 便宜上、この関数を以下に示すものに置き換えます。
  private static function escape($string) { return mysqli_real_escape_string(self::$db,$string); } 

この関数は文字列を受け取り、SQLクエリのエスケープを返します。 これにより、 SQLインジェクションを忘れてしまいます 。これは重要な事実です。

テーブルのフィールド、より具体的にはテーブルクラスのプロパティを選択するには、クラスを操作するためにphpツールを使用します。
機能コードは次のとおりです。
  private static function _getVars(){ return array_filter(get_class_vars(get_called_class()),function($elem){ if (!is_object($elem)) return true; }); } 

この関数はすべてのプロパティを取得し、それらをフィルタリングします。 プロパティがオブジェクトであり、stackとdbを選択する場合、含まれません。 出力は、テーブルフィールドを持つ配列です。 著者を呼び出すとき:: _ getVars(); 関数は配列array( "idauthor"、 "Name"、 "Year")を返します。

データサンプリング


データサンプリングはORMライブラリの重要なトピックであり、データの取得方法と提示方法に関する疑問が生じます。
現在の記事では、クエリの1つのバリアントのみを検討します。

このメソッドは静的であり、識別子(findID)によってデータベースから1つのインスタンスを選択します。
機能コードは次のとおりです。
  static function findID($id){ if (is_numeric($id)){ // ,     $query = "SELECT * FROM `".get_called_class()."` WHERE `".key(self::_getVars())."` = $id LIMIT 1"; $result = self::$db->query($query); //  self::$stack->push($query." [".$result->num_rows."]"); //    if ($result->num_rows == 1){ //    $row = $result->fetch_object(); //    $cName = get_called_class(); //   $rClass = new $cName(); //   foreach ($row as $key => $value) $rClass->$key = $value; //   return $rClass; //  } else return false; //   ,   } else return false; //     } 

コードはコメントで詳細に説明されており、追加の説明は不要です。
次のようにしてインスタンスを取得できます。
  $auth = authors::findID(2); if ($auth){ // }else{ //   } 


非静的メソッド


静的メソッドについては十分ですので、非静的メソッドに移りましょう。 特定のインスタンスに適用されるメソッド。
上記では、識別子2の著者のインスタンスを選択しました。リクエストが成功すると、クラスのインスタンスが作成されます。
  $auth->idauthor = 2; $auth->Name = "  "; $auth->Year = "1818—1883"; 

パラメータの変更は非常に簡単ですが、どのように保存しますか?
保存も同様に簡単です。 以下は保存する機能コードです。
  public function Save(){ //  - UPDATE $id = key(self::_getVars()); //  if (!isset($this->$id) || empty($this->$id)) return $this->Add(); // ,  $query = "UPDATE `".get_called_class()."` SET "; //  $columns = self::_getVars(); //   $Update = array(); //  foreach ($columns as $k => $v) { //   if ($id != $k) //    $Update[] = "`".$k."` = ".self::RenderField($this->$k); //   } $query .= join(", ",$Update); //   $query .= " WHERE `$id` = ".self::escape($this->$id)." LIMIT 1"; //   $result = self::$db->query($query); self::$stack->push($query." [".($result ? "TRUE" : self::getError())."]"); //  return ($result) ? true : false; //  } 

コードにはコメントが含まれており、追加の説明は不要です。 前の例に従って名前を変更するには、次のコードを実行する必要があります。
  $auth->Name = "  "; echo $auth->Save() ? "" : "  (("; 


Save関数には素晴らしいRenderField関数があります。 関数は非常に重要であり、静的であり、リクエストの正しい構築を担当します。そのコードを以下に示します。
  private static function RenderField($field){ $r = ""; //   switch (gettype($field)) { //    case "integer": case "float": // int  float $r = $field; break; case "NULL": $r = "NULL"; break; // NULL case "boolean": $r = ($field) ? "true" : "false"; break; // boolean case "string": //   $p_function = "/^[a-zA-Z_]+\((.)*\)/"; //   preg_match($p_function, $field,$mathes); //    if (isset($mathes[0])){ // ,   $p_value = "/\((.+)\)/"; //     preg_match($p_value, $field,$mValue); //  if (isset($mValue[0]) && !empty($mValue[0])){ //        $pv = trim($mValue[0],"()"); //    $pv = "'".self::escape($pv)."'"; //     $r = preg_replace($p_value, "($pv)" , $field); //   } else $r = $field; //    } else $r = "'".self::escape($field)."'"; //    break; default: $r = "'".self::escape($field)."'"; break; //   } return $r; //  } 

この関数は、テキストを単一引用符で囲む必要がある場合と含まない場合を決定します。

しかし、データベースにインスタンスを追加する必要がある場合はどうでしょう。 コードを実行して、クラスのインスタンスとして作成できます。
  $auth = new authors(); $auth->Name = "  "; $auth->Year = "1918-1983"; $auth->Add(); 


機能追加コードを以下に示します。
  public function Add(){ //  - INSERT $query = "INSERT INTO `".get_called_class()."` ("; //  $columns = self::_getVars(); //  $q_column = array(); //    $q_data = array(); //    foreach ($columns as $k => $v){ //   $q_column[] = "`".$k."`"; //   $q_data[] = self::RenderField($this->$k); //    } $query .= join(", ",$q_column).") VALUES ("; //   $query .= join(", ",$q_data).")"; //   $result = self::$db->query($query); //  $insert_id = self::$db->insert_id; //   self::$stack->push($query." [".($result ? $insert_id : self::getError())."]"); //  return ($result) ? $insert_id : false; //  } 


オブジェクトを削除


そして最後に、削除。 phpには削除機能はなく、伝統を壊しません。したがって、Remove()メソッドを呼び出します。
前の例から作成者のエントリを削除するには、コードを実行する必要があります。
  $auth = authors::findID(2); $auth->Remove(); 

インスタンスを選択して削除します。 すべてが非常にシンプルで簡潔です! 削除の機能コードは次のとおりです。
  public function Remove(){ //  - DELETE $id = key(self::_getVars()); //  if (!empty($this->$id)){ //    $qDel = "DELETE FROM `".get_called_class()."` WHERE `$id` = ".$this->$id." LIMIT 1"; $rDel = self::$db->query($qDel); //   self::$stack->push($qDel." [".($rDel ? "TRUE" : self::getError())."]"); //  return $rDel ? true:false; //  } else return false; //  } 


このORMライブラリは、特に書き始めたばかりなので、現代のモンスターではありませんが、小規模なプロジェクトでの使用には非常に適しています。 以下では、データベースモデルの自動生成について説明します。

Source: https://habr.com/ru/post/J305786/


All Articles