0

I am trying to produce a result that requires PHP code to evaluate whether a Drupal 8 node field is a "x", an "f", a "m", a "h", or an "l".

Thanks to some help on an earlier question, I've accomplished my task (to replace the value with a useful icon) when the value is binary: if it exists, show this. If it's empty, show nothing. I've done this via CSS.

Now I'd like to extract the actual value of the node field, and display different icons based on its value.

I am not planning to do this via a function, but rather by code on the node itself. Is there some syntax I can use within the php that will extract this? So that I can have the equivalent of:

$price = $node[field][value];

then I'd do:

if ($price == "m") { // use icon X }
else if ($price == "h") { // use icon Y };

Thank you for any and all help/suggestions!

4
  • You can’t do php in a twig file. The proper way to do this is set the icon value from a preprocess_node hook in the .theme file.
    – Kevin
    Commented Jan 5, 2019 at 0:12
  • Thank you, Kevin. I am fairly new...was hoping to do this in the node Content itself using php. Is that just silly? Impossible? Alternately, is there a good place to start learning what a preprocess_hook is and how to use it? My other alternative would be to split the field into its various values and just do it binarily -- "if exists, rewrite the background-image" otherwise display none. If that's easier in my case, I could opt for that. It would suck to add 6 fields into the node but I don't have thousands of nodes...30 or 40 or so. If that's the easiest, I'll do it that way. Commented Jan 5, 2019 at 0:27
  • Keeping php code in the database is bad practice and never advised. This is pretty easy with one list field and a switch statement
    – Kevin
    Commented Jan 5, 2019 at 0:56
  • @Kevin, thanks for sticking with me on this. Is there a way to implement this that's relatively newbie friendly? I've heard of hooks as a term but have never used them. Where's the best place to start? Also, in your comment, the "pretty easy with..." can you give me the syntax for how this would be done? Are you talking about something within a .theme file? Or (inadvisable as it may be) doing it on the page itself. If so, I think the "list field" part might be what I'm missing -- how do I do that part? Again, thank you in advance for any additional info/help! Commented Jan 5, 2019 at 1:08

2 Answers 2

2

This only requires one field. It sounds like it is a list (text) field to me.

This should be done as a new variable to the node template by way of using hook_preprocess_node in your MYTHEME.theme (replace any instance of MYTHEME with your actual themes name, i.e. bartik) file. Here is an example:

function mytheme_preprocess_node(&$variables) {
  $type = $variables['node']->getType();

  if ($type == 'NODE_TYPE') {
    $price = $variables['node']->get('field_name')->value;

    switch ($price) {
      case "m":
        $variables['custom_icon'] = 'icon1';
        break;

      case "h":
        $variables['custom_icon'] = 'icon2';
        break;

      case "x":
        $variables['custom_icon'] = 'icon3';
        break;

      case "f":
        $variables['custom_icon'] = 'icon4';
        break;

      case "l":
        $variables['custom_icon'] = 'icon5';
        break;

      default:
        $variables['custom_icon'] = FALSE;
        break;
    }
  }
}

Then, create a node--NODE-TYPE.html.twig file, where NODE-TYPE is the machine name (bundle) of the node in question (ex. article, page, product).

In this file, you now have a new variable available to use, which would be output with:

{% if custom_icon %}
  {{ custom_icon }}
{% endif %}

If no value, or value does not match whats expected, the switch statement will set the variable to FALSE so you can check in Twig if you should output it or not.

17
  • Thank you very much, @Kevin! I was writing my comment simultaneously. I will try to implement this and might get back with questions if I can't figure it out! Again, thank you! Commented Jan 5, 2019 at 1:10
  • And just curious: this above code will NOT work as php on the page, right? It's only usable through implementing in the .theme of my theme? Commented Jan 5, 2019 at 1:11
  • You cannot put PHP in Twig template files, nothing will happen. As you can see from the code, the variable will only be created for the node type you are targeting. hook_preprocess_node is the standard way of manipulating or creating new variables for the node template. See: api.drupal.org/api/drupal/core%21modules%21node%21node.module/…
    – Kevin
    Commented Jan 5, 2019 at 1:12
  • This is exactly how I would solve the issue. I tried looking for tutorials, but most are outdated (and linking to random blogs is discouraged here, because we can't guarantee the link would work in the future). I would recommend picking up one of the Drupal 8 Theming books or checking out drupalize.me on theming.
    – Kevin
    Commented Jan 5, 2019 at 1:22
  • thank you very much. I will take a stab at this and if I get it working I'll be sure to circle back and give this a bright green checkmark. If not I'll likely have a few more questions. I really appreciate your adding the additional explanations (for example, "replace with Bartik..."). While I would like to of course learn the underlying concepts of theming, my hope is to get this up and working as soon as possible. But I did try (before posting) to find good D8 tutorials on something like this and it seemed hard. I'll check the book too. Thanks again! Commented Jan 5, 2019 at 4:09
0

To display different icons depending on some field values you can simply make use of template_preprocess_field. Get the field value and add a CSS class accordingly. And the rest is just CSS.

/**
 * Implements template_preprocess_field__FIELD_NAME().
 *
 * @param array $variables
 */
function MYTHEME_preprocess_field__field_price(&$variables) {

  // Get the field value.
  $value = $variables['element'][0]['#markup'];

  // Do whatever else you need to do with $value.
  // ksm($value); ...
  // ...

  // And then append $value as a new CSS class to the field wrapper.
  $variables['attributes']['class'][] = $value;
}

Install the Devel sub-module Kint to let ksm() pretty-print the value for debugging.


Note, depending on the field type you used, the value may be hidden in $variables['element'][0]['#text']; or $variables['element'][0]['#value']; or something else. Simply check what's inside $variables['element'] via ksm($variables['element']), first.

2
  • This is another way to do it, but since I wasn’t sure where this will be output I listed the node preprocess. It should be noted that if this icon displays outside of the context of the field output, that’s the way to go. If the icon shows alongside the price within the fields own markup, then this is more fitting.
    – Kevin
    Commented Jan 5, 2019 at 13:49
  • @Kevin – Absolutely. +1 for your answer. I avoid editing templates whenever possible. Even on the node level, if the icon should be displayed in the context of another field (maybe price field) of the same node, I'd use prep_field__price, load the parent object, get the icon field value, and append that as class to the price field.
    – leymannx
    Commented Jan 5, 2019 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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