0

私のプロジェクトのコードはすべて手続き型です。フレームワークや MVC 構造を使用していません。PHP のほとんどは、いくつかのロジックを備えたフォーム ハンドラーです。次のようなコードがたくさんあります。

<?php

require "headerFile.php";

$user = array(); // filled with user data

if (isset($_POST['submitButton'])) {
    if (isset($_POST['money'])) {
        if (is_numeric($_POST['money'])) { // I don't actually validate numbers this way
            if ($_POST['money'] <= $user['money']) {
                $query = mysql_query("SELECT * FROM someTable WHERE id={$user['id']}");

                if($result = mysql_fetch_array($query)) {
                    if ($someOtherCheck == $user['someOtherData']) {
                        /*
                         * run some queries, give user some item
                         *
                         */
                    } else {
                        echo "This isn't right.";
                    }
                } else {
                    echo "You don't have a row in some table!";
                }
            } else {
                echo "You don't have that much money!";
            }
        } else {
            echo "Enter a valid number";
        }
    } else {
        echo "Enter how much you want to wager.";
    }
}

// some hard coded form goes here

require "footerFile.php";

?>

これらのフォームは 100 を超え、ネストされた if ハンドラーがあり、条件が多い/少ない類似のものもあります。

OOP の使用を開始したいと考えており、デザイン パターンについて調べていますが、自分のプロジェクトに適用できるものが見つからないようです。

上記のブロックに似た新しいコード ブロックを大量に追加しています。コピーして貼り付けて、あちこちでいくつかのビットを変更したくありません。どのようなオプションがありますか?

4

7 に答える 7

2

まず、大きな赤い旗であるはずのコードをコピーして貼り付ける場合。これは、コピーアンドペーストの代わりに、使用できる一般化された関数を作成する必要があるという警告です。

第二に、それは本当に-のようmysql_queryな関数の使用をやめる時です。PHPページでさえ、これらの関数の使用は推奨されていないと述べています。SQLをよりOOに似たPDOに移行し始めます。

あなたが投稿したコードに似たアプリケーションを継承したとき、私は物事を処理し始めるために取った手順についてブログに投稿しました。それはあなたにも役立つかもしれません-http://mattmccormick.ca/2011/10/13/how-to-refactor-a-php-application/

于 2012-10-02T22:23:17.657 に答える
1

フレームワークについて

適切なフレームワークは、懸念事項の分離を通じてコードをより適切に編成するのに役立ちますが、必ずしもベスト プラクティスを強制するわけではありません。主観的に言えば、ベスト プラクティスが頭に定着するまでには、実践的な経験と多くの間違いを犯す必要があります。

フレームワークを配信メカニズムとしてのみ考えてみてください。最適なのは、コードが 1 つのフレームワークに結び付けられていないことです。これは通常、コンポーネントを使用して、ルーティング、検証、構成、イベント、依存関係など、アプリケーションのさまざまな側面を処理することを意味します。


OOPについて

あなたが始めるべきだと私が思うことは、SOLIDの原則です。これにより、保証はできませが、後で多くの時間を費やすミスを避けることができます。

何よりも、オブジェクトは単一の責任のみを持つ必要があります。たとえば、Productオブジェクトは、データ ストアとしての機能、永続化、注文の処理などの責任を負うべきではありません。

また、別の大物は依存性注入です。これは、クラスの単体テストに非常に役立ちます (これを習慣化する必要があります)。一言で言えば、クラスで依存関係を構築しないでください。事前に構築し、コンストラクター引数またはセッター メソッドのいずれかを介して渡します。

アプリケーションを設計するプロセスは、独自の書籍を用意する価値があるため、ここですべてを書くつもりはありません。ただし、SOLID の原則に従えば、より優れた開発者になることができます。


上記のコードについて

そのような入れ子は一般的に匂いであり、なぜあなたが質問をしているのかわかります...

ステップ 1 は、検証を独自のサービスに分離することです。これを MVC の意味で考えると、少なくともコントローラーには [pseudocode] しかありませんif ($form->isValid()) { do something }。これだけで、あなたが持っているスパゲッティの大部分がなくなります.

于 2012-10-02T22:24:36.970 に答える
1

OOP は必ずしもアプリケーションに関するものではありません。読みやすさと構造についてです。正直なところ、ここに投稿したコードはどれくらい読みやすいですか? たくさんのことが起こっており、それらをすべて解読するには 10 分かかります。ただし、クラス関数を使用してクラスに分解すると、物事が一目でわかり、何が起こっているかを知ることができます。

OOP は常に php に対して大量の処理を行うわけではありませんが、他のほぼすべての非静的ロード言語に対して行う必要があります。プロジェクトに複数のプログラマーがいる場合、両方ともコードを読むことができるという追加の利点があります。コメントは友達です。

最良の選択肢は、戻り値のある関数を使用することです。値を返すと、関数は必要なことを何でも行います。私は個人的に次のようなことをします

$class->check

エラーの場合

$this->error_handler

そして、関数のエラー ハンドラは、ダイまたはエコーの場合はエラーでやりたいことは何でもしますが、エラー ハンドラを作成するので、それを変更したい場合は、20 ではなく 1 か所でチャンスを与えます。 .

于 2012-10-02T21:58:59.900 に答える
1

OOP を導入しなくても、コードを構造化して読みやすくすることは驚くべきことです。条件が相互に依存していない場合は、条件をネストする必要はありません。

$form_is_valid = true;

if (!isset($_POST['submitButton'])) {
    echo "This isn't right.";
    $form_is_valid = false;
}

if (!isset($_POST['money'])) {
    echo "Enter how much you want to wager.";
    $form_is_valid = false;
} elseif (!is_numeric($_POST['money'])) {
    echo "Enter a valid number";
    $form_is_valid = false;
} elseif (!$_POST['money'] <= $user['money']) {
    echo "You don't have that much money!";
    $form_is_valid = false;
}

if ($form_is_valid) {
    do_stuff_here();
}
于 2012-10-02T22:12:34.377 に答える
0

OOP の使用を開始したいと考えており、デザイン パターンについて調べていますが、自分のプロジェクトに適用できるものが見つからないようです。

まだ始める必要はありpatternsません..基本を理解すれば、そこから進めることができます..

これは基本的な例です

if (isset($_POST['submitButton'])) {

    $db = new \mysqli("localhost", "user", "pass", "db");

    $user = new User("Juddling Stack", 123456);
    $user->setMoney(500.01);

    $player = new PlayerRegister($db, $user);

    if (! isset($_POST['money']) || ! is_numeric($_POST['money']))
        $player->addError("Enter Valid Wager Money");

    if ($_POST['money'] <= $user['money']) {
        $player->addError("You don't have that much money!");
    }

    try {
        $player->doSQL();
    } catch ( BaseException $e ) {

        foreach ( $e->getError() as $error ) {
            echo $error, " <br />";
        }
    }
}

使用クラス

于 2012-10-02T22:55:23.883 に答える
0

OOP を使用しておらprogramming-overhead、呼び出されている、またはプログラマー用語で発生している問題を述べるところから始めましょうspaghetti-code

多くのオーバーヘッドが発生した場合、つまり、内容が異なるだけで機能は同じである、ほぼ同じコード行を書くのに時間が費やされていることを意味します。次に、機能が同じであるが、その内容を区別するコードのすべての平和をスライスし始めます。

あなたは、コピーして貼り付ける必要があると述べましたが、さらに複雑で、form検証部分 (ステージ 1 と呼んだもの) を行うだけです。これは、すべての作業を行うロジックを適用する方法の簡単な例にすぎません。それが期待する供給入力。1 つの例は、他の例よりもエレガントかもしれません。

以下のすべてのコードはテストされていません

同等の機能のコードを見つけるための例。

 // functionality on checking values is the same, but it's content is not
 if (isset($_POST['submitButton'])) {
   if (isset($_POST['money'])) {
     if (is_numeric($_POST['money'])) {

 // though every decision made by its content is only being produced once .. 
      } else
          echo "You don't have that much money!";
    } else
        echo "Enter a valid number";
} else
    echo "Enter how much you want to wager.";

ここでのコツは、これを論理的に解決するための解決策を見つけることです。PHP には組み込み関数がたくさんありますが、まずそれを解決する方法についてのアイデアを把握してください。例としてkey、 のような各 に、設定/存在しない場合に等しい値を持たせることがsubmitButton挙げられます。次に、値を によって提供されるキーと比較しているため、何があっても..配列が意思決定者です。moneynot existsnull$_POST$_POST

jQueryキーにデフォルト値を適用するメソッドを使用してライブラリが構築された例が分かり$.extend()やすいので、キーには常に値があり、存在するかどうかを最初にチェックしないことで常に決定を下す必要があります。しかし、PHP も同様です。

値をデフォルトにしましょう。

$_POST = array_merge(array(
  'submitButton' => null,
  'money' => 0,
  'etc' => '...'
, $_POST);

この配列を検証する関数の作成は、存在する値に常に依存できるため、はるかに簡単になりました。

あなたは、検証が必要なフォームが他にもたくさんあると述べました。特定のフィールドを検証する関数を次に見つけ出す必要があります。

有効または無効なフォームの正式な表現は、配列にすることができます。

$valid_form = array(
  'submitButton' => array('not_null'),
  'money' => array('not_null','int'),
  'etc' => '...'
); 

検証する関数は次のようになります

function validateForm($values, $valid) {
  // error array to be returned
  $error = array();
  // let's iterate over each value, remember we defaulted the $_POST array with
  // all the fields it can have, so all fields should be iterated apon.
  foreach($values as $key => $value) {
    if(array_key_exist($key, $valid)) {
      // logic content can be used by different functions, switch
      // used here for simplicity
      foreach($valid[$key] as $validation) {
        switch($validation) {
          case 'not_null':
            if(is_null($value)) {
              $error[] = "error logic";
              continue; // skip rest
            }
          break;
          case 'etc':
            $error[] = "..";
          break;
        }
      }
    }
  }
  return $error ? $error : true; // true being valid
}

エラー処理はさまざまな方法で実行できますが、単純な例を 1 つだけ挙げると (このプロジェクトがどれだけ広範囲になるかによって異なります)、エラーの内容を検証キーにバインドできます。

$vfe = $valid_form_errors = array( // $vfe for simlicity's sake
  '__no_error' => 'no error present for "%key%" validation',
  'not_null' => '%key% should not be null',
  'int' => '%key% expects to be an integer'
);

$valid_form = array(
  'submitButton' => array('not_null'),
  'money' => array('not_null','int'),
  'etc' => '...'
);

正式なエラー メッセージを作成する関数

function error_msg($key, $validation) {
  global $vfe;
  // error exists?
  $eE = array_key_exists($validation,$vfe);
  return str_replace('%key%', $eE?$key:$validation, $vfe[$eE?$validation:'__no_error']);
}

そして単純なスイッチでは、エラーロジックは

  foreach($valid[$key] as $validation) {
    switch($validation) {
      case 'not_null':
        if(is_null($value))
          $error[] = error_msg($key, $validation);
      break;
      case 'etc':
        $error[] = "..";
      break;
    }
  }

では、別のロジックを使用すると、コードはどのように見えるでしょうか?

    // first stage ..
    $form_valid = validateForm($_POST, $valid_form);    
    if ($form_valid === true) {
      // second stage, same logic be applied as with validateForm, etc.
      if($_POST['money'] <= $user['money']) {
        $query = mysql_query("SELECT * FROM someTable WHERE id={$user['id']}");

        if($result = mysql_fetch_array($query)) {
            // third stage, same logic can be applied here..
            if ($someOtherCheck == $user['someOtherData']) {

            } else {
                echo "This isn't right.";
            }
        } else {
            echo "You don't have a row in some table!";
        }
    }
    else {
      $errors = $form_valid;
      // error handling here
      print_r($errors);
    }    

すべては、期待される値をどれだけ具体的に定義できるかにかかっています。エラーをフォームキーにバインドするなど、すべての機能をより具体的に拡張して、後の段階でその入力を具体的に対象とすることができます。重要なことは、関数が期待する値を比較するように頼むだけでこれらすべてを実行する可能性のある重複をすべて消去し、実際にどの値があるかを彼に伝えることです。

于 2012-10-02T23:08:57.463 に答える
0

コードがモデル レイヤーとビュー レイヤーの両方の特定のコンポーネントを組み合わせているようです。データベースに対してクエリを実行していて、同じ場所にハードコードされたフォームを含めています。したがって、これらのタスクを 2 つの別個のクラスに分割することから始めるのがよいでしょう。たとえば、データベースに接続してそれに対してクエリを実行するクラスを作成し、実際にコンテンツを提供する別のクラスを作成します。

デザイン パターンに関する私のアドバイスは、詳細に行き詰まりすぎないようにすることです。代わりに、なぜ特定のパターンが非常に役立つのか、どのような問題を解決しようとしているのかを理解しようとします。多くの初心者はhowに行き詰まりすぎて、単純な解決策で十分だったフレームワークのニュアンスを学ぶのに多くの時間を無駄にしてしまいます。

最後に、コードを読むときは、クラスに構造化される可能性のあるものに注意してください。また、専門化が重要であることを忘れないでください。その機能に非常に特化したクラスを構築することで、他のプロジェクトで使用できる可能性のあるモジュラー コンポーネントを構築することになります。

于 2012-10-02T22:19:05.583 に答える