function field_view_value

You are here

7 field.module field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL)

Returns a renderable array for a single field value.

Parameters

$entity_type: The type of $entity; e.g., 'node' or 'user'.

$entity: The entity containing the field to display. Must at least contain the id key and the field data to display.

$field_name: The name of the field to display.

$item: The field value to display, as found in $entity->field_name[$langcode][$delta].

$display: Can be either the name of a view mode, or an array of display settings. See field_view_field() for more information.

$langcode: (Optional) The language of the value in $item. If not provided, the current language will be assumed.

Return value

A renderable array for the field value.

Related topics

1 call to field_view_value()
FieldDisplayAPITestCase::testFieldViewValue in modules/field/tests/field.test
Test the field_view_value() function.

File

modules/field/field.module, line 792
Attach custom data fields to Drupal entities.

Code

function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL) {
  $output = array();

  if ($field = field_info_field($field_name)) {
    // Determine the langcode that will be used by language fallback.
    $langcode = field_language($entity_type, $entity, $field_name, $langcode);

    // Push the item as the single value for the field, and defer to
    // field_view_field() to build the render array for the whole field.
    $clone = clone $entity;
    $clone->{$field_name}[$langcode] = array($item);
    $elements = field_view_field($entity_type, $clone, $field_name, $display, $langcode);

    // Extract the part of the render array we need.
    $output = isset($elements[0]) ? $elements[0] : array();
    if (isset($elements['#access'])) {
      $output['#access'] = $elements['#access'];
    }
  }

  return $output;
}

Comments

I struggled with this for a while, presuming (even having read this documentation) that $item would be the delta of the field value you wanted to render... it's not. It's the actual field item itself as found in $entity->field_name[$langcode][$delta]. You should access this via field_get_items() for proper localisation. For example:

$node = node_load($nid);
$image = field_get_items('node', $node, 'field_image');
$output = field_view_value('node', $node, 'field_image', $image[0]);

Where $image[0] refers to the value you want.

The reason behind that is field_get_items returns the array of items found, even if its just one.
The 0 refers the item's delta, or array position in the list.
So, when you run field_view_value, you should be passing a specific item[delta] to it.

<?php
$node
= node_load($nid);
$image = field_get_items('node', $node, 'field_NAME');
foreach (
$image as $key=>$value) {
$output = field_view_value('node', $node, 'field_NAME', $image[$key], array(
 
'type' => 'image',
 
'settings' => array(
   
'image_style' => 'thumbnail', //place your image style here
   
'image_link' => 'content',
  ),
));
print
render($output);
}
?>

Hope it helps,

Guus

It looks like your foreach() loop will overwrite the $output array on each iteration. If anyone is running into problems with this example, try replacing the first $output with $output[], or work in an array_push(), if that suits you.

guus, thanks for the example. it came in handy for my current project.

Thanks for the help, I am now using a wrapper method like this for a better api in some preprocess functions for a theme. You can easily add a loop if you need multiple values.

<?php
function mymodule_render_field ( $entity_type_id , $entity_object , $field_id , $display_opts = null ) {
    if (
$display_opts == null ) $display_opts = array();
   
$field = field_get_items ( $entity_type_id , $entity_object , $field_id );
   
$output = field_view_value ( $entity_type_id , $entity_object , $field_id , $field[ 0 ], $display_opts );

    return

drupal_render ( $output );
}

//example for imagefield with custom imagestyle
function mymodule_render_imagefield_with_style ( $entity_type_id , $entity_object , $field_id , $image_style_id ) {
   
$opts = array (
           
'type' => 'image' ,
           
'settings' => array (
               
'image_style' => $image_style_id ,
               
'image_link' => 'content' ,
            ) ,
        );

    return

mymodule_render_field ( $entity_type_id , $entity_object , $field_id, $opts );
}
?>

Helpful last two comments.... I have been trying to add some conditional arguments in Rules with php, but I needed to get the CCK fields and their respective tokens. It was a bit of a nightmare! I have got over the confusion that token and entity have with their underscore/dash problem. I did find though that ['#markup'] did work, since printing out in a foreach got me the result, but also printed out the "1" from the [#access] in the array.

This is what each array looks like using print_r($output); I have been testing with just 2 of my 3 MAC Address fields.

Array
(
[#markup] => 00:11:22:33:44:BB
[#access] => 1
)

Array
(
[#markup] => 22:22:22:BB:CC:D1
[#access] => 1
)

Array
(
[#markup] =>
[#access] => 1
)

Basically I have a content type called network_connection that a user submits their MAC address of their computer/device to get access to our network, the fields are firstname, lastname, email, network, and after alot of heartache I just went with three text fields with one value for a limited amount of MAC addresses. I had problems at first understanding how to extract a textarea field or an unlimited number of instances of a single textfield. I might have a look at this again since I have a better understanding (I hope) of how tokens are used.

Back to business, I needed to create a rule, that fired on when a new content was created of type network_connection and would then send an email to the Computer IT Dept. But the email had to be formatted in such a way that they could just copy/paste the respective code to execute a shell script, that would contain the name, email and mac address. I needed to check if there was 1,2 or 3 MAC addresses to create each line of shell script code.

I haven't even got to that part yet, but I will leave the code I have that finally allowed me to move a CCK textfield token into a php variable.

This is the message part of the email rule:

As you can see below printing out the entity tokens is no major problem, but they are different ( --- instead of ___) from the Token tokens used to grab the value and use as a php variable. (there is a massive discussion somewhere about wether Tokens or Entity should be using dashes or underscores)

The following user is requesting access to our network

Name     : [node:field_first_name] [node:field_last_name]
Email     : [node:field-email]
Network : [node:field_network]
MAC adress(es) :
[node:field-mac-address-1]
[node:field-mac-address-2]
[node:field-mac-address-3]

Execute the following command(s) on ctiosj:/CTIO/DHCP to check if the user data
already exists in our database:

HERE IS WHERE I WANT A LINE FOR EACH MAC ADDRESS TO BE COPY/PASTED BY THE IT DEPT. I NEEDED to be able to play with the MAC Address, to be able to check if the token was empty or not and to also check the format, though this can be down by a field validation module as well. I also will want to grab the first part of the email address to create an id for each script. john.smith@gmail.com = john.smith0 for the first mac address

---php code here
$node = node_load($node->nid);

$field = field_get_items('node', $node, 'field_mac_address_1');
$output = field_view_value('node', $node, 'field_mac_address_1', $field[0]);
echo "\nVALUE1\n";
print $output['#markup'];
$out1 = $output['#markup'];

$field = field_get_items('node', $node, 'field_mac_address_2');
$output = field_view_value('node', $node, 'field_mac_address_2', $field[0]);
echo "\nVALUE2\n";
print $output['#markup'];
$out2 = $output['#markup'];

$field = field_get_items('node', $node, 'field_mac_address_3');
$output = field_view_value('node', $node, 'field_mac_address_3', $field[0]);
echo "\nVALUE3\n";
print $output['#markup'];
$out3 = $output['#markup'];

print "\nVALUES IN VARIABLES\n";
if(!empty($out1)){
print $out1;
}
else
{
print "EMPTY";
}
print "\n";
if(!empty($out2)){
print $out2;
}
else
{
print "EMPTY";
}
print "\n";
if(!empty($out3)){
print $out3;
}
else
{
print "EMPTY";
}
print "\n";

---php code ends here

I tested this out and sent my 500th email and got the following after creating a content type called network connection, that only had the first and second MAC address filled in and not the third.

VALUE1
00:11:22:33:44:BB
VALUE2
22:22:22:BB:CC:D1
VALUE3

VALUE IN VARIABLE
00:11:22:33:44:BB
22:22:22:BB:CC:D1
EMPTY

There is probably a nicer way of doing this..but anyhow...

The following user is requesting access to our network

Name     : [node:field_first_name] [node:field_last_name]
Email     : [node:field-email]
Network : [node:field_network]
MAC adress(es) :
[node:field-mac-address-1]
[node:field-mac-address-2]
[node:field-mac-address-3]

Execute the following command(s) on ctiosj:/CTIO/DHCP to check if the user data
already exists in our database:

---php start
$node = node_load($node->nid);

$field = field_get_items('node', $node, 'field_mac_address_1');
$output = field_view_value('node', $node, 'field_mac_address_1', $field[0]);
echo "\nVALUE1\n";
print $output['#markup'];
$out1 = $output['#markup'];

$field = field_get_items('node', $node, 'field_mac_address_2');
$output = field_view_value('node', $node, 'field_mac_address_2', $field[0]);
echo "\nVALUE2\n";
print $output['#markup'];
$out2 = $output['#markup'];

$field = field_get_items('node', $node, 'field_mac_address_3');
$output = field_view_value('node', $node, 'field_mac_address_3', $field[0]);
echo "\nVALUE3\n";
print $output['#markup'];
$out3 = $output['#markup'];

$field = field_get_items('node', $node, 'field_email');
$output = field_view_value('node', $node, 'field_email', $field[0]);
echo "\nVALUE4 EMAIL\n";
print $output['#markup'];
$out4 = $output['#markup'];
$email = explode(">",$out4);
$email = $email[1];
$email_user = explode("@",$email);
$email_user = $email_user[0];

print "\nEMAIL AND EMAIL USER\n";
//print $out4;
//print "\n";
//print $email;
//print "\n";
print $email_user;
print "\n";

print "\nVALUE IN VARIABLE\n";
if(!empty($out1)){
print $out1;
}
else
{
print "EMPTY";
}
print "\n";
if(!empty($out2)){
print $out2;
}
else
{
print "EMPTY";
}
print "\n";
if(!empty($out3)){
print $out3;
}
else
{
print "EMPTY";
}
print "\n";

----php end

The following user is requesting access to our network

Name : David Walker
Email : dw@noao.edu
Network : CTIO
MAC adress(es) :
00:11:22:33:44:BB
22:22:22:BB:CC:D1
[node:field-mac-address-3]

Execute the following command(s) on ctiosj:/CTIO/DHCP to check if the user data
already exists in our database:

VALUE1
00:11:22:33:44:BB
VALUE2
22:22:22:BB:CC:D1
VALUE3

VALUE4 EMAIL
dw@noao.edu
EMAIL AND EMAIL USER
dwalker

VALUE IN VARIABLE
00:11:22:33:44:BB
22:22:22:BB:CC:D1
EMPTY

Hope this helps someone...

$view_field = field_view_value('MY_ENTITY_TYPE', $entity, 'field_NAME', $entity->field_NAME['und'][0], array());
$view = render($view_field);

The direct reference is still problematic for a host of reasons (und is language-specific, your data wasn't sanitized, it only gave you a single value, and you lose some delicious theme data that is packaged in with the field).

<?php
  $fields
= field_get_items('MY_ENTITY_TYPE', $entity, 'field_name');
 
$view_field = field_view_value('MY_ENTITY_TYPE', $fields, 'field_name', $better[0], array());
 
$view = render($view_field);
?>

oops, typo

<?php
  $better
= field_get_items('MY_ENTITY_TYPE', $entity, 'field_name');
 
$view_field = field_view_value('MY_ENTITY_TYPE', $entity, 'field_name', $better[0], array());
 
$view = render($view_field);
?>

output the this code:

<?php

$node

= node_load($nid);
$field = field_get_items('node', $node, 'field_availability_product_type');
$available = field_view_value('node', $node, 'field_availability_product_type', $field[0]);
     if(
$available == 1){$class = 'green-price';}else{$class = 'gray-price';} print '<div class="basic-cart-price '.$class.' price-node"><strong>'.render($node->price['und'][0]['value']).'&nbsp;<span class="currency-price">грн.<span></strong></div>';
?>

in the file views-view-field--my-field.tpl.php
The output is a error.
Thank for any help

Notice: Undefined variable: nid в функции include() (строка 4 в файле /home/sortosad/sortosad.com.ua/www/sites/all/themes/sorto/views-view-field--views-block-and-pages-and-etc--page-with-page-title-2--price.tpl.php).
EntityMalformedException: Отсутствует связующее свойство у сущности типа node. в функции entity_extract_ids() (строка 7633 в файле /home/sortosad/sortosad.com.ua/www/includes/common.inc).

I wanted fill out the meta keywords tag and used field_view_value and field_get_items functions to get filed_tags tag content.

//getting keywords
$tags = field_get_items('node', $node, 'field_tags');
$keywo = array();
foreach($tags as $item=>$value){
$output = field_view_value('node', $node, 'field_tags', $tags[$item]);
$keywo[] = strip_tags(render($output));
}
$keywords = implode(",", $keywo);

$markup .= ''; -> just place it to the head section

Hope it helps someone or/and someone give an advice in case I´m doing something wrong.

$markup = '<meta name="keywords" content="'.$keywords.'"/>';

I tried to use this function to display an image field which could be empty. My expectation was that it would show the default if there was no value. This is not the case. After a lot of debugging it seems that it just isn't supported.

image_field_prepare_view() expects the array of items to be empty, but field_view_value() sets it to array($item), so it doesn't matter what you pass as $item, whether FALSE or an empty array, $items will end up being array[0] => $item, so it is not empty since the zeroth element is set.

If you want to output just the image without the label and wrapping elements but with the possibility of using the default, just use field_view_field() and extract the parts you want or pass $display to it and specify that you don't want the label.

Also note that field_get_default_value() doesn't work for image fields, or at least it doesn't if you set the default on the whole field rather than for the instance.

I was trying to use field_view_value() within a custom display suite field renderer callback for an entity reference but I was getting no result. This was not the case for other field types such as date fields.

If I added the entity reference field directly to the display then I found that I did get output from my custom field, but then, of course, the field was being displayed twice.

By running the code in a debugger I found that the cause of my problem was that hook_prepare_view() functions were not being invoked in field_view_field() for the entity reference field because $entity->_field_view_prepared was set TRUE. Setting it FALSE before calling field_view_value() and back to TRUE afterwards fixed the problem.

<?php
  $data
= field_get_items('node', $field['entity'], 'field_location');
 
$field['entity']->_field_view_prepared = FALSE;
  foreach (
$data as $key => $item) {
   
$value = field_view_value('node', $field['entity'], 'field_location', $item, array(
     
'label'=>'hidden',
     
'type' => 'entityreference_label',
     
'settings'=>array('link' => TRUE),
    ));
   
$locations[] = render($value);
  }
 
$field['entity']->_field_view_prepared = TRUE;
 
$output .= implode(', ', $locations);
?>

It seems that $entity->_field_view_prepared is set true after all the 'normal' fields that have been added to the display have prepared. Not sure if this is a bug or not. Possibly checking the actual preparedness of the field in field_view_field() rather than relying on the $entity->_field_view_prepared value whould be an improvement.

I've seen this particular pattern multiple times in Drupal code. From the function definition above:

$clone = clone $entity;
$clone->{$field_name}[$langcode] = array($item);
$elements = field_view_field($entity_type, $clone, $field_name, $display, $langcode);

I'm pretty sure this doesn't do what it was "supposed" to do. PHP clone creates a shallow clone. Setting the values of a (not cloned) field on that clone also affects the original $entity AFAIK.

Anybody want to confirm or deny that?