1

さまざまなリターンの関数をより適切に処理する方法についてアドバイスが必要です。
私のクラスには、次のような単純なログイン関数があります。

public function login($email, $password){

$record = // Go to database and find what we need.

if($record){
   // Check pass, $user_match = TRUE;
} else {
   return 1;         //No such user. Please register!
}

$active = (1 == $record['is_active']) ? TRUE : FALSE;
$verified = (1 == $record['is_verified']) ? TRUE : FALSE;

//User email and password matched:
if($user_match == true){
   if($verified === true){
       // Start session and insert to db table "online_users"
   // Check that user was inserted to table: $confirm = $stmt->rowCount();

         if($confirm !== 1){
           return 2; //Unexpected technical error. Please try again in a moment.
         }

       return 0;     //0 means that all clear, we good to go.

       } else {
           return 3; //not verified
       }
    } else {
        return 4;    // no match with email and pass, reject!
    }
}

問題は、今では常にすべての返品をチェックする必要があるということです。次のようなものです。

$log = $user->login($_POST['email'], $_POST['pass']);
if($log === 0) {
    //Log in & edirect
} elseif ($log === 1) {
    //No such user. Tell to register
} elseif($log === 2){
    //technical error, try again
} elseif($log === 3){
    //Not verified
} elseif($log === 4){
    //wrong password

今は本当に迷惑です。20回の返品のようにチェックする必要があるかどうか想像してみてください。より良い方法はありますか?それをより効率的かつ迅速に行う方法は?
前もって感謝します。

4

4 に答える 4

3

この関数の目的を再考し、それに応じて戻り値の型を構成する必要があります。目的がユーザーのログインである場合、答えは 1 つしかありません。機能したか、機能しなかったかです。したがって、関数の主要な戻り値の型はブール値である必要があります。失敗のさまざまな原因をどのように区別するかは、別のトピックです。

オプション 1: 例外をスローする:

try {
    if (!$foo->login()) {
        echo 'Invalid credentials';
    }
} catch (UserNotActiveException $e) {
    ...
} catch (UserNotValidatedException $e) {
    ...
}

ログインの失敗は実際には例外的な状況ではないため、必ずしも最も洗練されたオプションではありません。

オプション 2: エラー状態をログイン プロバイダーに保存します。

if (!$foo->login()) {
    echo "You're not logged in because ", $foo->loginError();
}

これが良いかどうかは、クラスが他の方法でどのように使用されるかによって異なります。ステートフルになりすぎたくない場合があります。

オプション 3: ログインの問題をユーザーの状態から完全に分離します。

if (!$foo->login($user)) {
    switch ($foo->currentStatus($user)) {
        case $foo::ALL_OK :
             echo 'Login credentials invalid';
             break;
        case $foo::ACCOUNT_INACTIVE :
             ...
    }
}

オプション 4: ステータス オブジェクトを返す:

$result = $foo->login();
switch ($result->status) {
    case $result::ALL_OK :
        ...
}

それは基本的にあなたが今やっていることですが、マジックナンバーはありません。

于 2012-11-07T14:22:59.873 に答える
1

例外を使用することは、アプリケーションの残りの部分にどのように適合するかに応じて、エラー コードの明確な処理を提供する 1 つの方法になります。

Nanne が指摘したように、フロー制御に例外を使用するべきではありません。例外は例外的な状況を示すだけであるべきです。技術的なエラーは明らかに例外的な状況であり、例外を使用することは明確かつ適切です。

残りの部分に例外を使用することはあまり明確ではありませんが、それでもオプションです。失敗条件ごとに異なるエラー メッセージを使用して例外をスローしたり、失敗条件に適したハンドラーを持つ異なる例外クラスをスローしたりすることができます。

これ、このコードが他のコードとどのように適合するかに応じて、例外のセマンティクスを壊し始めています。たとえば、不適切な例外をスローすることを心配することなく、他の場所でログイン関数を呼び出すことができることは、有用または必要な場合があります。

結局、これらの失敗した条件のそれぞれについて明示的なチェックを行い、それらを関数内で返す必要性を回避することはおそらくありません。繰り返しになりますが、必要な柔軟性に応じて、ログインが成功した場合は true を返し、失敗した場合はエラー メッセージを返すことができます (===結果が真実であるだけでなく、真であることを確認するために使用します)。または、成功プロパティとエラー状態を含むオブジェクトを返すこともできます。これにより、少なくともエラー処理コードは、成功を確認してエラー コードを処理する問題になります。

障害条件ごとに大幅に異なるエラー処理メカニズムが必要な場合は、障害ケースごとに定数を返すことで、少なくともコードで何が起こっているかを明確にすることができます。LOGIN_PASSWORDS_DO_NOT_MATCHその後、不可解な番号の代わりに返すことができます。これは、エラー コードで確認できます。

于 2012-11-07T14:13:52.743 に答える
0

多くのステートメントswitchが必要な場合は、ステートメントを使用することをお勧めします。if-else

$log = $user->login($_POST['email'], $_POST['pass']);

switch ($log) {
   case 1:
     break; 
   case 2:
     break;
   //etc....
}

エラー コードを明確にするには、「マジック ナンバー」の代わりに、名前付き定数または name=>code ペアの静的配列を使用します。

static $ERROR_CODES = array(
   "WRONG_PASSWORD"=>1,
   "WRONG_EMAIL"=>2
);

switch ($log) {
   case LoginClass::$ERROR_CODES["WRONG_PASSWORD"]:
     break; 
   case LoginClass::$ERROR_CODES["WRONG_EMAIL"]:
     break;
   //etc....
}
于 2012-11-07T14:14:45.913 に答える
-1

INIファイルを使用できます

バグをiniファイルに書き込みます。

1 = "Error"
2 = " Technical"
3 = "Network"
...

そしてそれをiniファイルに保存します。次に、次のコードを使用します。

<?php
$array = parse_ini("er.ini");
echo $array[$log];
?>
于 2012-11-07T14:17:31.350 に答える