4
\$\begingroup\$

On my webform, there are two kinds of address-fields a user can give. But since it's a complex webform (Drupal) it's kind of hard to achieve. Every time a user adds an extra address, the form is regenerated and there will be a new item added to the $address_afl and $address_bev-array. Is it possible to compress this code so the foreach-loop starts looping with the highest value (either $address_afl or$address_bev )

$address_afl = $form['field_afl_dienst_adressen']['und'];
$i = 0;
foreach($address_afl as $value) {
    if (is_array($value)) {
        $test = array_keys($value);
    if(is_array($test)) {
        foreach ($test as $z) {
            if (strpos($z, '#') === 0) continue;
            if (isset($form['field_afl_dienst_adressen']['und'][$i][$z])) {
                $form['field_afl_dienst_adressen']['und'][$i][$z]['#prefix'] = "<div class='address-publicatie-$z'>";
                $form['field_afl_dienst_adressen']['und'][$i][$z]['#suffix'] = "</div>";
            }
        }
    }
    }
    $i++;
}

$address_bev = $form['field_bevoegde_adressen']['und'];
$i = 0;
foreach($address_bev as $value) {
    if (is_array($value)) {
        $test = array_keys($value);
    if(is_array($test)) {
        foreach ($test as $z) {
            if (strpos($z, '#') === 0) continue;
            if (isset($form['field_afl_dienst_adressen']['und'][$i][$z])) {
                $form['field_bevoegde_adressen']['und'][$i][$z]['#prefix'] = "<div class='address-publicatie-$z'>";
                $form['field_bevoegde_adressen']['und'][$i][$z]['#suffix'] = "</div>";
            }
        }
    }
    }
    $i++;
}
\$\endgroup\$
3
  • 2
    \$\begingroup\$ Can you merge your two $address_ arrays into a single array? Maybe generalize this code into a function that takes the form name as a parameter, this way your loop is programed once and called twice. \$\endgroup\$ Dec 21, 2011 at 1:12
  • 1
    \$\begingroup\$ Your indentation is confusing, Your second if is should not be at the same level as the first. However, array_keys always returns an array so you don't need the second if and they should be deleted. \$\endgroup\$
    – Paul
    Dec 21, 2011 at 11:48
  • \$\begingroup\$ @Paul, I needed to check if they variable is an array for avoiding some NOTICE-messages... \$\endgroup\$
    – Michiel
    Dec 22, 2011 at 7:46

2 Answers 2

2
\$\begingroup\$

I don't quite exactly understand the logic, but you could extract out at least one method which removes lots of code duplication. I've inverted some conditions (which improves code readability) and placed some comments into the code too.

function processValue(&$form, $value, $i, &$form_sub) {
    if (!is_array($value)) {
        return;
    }

    // TODO: rename test to $keys or something more meaningful
    $test = array_keys($value);
    if (!is_array($test)) {
        // TODO: is it possible? according to the documentation 
        // array_keys() always returns array 
        return;
    }
    foreach ($test as $z) {
        if (strpos($z, '#') === 0) {
            continue;
        }
        if (!isset($form['field_afl_dienst_adressen']['und'][$i][$z])) {
            continue;
        }
        $form_sub[$i][$z]['#prefix'] = "<div class='address-publicatie-$z'>";
        $form_sub[$i][$z]['#suffix'] = "</div>";
    }
}


$address_afl = $form['field_afl_dienst_adressen']['und'];
$i = 0;
foreach($address_afl as $value) {
    processValue($form, $value, $i, $form['field_afl_dienst_adressen']['und']);
    $i++;
}

$address_bev = $form['field_bevoegde_adressen']['und'];
$i = 0;
foreach($address_bev as $value) {
    processValue($form, $value, $i, $form['field_bevoegde_adressen']);
    $i++;
}

A possible bug: both foreach has the following condition with the same $form index:

if (isset($form['field_afl_dienst_adressen']['und'][$i][$z])) ...

Maybe you want to change the second one to

if (isset($form['field_bevoegde_adressen']['und'][$i][$z])) ...

It would make possible some other refactorings (fewer parameters etc.), as Victor T. suggested.

\$\endgroup\$
0
1
\$\begingroup\$

You should be able to factor all those duplicates down into 2 function calls.

I think palacsint's observation is correct that $test is always an array here. In fact, I'm not sure I see why you don't just use the keys in $value directly. It doesn't appear the keys get changed in the loop.

if (is_array($value)) {
    $test = array_keys($value);
if(is_array($test)) {
    foreach ($test as $z) {

This refactor is similar to palacsint's suggestion but taken further.

function name_needed(&$addr_src)
{
    $i = -1;
    foreach($addr_src as $next) 
    {
        ++$i;
        if (!is_array($next)) continue;

        foreach($next as $z => $_) 
        {
            if (strpos($z, '#') === 0 || !isset($addr_src[$i][$z])) continue;

            $addr_src[$i][$z]['#prefix'] = "<div class='address-publicatie-$z'>";
            $addr_src[$i][$z]['#suffix'] = "</div>";
        }
    }
}

name_needed($form['field_afl_adressen']['und']);
name_needed($form['field_bevoegde_adressen']['und']);
\$\endgroup\$
1
  • \$\begingroup\$ I've also thought of moving a little bit further, but in both foreach the if condition uses the same key. Check my update for the details. \$\endgroup\$
    – palacsint
    Dec 22, 2011 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.