2012-08-27 7 views
5

少し紹介してみましょう。私はPHPでOOPを学ぶ過程にあります。私はDesign Patternsも研究しましたが、さまざまなタイプの概念をまだ完全には把握していません。私は数ヶ月おきに私が正しいことをやっているわけではなく、自分のスタイルを変えなければならないことを認識しています。 これはとてもイライラです。それゆえ、私は物事を一回だけ行う正しい方法を見出したいと思います。私は完全には、次のトピックについてStackOverflowの上に読むことを試みている:私はまだいくつかのことについて明確ではないよしかしPHPでOOPプログラミングでクラスを設定する正しい方法は何ですか?

ORM
データマッパー
シングルトン
グローバルは

関連
すべて悪です。私はここに明確かつ簡潔な方法で私のコードを掲載しています。人々がの両方を指摘できることを願っています。は良い方法と悪い方法です。最後にすべての質問をリストアップします。

私は正直に話題のほぼすべての質問を検索しましたが、私はまだ明らかにできなかったいくつかのことを知りたいと思います。申し訳ありませんが、それはとても長いですが、私はそれを整理しようとしましたので、よく読んでください!

私は、データベースクラスの本質を投稿することから始めます。

database.phpで

<?php 


class DatabaseMySQL{ 

    private static $dbh; 

    public function __construct(){ 
     $this->open_connection(); 
    } 

    public function open_connection(){ 
     if(!self::$dbh){ 
      return (self::$dbh = new PDO(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME, DB_USER,DB_PASSWORD)) ? true : false; 
     } 
     return true; 
    } 

    public function query($sql, $params=array()){ 
     $this->last_query = $sql; 
     $stmt = self::$dbh->prepare($sql); 
     $result = $stmt->execute($params); 
     return $result ? $stmt : $stmt->errorInfo(); 
    } 

    public function fetch_all($results, $class_name=''){ 
     return $results->fetchAll(PDO::FETCH_CLASS, $class_name); 
    } 

} 

?> 

これは私のDatabaseクラスファイルです。このクラスは私がこのクラスのように多くのインスタンスを作成することを可能にし、クラスのStaticプロパティとして格納されている既にインスタンス化されたPDOオブジェクトを再利用します。また、PDOを使用して結果セットからデータを取り出し、指定されたクラスのオブジェクトとしてデータを取得します。

私が持っている次のファイルは、他のすべてのクラスが継承しているクラスです。私はそれをMainModelと呼んだ。これが慣習に従うかどうかはわかりません。

MainModel.php

<?php 



abstract class MainModel{ 

    protected static $table; 

    public function __construct($array=array()){ 
     $this->assign_known_properties($array); 
    } 

    public function assign_known_properties($array){ 
     foreach($array as $key=>$value){ 
      $this->$key = $value; 
     } 
    } 

    public static function find_by_id($id){ 
     $db = new DatabaseMySQL(); 
     self::intialise_table_name(); 
     $id = (int) $id; 
     $sql = "SELECT * FROM ".static::$table." "; 
     $sql .= "WHERE id = {$id} ";  
     $result = self::find_by_sql($sql);  
     return array_shift($result); 
    } 

    public static function find_all(){ 
     $db = new DatabaseMySQL(); 
     self::intialise_table_name(); 
     $sql = "SELECT * FROM ".self::$table." "; 
     return self::find_by_sql($sql); 
    } 

    public static function fetch_as_objects($results){ 
     $db = new DatabaseMySQL(); 
     $called_class = get_called_class(); 
     $results = $db->fetch_all($results, $called_class); 
     return $results; 
    } 

    public static function find_by_sql($sql){ 
     $db = new DatabaseMySQL(); 
     $results = $db->query($sql); 
     return $results ? self::fetch_as_objects($results) : false; 
    } 

    public static function intialise_table_name(){ 
     $called_class = get_called_class(); 
     static::$table = strtolower($called_class).'s'; 
    } 

    public function get_table_fields(){ 
     self::intialise_table_name(); 
     $sql = "SHOW FIELDS FROM ".static::$table." "; 
     return self::find_by_sql($sql); 
    } 

    public function set_table_details(){ 
     $fields = $this->get_table_fields(); 
     $total = count($fields); 
     $array = array(); 
     foreach($fields as $object){ 
      $array [] = $object->Field; 
     } 
     $this->table_details = array('objects'=>$fields,'array'=>$array,'total'=>$total); 
     $this->set_placeholders_for_new_record(); 
     $this->set_properties_as_array(); 
     $this->set_properties_as_array(true); 
    } 

    public function set_properties_as_array($assoc=false){ 
     $array = array(); 
     if (!$assoc){ 
      foreach($this->table_details['array'] as $field){ 
       if(isset($this->$field)){ 
        $array [] = $this->$field; 
       }else{ 
        $array [] = NULL; 
       } 
      } 
      $this->table_details['values'] = $array; 
     }else{ 
      foreach($this->table_details['array'] as $field){ 
       if(isset($this->$field)){ 
        $array[$field] = $this->$field; 
       }else{ 
        $array [$field] = NULL; 
       } 
      } 
      $this->table_details['assoc_values'] = $array; 
     } 
    } 

    public function set_placeholders_for_new_record(){ 
     $string = ''; 
     for($i=0; $i<$this->table_details['total']; $i++){ 
      $string .= '? '; 
      if(($i+1) != $this->table_details['total']){ 
       $string .= ", "; 
      } 
     } 
     $this->table_details['placeholders'] = $string; 
    } 

    public function create(){ 
     $db = new DatabaseMySQL(); 
     $this->set_table_details(); 
     $sql = "INSERT INTO ".static::$table." "; 
     $sql .= " VALUES({$this->table_details['placeholders']}) "; 
     $result = $db->query($sql, $this->table_details['values']); 

     // If array is returned then there was an error. 
     return is_array($result) ? $result : $db->insert_id(); 
    } 

    public function update(){ 
     $db = new DatabaseMySQL(); 
     $this->set_table_details(); 
     $sql = "UPDATE ".static::$table." "; 
     $sql .= " SET "; 
      $count = 1; 
      foreach($this->table_details['array'] as $field){ 
       $sql .= "{$field} = :{$field} "; 
       if($count < $this->table_details['total']){ 
        $sql .= ", "; 
       } 
       $count++; 
      } 

     $sql .= " WHERE id = {$this->id} "; 
     $sql .= " LIMIT 1 "; 
     $result = $db->query($sql, $this->table_details['assoc_values']); 
     return $result; 
    } 

    public function save(){ 
     return isset($this->id) ? $this->update() : $this->create(); 
    } 
} 


?> 

このファイルを要約します。呼び出されたクラスのオブジェクトを動的に生成する静的メソッド、例えばfind_by_id($int)を使用します。 Late Static Bindingsを使用して呼び出されるクラスの名前にアクセスし、$stmt->fetchAll(PDO::FETCH_CLASS, $class_name)を使用して、これらのオブジェクトをデータベースからのデータでインスタンス化し、自動的にオブジェクトに変換します。

各静的メソッドでは、DatabaseMySQLクラスのインスタンスをインスタンス化します。それぞれの静的メソッドでは、クラスの名前を取得してsを追加することによって、動的にSQLクエリで使用される正しい静的な名前$tableを設定しました。だから私のクラスがUserだったら、テーブル名はusersになります。

私のコンストラクタでは、オブジェクトのプロパティとして変数を挿入するために使用できるオプションの配列を作成しました。このようにすべてが動的に行われるため、私は自分のプロジェクトの最終段階にいられます。私の継承クラス。

User.php

class User extends MainModel{ 

} 

Question.php

class Question extends MainModel{ 

} 

は、私が今やっていることは簡単です。私は言うことができます:

$user = new User(array('username'=>'John Doe')); 
echo $user->username; // prints *John Doe* 
$user->save(); // saves (or updates) the user into the database. 

私は静的な呼び出しでユーザーを取得できます。私の質問のためのだから今

$user = User::find_by_id(1); 
echo $user->username; // prints users name 

  • 1)それが一つでも全く).dataのマッパーである場合は、(このデザインパターンを呼ぶものの名前は?依存性注射?ドメインモデル(それが何であれ)?データアクセス層?

  • 2)今のところ、この実装はうまく構成されていると考えられますか?

  • 3)良いことがあれば、私のコードには欠落していることを知っておくべき命名規則がありますか?

  • 4)あなたが特に気に入った点を指摘してもよろしいので、どの部分を確実に保存するか分かりますか?

  • 5)なぜそれが良いのではないかと思われる場合は、詳細な説明をしてください。

  • 6)万一私のcreateupdate、私のfind_by_id、唯一の静的と呼ばれているfind_allと同じクラスになると、実際にオブジェクトを返す私のオブジェクトのすべてのメソッドをしているdelete。彼らが2つの異なるクラスにいなければならない場合は、どうすればよいですか?

  • 7)なぜ誰もが$load->('UserClass')機能を使用し、マッパーのような派手な言葉を使用していますが、私は一度もそれらを必要としませんでしたか?

+4

これは、ここに適合します:http://codereview.stackexchange.com/ –

+1

@IliaRostovtsev私はそれを知っていませんでしたが、私はまだ専門家からの答えがほしいと思う、私は彼らが主にここにいると思う! –

+3

No.話題だけを読んではいけません(私はSOを最初の参照として使用することをお勧めしません)。経験を積む、あなたの手を汚くするのを恐れないでください(この質問は良いスタートです)。黒と白がないことを知ってください。文脈はわかりませんが、グローバルは必ずしも悪いものではなく、悪用されると恐ろしいものです。 ORMとシングルトンの場合と同じことですが、すべての場合、それは良い習慣ですが、必ずしもベストではありません。 – skytreader

答えて

1

解決策は、「Active Record」と呼ばれています。メリットと欠点のために、Martin Fowlerの本「エンタープライズアーキテクチャのパターン」と、インターネット上で見つけられる会話の多くを読むことができます。

私の個人的な見解は、プライマリ・ビジネス・ロジックがデータベースに読み書きするデータベース駆動型アプリケーションを構築するための完璧な方法です。より複雑なビジネスロジックを構築する際には少し負担になりがちです。

また、スタックオーバーフローは「このトピックについてお聞かせください」スタイルの質問ではなく、客観的に真の回答がある回答です。だから、あなたの質問1は適合しますが、他のものは実際には適していません...

+0

時間を割いてくれてありがとうNeville、ありがとう、私は私の質問がこのトピックのスタイルについて議論していたと思っていませんでした。質問3と質問6はどうですか? –

+0

@InGodITrustおそらく、あなたは神= pに尋ねるべきです。私は3と6に答えます:命名規則と名前空間については[PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md)を読んでください。これは現在の標準です。あなたのメソッドについては、それらをすべて同じクラスに入れることは大丈夫です。 ORMからDBALを分離することも考えてください。問合せ構築部分とエンティティ/関係部分から接続部分を分離する必要があります。これはすべて学習には良いことですが、私もそれをやっています。実際のプロジェクトでは、Doctrine2やSymfony2のようなよくテストされたライブラリを使うべきです。 – ChocoDeveloper

+0

@ChocoDeveloper私は彼に依頼して、まだ返信を待っています。ヒント、あなたが与えた素晴らしいリンクありがとう! –

関連する問題