9

したがって、私は PHP のバックグラウンドが豊富なわけではありません。また、整形式のコードでは、「スーパーグローバル」を直接使用する必要があるかどうか疑問に思っていました。たとえば、関数 say$_SESSION['x'] = 'y';または if の途中で、通常は変数、そこから使用できる引数としてそれらを送信することをお勧めします。

class Doer {
    private $sess;
    public function __construct(&$sess) {
        $this->sess =& $sess;
    }
} 

$doer = new Doer($_SESSION);

次に、Doer->sessDoer 内などからバージョンを使用します。(この方法の利点は、Doer$_SESSION の使用が明確になることです。)

この問題に対して受け入れられている PHP 設計アプローチは何ですか?

4

6 に答える 6

13

私は、、、、およびを OOP 構造にラップするのが好きです$_SESSION$_POST$_GET$_COOKIE

私はこの方法を使用して、サニテーションと検証、必要なすべてのisset ()チェック、ノンス、setcookieパラメーターなどを処理するコードを一元化します。また、クライアント コードをより読みやすくすることができます (そして、より保守しやすいという錯覚を与えます)。

特に複数のコーダーがいる場合、この種の構造の使用を強制するのは難しいかもしれません。$_GET$_POST、および(と私は信じています) を使用$_COOKIEすると、初期化コードでデータをコピーしてから、スーパーグローバルを破棄できます。私は試していませんが、巧妙なデストラクタが $_SESSION (ロード時に $_SESSION を消去し、デストラクタに書き戻す) でこれを可能にする可能性があります。

ただし、通常、これらの強制手法は使用しません。慣れてくると$_SESSION、セッションクラス以外のコードを見ると変な感じになってしまい、ほとんどソロで作業しています。

編集
誰かに役立つ場合に備えて、サンプルクライアントコードを次に示します。主要なフレームワークのいずれかを見ると、より良いアイデアが得られると確信しています...

$post = Post::load ();  
$post->numeric ('member_age');  
$post->email ('member_email');
$post->match ('/regex/','member_field');
$post->required ('member_first_name','member_email');
$post->inSet ('member_status',array('unemployed','retired','part-time','full-time'));
$post->money ('member_salary');
$post->register ('member_last_name'); // no specific requirements, but we want access
if ($post->isValid())
{
  // do good stuff
  $firstName = $post->member_first_name;
}
else
{
  // do error stuff
}

Post とその仲間はすべて、コア検証コードを実装する基本クラスから派生し、フォーム トークン、セッション Cookie 構成などの独自の特定の機能を追加します。

内部的には、クラスは検証メソッドが呼び出されたときに抽出された有効なデータのコレクションを保持し、魔法のメソッド$_POSTを使用してそれらをプロパティとして返します。__get失敗したフィールドには、この方法ではアクセスできません。私のバリデーション メソッド ( を除くrequired) は、空のフィールドで失敗することはありません。それらの多くはfunc_get_args、一度に複数のフィールドを操作できるようにするために使用します。一部のメソッド ( などmoney) は、データをカスタム値の型に自動的に変換します。

エラーの場合、データをセッションに保存できる形式に変換し、フォームに事前入力し、元のフォームにリダイレクトした後にエラーを強調表示するために使用する方法があります。

これを改善する 1 つの方法は、フォームのレンダリングに使用される Form クラスに検証情報を格納し、クライアント側の検証を強化し、送信後にデータをクリーニングすることです。

于 2010-08-17T00:29:22.440 に答える
4

スーパーグローバルの内容を変更することは、悪い習慣と見なされます。特にコードが 100% 制御下にある場合は特に問題はありませんが、混合ソース コードを検討する場合は特に、予期しない副作用につながる可能性があります。たとえば、次のようなことをするとします。

$_POST['someval'] = mysql_real_escape_string($_POST['someval']);

PHP が 'someval' を使用可能にするすべての場所で変更が行われることを期待するかもしれませんが、そうではありません。コピーは$_REQUEST['someval']変更されず、元の「安全でない」バージョンのままです。これは、$_POST ですべてのエスケープを行うと、意図しないインジェクションの脆弱性につながる可能性がありますが、後のライブラリは $_REQUEST を使用し、すでにエスケープされていると想定します。

そのため、スーパーグローバルを変更できる場合でも、スーパーグローバルを読み取り専用として扱うのが最善です。値をいじる必要がある場合は、独自の並列コピーを維持し、そのコピーを維持するために必要なラッパー/アクセス メソッドを実行します。

于 2010-08-17T02:44:53.820 に答える
4

この質問は古いことは知っていますが、回答を追加したいと思います。

入力を処理するマリオのクラスは素晴らしいです。

私は、何らかの方法でスーパーグローバルをラップすることを好みます。これにより、コードが非常に読みやすくなり、保守性が向上します。

たとえば、私の現在の仕事には、嫌いなコードがいくつかあります。セッション変数は非常に頻繁に使用されるため、サイト全体に大きな影響を与えずに実装を現実的に変更することはできません。

例えば、

アプリケーションに固有の Session クラスを作成したとします。

class Session
{
    //some nice code
}

次のようなものを書くことができます

$session = new Session();
if( $session->isLoggedIn() )
{
   //do some stuff
}

これに対して

if( $_SESSION['logged'] == true )
{
   //do some stuff
}

これは些細なことのように思えますが、私にとっては大したことです。将来、インデックスの名前を「logged」から「loggedIn」に変更したいと決めたとします。

これを変更するには、セッション変数が使用されているアプリ内のすべての場所に移動する必要があります。または、そのままにして、両方の変数を維持する方法を見つけることもできます。

または、そのユーザーが管理者ユーザーであり、ログインしていることを確認したい場合はどうすればよいですか? このため、セッションで 2 つの異なる変数をチェックすることになるかもしれません。しかし、代わりにそれを 1 つのメソッドにカプセル化して、コードを短くすることができました。

これにより、他のプログラマーがコードを読みやすくなり、コードを見るときにそれについて「考える」必要がなくなるため、コードを見るのに役立ちます。メソッドにアクセスして、ユーザーをログインさせる方法が 1 つしかないことを確認できます。「ログイン済み」チェックをより複雑にしたい場合は、IDE でグローバル検索を実行してそのように変更しようとするのではなく、1 つの場所に移動して変更するだけでよいため、これも役立ちます。

繰り返しますが、これは些細な例ですが、セッションをどのように使用するかによっては、メソッドとクラスを使用してアクセスを保護するこのルートにより、作業がはるかに簡単になります。

于 2012-04-16T03:25:08.950 に答える
0

スーパーグローバルを参照渡しすることはまったくお勧めしません。あなたのクラスでは、変更しているものがセッション変数であることは不明です。また、 $_SESSION はクラス外のどこでも使用できることに注意してください。クラスに関係のない変数を変更することによって、そのクラスの外部からクラス内の変数を変更できるのは、オブジェクト指向の観点からは非常に間違っています。public 属性を持つことは悪い習慣であると考えられており、これはさらに最悪です。

于 2010-08-16T23:57:50.333 に答える
-3

これはPHPの適切な使用法ではありません。

$_SESSION変数を直接取得します。

$id   = $_SESSION['id'];
$hash = $_SESSION['hash'];

于 2010-08-16T23:37:16.543 に答える