4

I'm now using Advanced Custom Fields Plugin in wordpress.

And now I defined some Choices, and they have Choices set as below:

Field Name: time_availability

Field Type: Select

low : Once or twice
high : Several times

So, I want to enumerate these settings in the page code, like rendering:

<ul>
  <li><input type="radio" name="low" /> Once or twice</li>
  <li><input type="radio" name="high" /> Several times</li>
</ul>

How can I get the choices?


Update:

Seemed if calling the get_field_object($field_name) may got the entire field settings, including the choices.

But when I call the function with the field name, the below is returned:

array(18) {
  ["key"]=>
  string(33) "field_time_availability"
  ["label"]=>
  string(0) ""
  ["name"]=>
  string(27) "time_availability"
  ["_name"]=>
  string(27) "time_availability"
  ["type"]=>
  string(4) "text"
  ["order_no"]=>
  int(1)
  ["instructions"]=>
  string(0) ""
  ["required"]=>
  int(0)
  ["id"]=>
  string(37) "acf-field-time_availability"
  ["class"]=>
  string(4) "text"
  ["conditional_logic"]=>
  array(3) {
    ["status"]=>
    int(0)
    ["allorany"]=>
    string(3) "all"
    ["rules"]=>
    int(0)
  }
  ["default_value"]=>
  string(0) ""
  ["formatting"]=>
  string(4) "html"
  ["maxlength"]=>
  string(0) ""
  ["placeholder"]=>
  string(0) ""
  ["prepend"]=>
  string(0) ""
  ["append"]=>
  string(0) ""
  ["value"]=>
  bool(false)
}

Not the expecting result.

While if I call that function with the raw field name:

get_field_object('field_55df081515e81');

It goes right!

What's the matter? What's the difference and how can I get it right using the field_name?

Community
  • 1
  • 1
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189

3 Answers3

7

Finally, after all, I found a reliable solution to get around this question:

You can first see the api_acf_load_field function in the source code:

add_filter('acf/load_field', 'api_acf_load_field', 1, 2);
function api_acf_load_field( $field, $field_key )
{
    // validate
    if( !empty($GLOBALS['acf_register_field_group']) )
    {
        foreach( $GLOBALS['acf_register_field_group'] as $acf )
        {
            if( !empty($acf['fields']) )
            {
                foreach( $acf['fields'] as $f )
                {
                    var_dump($f['key']);
                    if( $f['key'] == $field_key )
                    {
                        $field = $f;
                        break;
                    }
                }
            }
        }
    }

    return $field;
}

We can just iterate through all registered fields to pick the correct one.

But the $GLOBALS['acf_register_field_group'] is there only when we call register_field_group explicitly (Case 2 below). Or in the normal case (Case 1 below), we can't got it in this way.

So see the different cases:


Case 1: When the field groups are defined in the admin panel (in the database):

function get_field_choices($field_name, $multi=false) {
    $results = array();
    foreach (get_posts(array('post_type' => 'acf', 'posts_per_page' => -1)) as $acf) {
        $meta = get_post_meta($acf->ID);
        foreach($meta as $key => $field) {
            if(substr($key, 0, 6) == 'field_') {
                $field = unserialize($field[0]);
                if($field['name'] == $field_name && isset($field['choices'])) {
                    if(!$multi) return $field['choices'];
                    else $results []= $field;
                }
            }
        }
    }
    return $results;
}

In this case, the field groups are store as post which post type is acf, and the field information are stored as post_meta of that field group.

So, we grab all the fields registered (from database), and pick the correct one(s).


Case 2: When register_field_group explicitly, like using the export php scripts in the functions.php:

function get_field_choices($field_name, $multi=false) {
    $results = array();    $results = array();
    foreach($GLOBALS['acf_register_field_group'] as $acf) {
        foreach($acf['fields'] as $field) {
            if(substr($field['key'], 0, 6) == 'field_') {
                if($field['name'] == $field_name && isset($field['choices'])) {
                    if(!$multi) return $field['choices'];
                    else $results []= $field;
                }
            }

        }
    }
    return $results;
}

Then we finally got a always work function:

function get_field_choices($field_name, $multi=false) {
    $results = array();
    foreach($GLOBALS['acf_register_field_group'] as $acf) {
        foreach($acf['fields'] as $field) {
            if(substr($field['key'], 0, 6) == 'field_') {
                if($field['name'] == $field_name && isset($field['choices'])) {
                    if(!$multi) return $field['choices'];
                    else $results []= $field;
                }
            }

        }
    }
    foreach (get_posts(array('post_type' => 'acf', 'posts_per_page' => -1)) as $acf) {
        $meta = get_post_meta($acf->ID);
        foreach($meta as $key => $field) {
            if(substr($key, 0, 6) == 'field_') {
                $field = unserialize($field[0]);
                if($field['name'] == $field_name && isset($field['choices'])) {
                    if(!$multi) return $field['choices'];
                    else $results []= $field;
                }
            }
        }
    }
    return $results;
}
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
7

Not sure why get_field_object always return false, and the answer I voted before not working any more, so I have to work out a new solution, I guess maybe ACF updated how data store, custom field now store in wp_post table, post type is acf-field.

function get_field_choices($field_name, $multi = false) {
  $results = array();
  foreach (get_posts(array('post_type' => 'acf-field', 'posts_per_page' => -1)) as $acf) {
    if ($acf->post_excerpt === $field_name) {
      $field = unserialize($acf->post_content);
      if(isset($field['choices'])) {
        if(!$multi) return $field['choices'];
        else $results []= $field;
      }
    }
  }
  return $results;
}
ahgood
  • 1,847
  • 20
  • 19
6

On ACFs site they state:

"The API will return the selected value. If you select the multiple option for this field, the API will return an array of values."

So try the following:

// get the selected value
$value = get_field('time_availability');
?>

<ul>
  <li><input type="radio" name="low" <?php echo ($value == 'low'?'checked="checked"':''); ?>/> Once or twice</li>
  <li><input type="radio" name="high" <?php echo ($value == 'high'?'checked="checked"':''); ?>/> Several times</li>
</ul>

If you have enabled the selection of multiple values, you should use checkboxes instead of radios.


To access the available choices, you have to get the field object.

// choose the field
$field_name = 'time_availability';
$field = get_field_object($field_name);

if( $field )
{
    // build the form
    echo '<select name="' . $field['key'] . '">';
        foreach( $field['choices'] as $k => $v )
        {
            echo '<option value="' . $k . '">' . $v . '</option>';
        }
    echo '</select>';
}

To get the field object from a user, use this notation:

$user_id = 2;  // the id of the user
$field_name = 'your_field';  // the name of the field
get_field_object($field_name, 'user_.'.$user_id)
xphan
  • 1,038
  • 6
  • 8
  • No, what I want is to loop through all the choices. – Alfred Huang Aug 27 '15 at 13:27
  • 2
    So update your question and don't downvote. See my updated question. – xphan Aug 27 '15 at 13:32
  • 1
    Well, I found the field alias is `field_55df081515e81`, while the field name is `time_availability`. and I got the choices from the alias `field_55df081515e81`, but fail to fetch from the name `time_availability`, why? – Alfred Huang Aug 27 '15 at 13:38
  • 2
    **get_field_object** works on field_name or field_key (which is unique). If you execute `get_field_object` with `field_name` and no corresponding page id, it tries to fetch the meta value from the current page. So if you try to get the field values on a **different** site, you would need to use either the field key or the field name in combination with the post id where you have saved your field. – xphan Aug 27 '15 at 13:41
  • My field is attached on the user, does this matter? I tried with no luck when I pass the user as the second parameter. – Alfred Huang Aug 27 '15 at 13:49
  • I tried on a post field, the method is ok, and the problem now is: how to get choices on user field? – Alfred Huang Aug 27 '15 at 13:53
  • 1
    Please try it like this: `get_field_object($field_name, 'user_.'.$user_id)` – xphan Aug 27 '15 at 13:55
  • You could also try to get all the fields and then filter: `$user_meta = get_field_objects('user_' . $userID);` – xphan Aug 27 '15 at 14:02
  • Finally got the point: I update the field group, but that field meta is not added on the specified user, so after I updated the user (id=37) to ensure the field, the `get_field_object('time_availability', 'user_37')` worked as expected! – Alfred Huang Aug 27 '15 at 14:13