1

多次元配列があり、配列に正しいレイヤーの必須フィールドが含まれているかどうかを確認する必要があります。

それを達成するための良いアプローチはありますか?入力は配列またはJSONにすることができます。

これまでの私のアプローチ:

入力配列が次のようになっていると仮定します。

 Array (
    [key] => key string
    [sub] => Array (
        [0] => Array (
            [id] => 123456
            [src] => source string
            [src_ids] => Array (
                [0] => 1
                [1] => 2
                [2] => 3
                [3] => 4
            )
            [data] => Array (
                [a_data] => a string
                [b_data] => b string
                [c_data] => c string
            )
        )
        [1] => Array (
            [id] => 557799
            [src] => source string
            [src_ids] => Array (
                [0] => 1
                [1] => 2
            )
            [data] => Array (
                [a_data] => a string
                [b_data] => b string
                [c_data] => c string
            )
        )
    )
)

必須の値は次のとおりです。

sub, id, src, src_ids, data, a_data

オプションの値は、他のすべてのようなものです。

key, 0 (of sub), 0-3 (of src_ids), b_data, c_data

入力配列を必須フィールドと照合する関数が欲しいのですが。私のアイデアは、次のようなレイヤーに基づく配列として必須値を作成することでした。

$mandatory = array( 
    1 => array( 'sub' ),
    3 => array( 'id', 'src', 'src_id', 'data' ),
    4 => array( 'a_data' )
);

キーはレイヤーの深さであり、配列値はそのレイヤーで許可されているキー名です。

次に、入力配列をクロールして、深さに基づいてキーが必須フィールドにあるかどうかを確認します。

/**
 * 
 * @param array $i input
 * @param array $m mandatory
 * @param integer $d depth
 * @return boolean
 */
function validate( $i, $m, $d=1 ) {
    foreach( $i as $k => $v ) {
        if( isset($m[$d]) ) {
            if( !in_array($k, $m[$d]) ) {
                return false;
            } else {
                if( is_array($v) ) {
                    $d++;
                    validate($v, $m, $d );
                }
            }
        } else {
            if( is_array($v) ) {
                $d++;
                validate($v, $m, $d );
            }
        }
    }
    return true;
}

しかし、これは2つの大きな問題を引き起こします。

  1. レイヤー番号4は、src_idsとデータの配列を保持しますが、データにのみ必須フィールドa_dataがあります。したがって、レイヤー番号4の場合はfalseが返されます。
  2. しかし、主な問題はこの関数の論理的な問題です。現在、必須フィールドが設定されている場合はチェックせず、深度の入力値が必須フィールドにあるかどうかのみをチェックします。この動作は間違っています。

比較配列も使用しようとしましたが、エントリが複数あるため、すべてのエントリを必須配列と比較できませんでした。

どんな助け、提案または解決策も大歓迎です。

ありがとう

4

2 に答える 2

1

これはあなたの要件を満たしていますか?

必要なフィールド構造:

$required = array(
    'sub' => array(
        array(
            'id' => '',
            'src' => '',
            'src_ids' => '',
            'data' => array(
                'a_data' => '',
            ),
        ),
    ),
);

基本的に、入力配列の構造を模倣するだけです。フィールド名がキーです。必須のサブフィールドは子孫です。sub[0]やのようにリストの場合は、キーを数値/名前なしのままにしておきますsub[1]。リスト内の各項目の構造がチェックされます。

再帰的検証関数:

function checkRequired($data, $req)
{
    // no more required fields
    if (empty($req))
        return true;

    // no more data fields; obviously lacks required field(s)
    if (empty($data))
        return false;

    foreach ($req as $name => $subtree) {
        // unnamed; it's a list
        if (is_numeric($name)) {
            foreach ($data as $dataitem) {
                if (checkRequired($dataitem, $subtree) == false)
                    return false;
            }
        } else {
            // required field doesn't exist
            if (!isset($data[$name]))
                return false;

            // fine so far; down we go
            if (!empty($subtree)
                && checkRequired($data[$name], $subtree) == false
            ) {
                return false;
            }
        }
    }

    return true;
}

私はどこかでふざけている可能性がありますが、うまくいけば、これを何か有用なものに適応させることができます. これは、実験できる実際の例です。

于 2012-07-12T19:31:09.500 に答える
1

$inputおよびを説明どおりに定義すると$mandatory、残りのコードは次のようになります。

$values[1] = $input;
$layer = 1;
$found_layer = true;

while($found_layer)
{
        $found_layer = false;
        foreach($values[$layer] as $li=>$le)
        {
                if(is_array($le))
                {
                        $found_layer = true;
                        if(!isset($values[$layer+1])) $values[$layer+1] = array();
                        $values[$layer+1] = array_merge($le, $values[$layer+1]);
                        $values[$layer][$li] = 'array';
                }
        }
        $layer++;
}

$not_found = $mandatory;

foreach($not_found as $layer=>$keys_to_match)
{
        foreach($values[$layer] as $key=>$value)
        {
                foreach($keys_to_match as $ktmi=>$ktm)
                {
                        if($ktm==$key) unset($not_found[$layer][$ktmi]);
                }
        }
        if(!count($not_found[$layer])) unset($not_found[$layer]);
        else $not_found[$layer] = array_values($not_found[$layer]);
}

その場合、コードは$not_found次のように生成されます。

Array
(
    [3] => Array
        (
            [0] => src_id
        )

)

つまり、入力の 3 番目のレベル (「レイヤー」) に、 に従って必須であるキー「src_id」を持つ要素がないことを意味し$mandatoryます。すべての必須要素が見つかった場合、$not_found空になります。注意してください、あなたは持っ'src_id'ています$mandatoryが、$input明らかにキーしか持っていません'src_ids'

パフォーマンスのために再帰の使用を避けました。

于 2012-07-12T19:54:31.620 に答える