Home Forums Backend Issues (wp-admin) Custom field types: saving and loading values


Custom field types: saving and loading values

  • I’m making a new language selector field type which creates a <select> field from all languages present in a given WPML instance. It’s based on this:

    I was able to follow the instructions fairly well: created the field type, populated it with all the language data from WPML, and made the <select> field appear when editing posts. But I can’t save the selected value to the database.

    There’s probably something very basic missing here, but I can’t figure out what it is. Below is what I wrote in the files which in the starter kit is called acf-FIELD_NAME-v5.php. (The part about constructing the array of languages, it works fine. Please just assume that this returns a run-of-the-mill PHP array.)

    if( ! defined( 'ABSPATH' ) ) exit;
    if( !class_exists('acf_field_wpml_languages') ) :
    class acf_field_wpml_languages extends acf_field {
    	function __construct( $settings ) {
    		$this->name = 'wpml_languages';
    		$this->label = __('WPML Languages', 'acf-wpml_languages');
    		$this->category = 'choice';
    		$this->settings = $settings;
    	function render_field( $field ) {
    		global $wpdb;
    		function get_all_langs_names( $lang, $wpdb ) {
    			$lang_data = array();
    			$languages = $wpdb -> get_results( 
    				$wpdb -> prepare( "
    					SELECT code, english_name, active, tag, name 
    					FROM {$wpdb -> prefix}icl_languages lang 
    					INNER JOIN {$wpdb -> prefix}icl_languages_translations trans 
    					ON lang.code = trans.language_code 
    					AND trans.display_language_code=%s", 
    				$lang )
    			foreach( $languages as $l ) {
    				$lang_data[$l -> code] = array(
    					'english_name' => $l -> english_name,
    					'active' => $l -> active,
    					'tag' => $l -> tag,
    					'name' => $l -> name,
    			return $lang_data;
    		// get language tag of current site locale...
    		$code = ICL_LANGUAGE_CODE;
    		$lang_tag = $wpdb -> get_var("
    			SELECT tag 
    			FROM {$wpdb -> prefix}icl_languages 
    			WHERE code='{$code}'"
    		// ... and then get language names associated with that tag
    		$languages = get_all_langs_names( $lang_tag, $wpdb );
    		// sort language array alphabetically, or however current language orders words
    		function sort_languages( $a, $b ) {
    			return strcmp( $a['name'], $b['name'] );
    		usort( $languages, 'sort_languages' );
    			foreach ($languages as $language) {
    				?><option value=<?php echo '"' . $language['tag'] . '"'; ?>><?php echo $language['name']; ?></option><?php
    new acf_field_wpml_languages( $this->settings );
  • did you rename the file acf-FIELD_NAME-v5.php to acf-wpml_languages-v5.php ?

  • I did. Was just referring to the original file name so people could identify it.

  • Your select field has no attributes <select>, like the name, id, other important information. Without a proper field name ACF can’t save your field value. You should take a look at some of the build in ACF fields to get examples of what you should use here.

  • It would be something that simple, wouldn’t it! Below is what I ended up using:

    $attrs = array(
        'id'      => $field['id'],
        'name'    => $field['name'],
    <select <?php echo implode( ' ', array_map(function($val, $key) { return sprintf( '%1$s="%2$s"', $key, esc_attr($val) ); }, $attrs, array_keys( $attrs ))); ?>>
        foreach ($languages as $language) {
            ?><option value=<?php echo '"' . $language['tag'] . '"'; if($language['tag'] == $field['value']): ?> selected="selected"<?php endif; ?>><?php echo $language['name']; ?></option><?php

    Credit to

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.