- Issue created by @wxman
- 🇬🇧United Kingdom joachim
📌 Allow adding computed bundle fields in Views Fixed would allow bundle fields to be output. Base fields apparently already can be output.
However, currently no kind of computed field is picked up automatically by Views data.
I'm pondering how best to fix this.
Probably a core patch for base fields & module code for bundle fields.
- 🇬🇧United Kingdom joachim
I've made a core patch that declares base computed fields to views: 📌 Automatically declare computed base fields to Views Needs work .
- 🇺🇸United States wxman
joachim - I checked on #3 and am I missing seeing the patch? I don't have a lot of experience with core patches so maybe I'm just missing it?
- 🇬🇧United Kingdom joachim
I can report that computed fields added in the UI work fine with the patch from 📌 Allow adding computed bundle fields in Views Fixed -- though you need to declare them in code as well.
- 🇺🇸United States wxman
@joachim I have set up two test sites, one running D9.x and the other 10.x. The 9.x site I installed Version: 4.0.0-alpha3 of Computed Field, and it's working as designed, except for not being accessible in Views.
I have applied patch: https://git.drupalcode.org/project/drupal/-/merge_requests/2511.patch.
Above you say "-- though you need to declare them in code as well". Where do I declare the field in code? If I figure that out is that going to make it able to be used in Views? - 🇬🇧United Kingdom joachim
> Where do I declare the field in code?
https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php...
- 🇺🇸United States wxman
Do I add that to a new custom module, or to the custom module I made at /web/modules/custom/buy_amazon?
/web/modules/custom/buy_amazon/src/Plugin/ComputedField/Computedbuyamazon.php - 🇬🇧United Kingdom joachim
It makes sense to put it in the same module as your computed field plugin, as both are required to make the field work.
- 🇺🇸United States wxman
I guess I'm going to have to wait till it gets fixed in Views. No matter what I try it still will not show in my View.
- 🇦🇹Austria maxilein
I could not wrap my head around building a plugin. Since I needed a solution a went back to a more traditional approach:
1. create a core field
2. create code in mmodule_ ...
mymodule_node_presave($entity) { switch ($entity->bundle()) { // Here you modify only your day content type case 'entity_machine_name': if (!empty($entity->field_name->value)) { ... do some custom calculation stuff
3. Make the field readonly in the form edit using Readonly Field Widget →
It is not as elegant as computed_field, but to me it was less time consuming, because I just did not comprehend the requirements and options for a plugin.
- 🇬🇧United Kingdom joachim
> I just did not comprehend the requirements and options for a plugin.
Could you explain more about the problem in a separate issue please? The plugins for computed fields are really pretty simply as plugins go, and there are examples in the module to draw from.
- 🇦🇹Austria maxilein
That is not a problem only of this module. It is a fundamental problem of Drupal. That's why I try to help with explanations wherever I can.
It may be pretty obvious for someone who programs Drupal for years. I could not get a proper article that leads me step by step. The explanations are extremely short.I try to avoid customizations, for easier upgrades. I do not want to read the source code in order to understand the basic purpose or principle of a module. At least not until I decided that a module could fit my purpose.
In this case: if I have to do coding anyway, why shouldn't I do in a way that seems less complex?
No offense! - 🇬🇧United Kingdom joachim
I really REALLY suggest you all use Module Builder. It will generate the plugin class for you.
- 🇦🇹Austria maxilein
joachim, please don't get me wrong. You are outstanding in all your efforts! And documenting much better than most of Drupal developers!
- 🇬🇧United Kingdom joachim
Thanks! :)
I've started some docs - https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib... →
Incomplete, but will add to them when I have time.
- 🇺🇸United States wxman
Here is the module I made to go with my "computed_buy_amazon" computer field. It's at: buy_amazon\src\Plugin\ComputedField\ComputedField.php
namespace Drupal\buy_amazon\Plugin\ComputedField; use Drupal\Component\Datetime\TimeInterface; use Drupal\computed_field\Field\ComputedFieldDefinitionWithValuePluginInterface; use Drupal\computed_field\Plugin\ComputedField\ComputedFieldBase; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * @ComputedField( * id = "buy_amazon_computedbuyamazon", * label = @Translation("Computed buy Amazon"), * field_type = "text", * attach = { * "scope" = "base", * "field_name" = "buy_amazon_computedbuyamazon", * "entity_types" = { * "entity_test" = {}, * }, * } * ) */ class Computedbuyamazon extends ComputedFieldBase { /** * {@inheritdoc} */ public function ComputeValue(EntityInterface $host_entity, ComputedFieldDefinitionWithValuePluginInterface $computed_field_definition): array { if(!empty($host_entity->field_isbn10->value)) { $ISBN = $host_entity->field_isbn10->value; }else{ if(!empty($host_entity->field_amazon_asin->value)) { $ISBN = $host_entity->field_amazon_asin->value; }else{ $ISBN = ''; } } if(!empty($ISBN)) { $value = '<a href="http://www.amazon.com/gp/product/'.$ISBN.'" alt="" style="border:none !important; margin:0px !important;" />'; return [ 0 => [ 'value' => $value, 'format' => 'full_html', ], ]; } } }
I'm guessing it's somewhere in here I need to add a hook to make it seen in Views? I tried following the Drupal site information but nothing worked.
- 🇬🇧United Kingdom joachim
No, the hook goes in the .module file.
Again, again - USE MODULE BUILDER. It will put all the things in the right places for you.
BTW, I don't think this will work:
> if(!empty($host_entity->field_isbn10->value)) {
IIRC you need to use $entity->field->isEmpty()
- 🇬🇧United Kingdom joachim
An example of how to declare the field to Views in hook_views_data(), from my comment on 📌 Allow adding computed bundle fields in Views Fixed :
$data['node_field_data']['test_2981047_base'] = [ 'title' => t('Test computed base field 2981047'), 'entity field' => 'test_2981047_base', 'field' => [ 'id' => 'field', ], ]; $data['node_field_data']['test_2981047_bundle'] = [ 'title' => t('Test computed bundle field 2981047'), 'entity field' => 'test_2981047_bundle', 'field' => [ 'id' => 'field', ], ];
- 🇬🇧United Kingdom joachim
* "entity_types" = { * "entity_test" = {}, * },
Do you actually want to attach this field to the 'entity_test' entity type?
- 🇮🇹Italy MarcoPBazz
An example of how to declare the field to Views in hook_views_data(), from my comment on #2981047: Allow adding computed bundle fields in Views:
It's working form me (Drupal 9.5x + computed 4.0.0-alpha2) as I can show my computed field, but if I try to filter but I get "missing or broken handler for this element" as message.
Here's my code in my .views.inc file
function mymodule_views_data_alter(&$data) { $data['node_field_data']['myfield'] = [ 'title' => 'Myfield title', 'entity field' => 'myfield', 'field' => [ 'id' => 'field', ], 'filter' => [ 'title' => t('Myfield title'), 'field' => 'id', 'id' => 'myfield', ], ]; }
What am I missing?
- 🇬🇧United Kingdom joachim
You can't filter by a computed field, as there is no data in the database for SQL to query.
- 🇺🇸United States mlncn Minneapolis, MN, USA
Curious about the difference between joachim's example of how to declare the field to Views in hook_views_data() 💬 Access Computed Field in Views Active versus that in the change record associated with the same issue, Computed fields can now be displayed by Views → , which would seem to suggest something looking more like this:
/** * Implements hook_views_data_alter(). */ #[Hook('views_data_alter')] public function addComputedFieldChangedFields(&$data) { $data['node']['computed_example'] = [ 'title' => t('Computed field example'), 'field' => [ 'id' => 'field', 'default_formatter' => 'string', 'field_name' => 'computed_example', ], ]; } }
'node' instead of 'node_field_data', no 'entity field' line.
Confirmed that i can get it to show up using Joachim's approach; here is the full thing in the object-oriented hook implementation → available from Drupal 11.1 onward:
declare(strict_types = 1); namespace Drupal\example\Hook; use Drupal\Core\Hook\Attribute\Hook; class ViewsDataAlter { /** * Implements hook_views_data_alter(). */ #[Hook('views_data_alter')] public function addComputedFieldChangedFields(&$data) { $data['node_field_data']['computed_example'] = [ 'title' => t('Computed field example'), 'entity field' => 'computed_example', 'field' => [ 'id' => 'computed_example', ], ]; } }
However i am unable to test that it works beyond showing up in Views due to i think an unrelated error: 🐛 Call to undefined method Drupal\computed_field\Field\FieldStorageDefinition::getThirdPartySetting() Active
- 🇺🇸United States mlncn Minneapolis, MN, USA
With the code above and a
computed_example
field that is otherwise working, while i can add my field to a view it does not work, and indeed warns immediately:The handler for this item is broken or missing. The following details are available:
Installing the appropriate module may solve this issue. Otherwise, check to see if there is a module update available.
That is, Views knows my computed field has a broken or missing handler, but it cannot provide any details about it.
Suggestions?
- 🇬🇧United Kingdom joachim
> 'node' instead of 'node_field_data',
node is the base table, node_field_data is the field data table. It may be that one of those is the old way, I'm not sure. Check how Views declares config fields to views data.
> no 'entity field' line.
IIRC Views field handler plugins expect this property to be there, to tell it the name of the field.
> The handler for this item is broken or missing. The following details are available:
Can you debug to see what handler it's trying to use?
- 🇺🇸United States mlncn Minneapolis, MN, USA
Inside $this Drupal\views\Plugin\views\field\Broken, configuration, id = "computed_changed_shortterm_fields"
(In the report above i replaced "computed_changed_shortterm_fields" with "computed_example" but other than that it is identical.)
And before handlePluginNotFound, when PluginManagerBase does createInstance, the $plugin_id it has is "computed_changed_shortterm_fields" with $configuration:
id = "computed_changed_shortterm_fields"
group = TranslatableMarkup "String"
title = TranslatableMarkup "Computed changed short-term fields"
entity_type = "node"
entity field = "computed_changed_shortterm_fields"What is the plugin expected to be?
Again, the computed field itself with ID "computed_changed_shortterm_fields" is working, but including that code here for completeness:
<?php namespace Drupal\hw_household\Plugin\ComputedField; use Drupal\computed_field\Attribute\ComputedField; use Drupal\computed_field\Field\ComputedFieldDefinitionWithValuePluginInterface; use Drupal\computed_field\Plugin\ComputedField\ComputedFieldBase; use Drupal\computed_field\Plugin\ComputedField\SingleValueTrait; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Computed field which outputs short-term changed fields as a string. */ #[ComputedField( id: "hw_household_changed_shortterm_fields", label: new TranslatableMarkup("Changed short-term fields"), field_type: "string", )] class ChangedShortTermFields extends ComputedFieldBase { use SingleValueTrait; /** * {@inheritdoc} */ public function singleComputeValue(EntityInterface $entity, ComputedFieldDefinitionWithValuePluginInterface $computed_field_definition): mixed { $revision_id = \Drupal::service('revision_summary.compare_revisions')->latestRevisionIdWithChangedField($entity, 'field_date_stamp'); $fields = \Drupal::service('revision_summary.compare_revisions')->listChangedFields($entity, $revision_id); return implode(',', array_values($fields)); } }
(Relying on Revision Summary → module which i've contributed, though it turns out to really be using Diff module, remixed slightly.)
- 🇬🇧United Kingdom joachim
Is this bit:
> id = "computed_changed_shortterm_fields"
what you've declared to views data? 'id' is the ID of the Views field plugin to handle the field. And you've not defined that plugin. IIRC you can just use the plugin for the specific field type -- see the core issue for declaring bundle fields to views.