2012-02-23 4 views
1

初心者の質問:私は、このコードのビットを構成する最善の方法を知りませんが、基本的には、この(擬似コードの時間)のようになります:PHP:いくつかの機能が利用できるオブジェクトを作る

if (form = submitted) { 
    submitted(); 
} 
else { 
    printForm(); 
} 

function submitted() { 
    process data from form; 
    if(errors = found) { 
     print warnings; 
     printForm(); 
    } else { 
     submit to database; 
    } 
} 

function printForm() { 
    print form with databound elements; 
} 

Iを次のコードを使用してUserオブジェクトを作成しますが、submitted()に1回、printForm()に1回、特にsubmitted()にエラーが見つかるとprintForm()が呼び出されます。

残念ながら...データベースへのアクセスは、(電子メールアドレスなどの既存のチェック)フォームからのデータを処理するために必要とされるので、私はsubmitted()printForm()の両方で次のコードビットを呼び出す必要があり

try { 
    $db = new Database(); 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $user = new User($db); 
} 
catch (PDOException $e) { 
    echo "<p>Error connecting to database: </p>".$e->getMessage(); 
}  

しかし、私の本能は、これが悪いと私に伝えます。それは...ですか?もしそうなら、私はそれをどのように修正すべきですか?

答えて

3

使用dependency injection:あなたはすべての単一の機能に依存性を注入する必要はないとしてもちろん

function submitted(Database $db, User $user) { 
    // ... 
} 

function printForm(Database $db, User $user) { 
    // ... 
} 

try { 
    $db = new Database(); 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $user = new User($db); 
} 
catch (PDOException $e) { 
    echo "<p>Error connecting to database: </p>".$e->getMessage(); 
} 

submitted($db, $user); 
printForm($db, $user); 

、それは、OOPを使用することをお勧めします:ものの

class Foo { 
    protected $db; 
    protected $user; 

    public function __construct(Database $db, User $user) { 
     $this->db = $db; 
     $this->user = $user; 
    } 

    public function submitted() { 
     // use $this->db and $this->user here 
    } 

    public function printForm() { 
     // use $this->db and $this->user here 
    } 
} 

try { 
    $db = new Database(); 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $user = new User($db); 
    $foo = new Foo($db, $user); 
} 
catch (PDOException $e) { 
    echo "<p>Error connecting to database: </p>".$e->getMessage(); 
} 

$foo->submitted(); 
$foo->printForm(); 
+0

私はOOPに切り替えました。私は最初からそうしていたはずです。 –

2

は作るのいくつかの方法があります。この優れた...

一つの関数呼び出しの前に$ユーザーを初期化し、各機能(依存性注入)に注入することであろう。

もう1つの方法は、ユーザーインスタンスのシングルトンを作成することです(これは道路に問題が発生することがわかりましたが)。User::instance()などの関数を使用してインスタンスを取得します。

あなたの機能をテストしやすくするため、依存性注入は私の意見では優れています。コードの残りの部分に今


は、:

  1. それは、典型的には、関数やクラスメソッド内で何かをエコーすることをお勧めではありません。代わりにデータを返し、関数の外で処理する必要があります。
  2. dbインスタンス化は、すべてのスクリプトの先頭に含まれるブートストラップファイルに格納されているはずです。エラーメッセージを単にエコーするのではなく、接続が失敗した場合、スクリプトが接続エラーを正常に処理した場合(ユーザに何かが間違っていることを知らせ、電子メールを送信してスクリプトの実行を停止させる方が良いでしょう)
+0

+1ヒントをありがとう、私は自分のコードにそれらを取り入れています。 –

0

Singletonパターンが悪いと見なされる場合もありますが、PHPでは(リクエストごとに個別のワーカープロセスを使用して)、あなたの場合は、あなたが望むものを実装するのが最も簡単な方法です。あなたが任意のページ上の任意のスクリプトで利用可能な要求を開始したUserのインスタンスを持っている、とあなただけのプロジェクトごとに一つの場所に$userオブジェクトを初期化する必要があること(スクリプトごとに1であなたがやりたいと思ったないように

)。

+0

カップリング、隠された依存関係、グローバルな状態に関するすべての問題はPHPのシングルトンにも当てはまります。リクエストごとに1つのインスタンスを持つことは間違いありませんが、PHPでシングルトンを悪くすることはありません。それは単にそれらをさらに余分にします。 – Gordon

+0

隠された依存関係について私はあなたに同意します。しかし、私は、グローバルな状態であるグローバルな状態の背後にある悪を見ません。コールスタック内のすべてのメソッドにコンテキストを渡すのではなく、シングルトンにコンテキストを格納することは意味があります(コンテキストがそのようなシングルトンの存続期間にわたって変化しない場合)。 – penartur

+0

コールスタック内のすべてのメソッドに対してコンテキストが必要な場所に依存関係を置くために持ち歩かなければならないというのは神話です。 https://www.youtube.com/results?search_query=The+Clean+Code+Talks&aq=f – Gordon

関連する問題