2016-04-12 13 views
0

ユーザーのための簡単なアクセスチェックを作成しようとしています。PHP:ユーザーが特定のグループに再帰的にアクセスできるかどうかを確認するにはどうすればいいですか?

$levels = ['trial' => [], 'enterprise' => ['admin'], 'paid' => ['trial'], 
'admin' => ['paid', 'editor'], 'editor' => []]; 

paidグループを見てみましょう:基本的に私はこのように定義されたtrialpaidadmin、などのようなグループの配列を持っています。 paidグループはtrialグループの配列にあります。paidグループのユーザーはtrialグループにアクセスすることもできます。 adminがその配列内paid基を有し、paid基は、その配列内trial基を有するため

同様admin基が(私は推測再帰を必要とする)paideditortrialグループにアクセスすることができます。

My機能は、このようなものです(私は再帰部分を把握することはできません):

<?php 
public function hasAccess($requiredLevel, $myLevel) {  
    global $levels; 
    return (($myLevel == $requiredLevel) || (in_array($requiredLevel, $levels[$myLevel])); 
} 

これは、例えば、レベルは、アレイ内に直接存在する場合に動作しますが、関連付けを作るために失敗しましたレベルが接続されているときadmin => paid => trial

この関数を簡単に再帰的にチェックできるようにこの関数を変更する方法はありますか?

P.それらが格納される順序も固定されていません。

答えて

1

これはそれを行う必要があります。

public function hasAccess($requiredLevel, $levels, $myLevel) { 
    // Check if $myLevel matches $requiredLevel 
    if ($requiredLevel === $myLevel) { 
     return true; 
    } 

    // Iterate through all levels under $myLevel 
    foreach ($levels[$myLevel] as $level) { 
     // If any of those levels has access, return true 
     if ($this->hasAccess($requiredLevel, $levels, $level)) { 
      return true; 
     } 
    } 

    return false; 
} 

私はあなたのために十分なまでのそれは明らかコメントを願っています。

グローバル変数を使用する代わりに、$levelsを引数として渡すことをお勧めします。グローバル変数を使用すると柔軟性が向上するため、一般的には悪い方法です。

あなたが気を付けておいていただきたいのは、無限ループに終わる循環参照だけです。これを解決するには、既に訪問したレベルの配列をオプションの引数として渡します:

public function hasAccess($requiredLevel, $levels, $myLevel, $visited = []) { 
    // Check if $myLevel matches $requiredLevel 
    if ($requiredLevel === $myLevel) { 
     return true; 
    } 

    // Add the current level to the visited array 
    $visited[] = $myLevel; 

    // Iterate through all levels under $myLevel 
    foreach ($levels[$myLevel] as $level) { 
     // Return true if any of those levels has access, 
     // and hasn't been visited before 
     if (
      !in_array($level, $visited) && 
      $this->hasAccess($requiredLevel, $levels, $level, $visited) 
     ) { 
      return true; 
     } 
    } 

    return false; 
} 
+0

素晴らしい!今はとても簡単に見えますが、私はちょうど再帰の周りで頭を包むことができませんでした。コード内の詳細なコメントに感謝します。また、循環参照ビットについて説明してください。 2つのレベルが 'admin' => ['paid']と 'paid' => ['admin']のように互いに参照している場合、または他の場合はありますか?どのように私はそれに対して保護するのですか?本当にありがとう。 – supersan

+0

はい、私は循環参照の意味です。私は自分の答えを更新しました。 –

関連する問題