---
url: 'https://metadrop.net/en/articles/search-api-create-custom-fields-using-custom-processors-in-drupal-8'
title: 'SEARCH API - Create custom fields using custom Processors in Drupal 8'
author: 'Agustin Gómez'
date: '2017-01-17T09:38:50+00:00'
updated: '2026-09-02T08:06:28+00:00'
type: article
summary: 'Create custom fields using custom Processors in Drupal 8'
tags:
  - 'Drupal 8'
  - 'Search API (Drupal module)'
  - Solr
image: 'https://metadrop.net/sites/default/files/styles/full/public/article/image/seach-api-architecture-overview.png.webp?itok=zbY6Tj2y'
published: true
og:
  determiner: Automatic
  site_name: Metadrop
  'image:url': 'https://metadrop.net/sites/default/files/styles/full/public/article/image/seach-api-architecture-overview.png.webp?itok=zbY6Tj2y'
  'image:type': image/png
  'image:width': '563'
  'image:height': '441'
  'image:alt': 'SEARCH API - Create custom fields using custom Processors in Drupal 8'
  street_address: 'Calle Manuel Luna, 12, 3 Dcha'
  locality: Madrid
  region: Madrid
  postal_code: '28020'
  country_name: España
  email: hola@metadrop.net
  phone_number: '910053180'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      '@type': Article
      '@id': 'https://metadrop.net/en/articles/search-api-create-custom-fields-using-custom-processors-in-drupal-8#article'
      name: 'SEARCH API - Create custom fields using custom Processors in Drupal 8'
      headline: 'SEARCH API - Create custom fields using custom Processors in Drupal 8'
      description: 'Create custom fields using custom Processors in Drupal 8'
      about:
        - 'Drupal 8'
        - 'Search API (Drupal module)'
        - Solr
      image:
        '@type': ImageObject
        url: 'https://metadrop.net/sites/default/files/styles/full/public/article/image/seach-api-architecture-overview.png.webp?itok=zbY6Tj2y'
        width: '563'
        height: '441'
      datePublished: '2017-01-01T00:00:00+0100'
      dateModified: '2026-09-02T10:06:28+0200'
      author:
        '@type': Person
        name: 'Agustin Gómez'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
      mainEntityOfPage: 'https://metadrop.net/en/articles/search-api-create-custom-fields-using-custom-processors-in-drupal-8'
    -
      '@type': Organization
      '@id': 'https://metadrop.net/#organization'
      url: 'https://metadrop.net/'
      name: Metadrop
      sameAs:
        - 'https://www.drupal.org/metadrop'
        - 'https://twitter.com/metadrop'
        - 'https://asociaciondrupal.es/partner/metadrop'
        - 'https://www.linkedin.com/company/metadrop'
      logo:
        '@type': ImageObject
        url: 'https://metadrop.net/themes/custom/mdrop_radix/logo-metadrop-500-500.jpg'
        width: '500'
        height: '500'
    -
      '@type': ItemPage
      '@id': 'https://metadrop.net/en/articles/search-api-create-custom-fields-using-custom-processors-in-drupal-8'
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://metadrop.net/en'
          -
            '@type': ListItem
            position: 2
            name: 'Expert Drupal & Tech Articles'
            item: 'https://metadrop.net/en/articles'
      publisher:
        '@type': Organization
        '@id': 'https://metadrop.net/#organization'
---
 1. [Articles](https://metadrop.net/en/articles)
 
  

# SEARCH API - Create custom fields using custom Processors in Drupal 8

Sunday, January 01, 2017

 

 



Create custom fields using custom Processors in Drupal 8



   



## Summary

This is a Drupal 8 example.

Using the [Search API](https://www.drupal.org/project/search_api) module will allow you to have a fast and complete search feature solution in your site, but sometimes there are some scenarios where we want to modify the behaviour of the indexed items.

## Scenario

We are using Search API module with the [Search API Solr](https://www.drupal.org/project/search_api_solr) backend.

Let's say we have a content type called "Expedient". This content type has a (entity reference) field pointing to a custom entity with some metadatas that we want to index and search.
Probably there will be many solutions for this scenario, but we will use a custom Processor to achieve this goal.

## Example

In this example we will create a search api Plugin processor taking the idea from these existing ones: AddURL and AggregatedFields processors.

Basically we will follow 3 steps:

1. **alterPropertyDefinitions**: We will define (create) three custom fields of different types.
2. **preprocessIndexItems**: We will use these fields depending on some "custom" conditions.
3. **preIndexSave**: We will let the index know about these fields and use them as if they were a "normal" content type field (just like the nid, for example)

## Code

Updates and code available in this [snippet](https://bitbucket.org/snippets/metadrop/aKrzK) and the [Drupal Community Documentation](https://www.drupal.org/node/2715959).

### 1. alterPropertyDefinitions()

We will define our fields with some label, description and type. We need to define them if we want to use them later on.

```php
<?php

/**
 * @file
 * Contains \Drupal\MY_MODULE\Plugin\search_api\processor\AddCustomField.
 *
 * A proccesor example that adds some custom fields.
 * 
 * @NOTE 
 *   - Replace any occurrences of MY_MODULE with your module machine_name.
 *   - Name this file AddCustomField.php and place it in the correct folder.
 *
 * @TODO Make some tests.
 */

namespace Drupal\MY_MODULE\Plugin\search_api\processor;

use Drupal\Core\TypedData\DataDefinition;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;


/**
 * @SearchApiProcessor(
 *   id = "MY_MODULE_add_custom_field",
 *   label = @Translation("Custom field examples"),
 *   description = @Translation("Adds custom field examples."),
 *   stages = {
 *     "pre_index_save" = -10,
 *     "preprocess_index" = -30
 *   }
 * )
 */
class AddCustomField extends ProcessorPluginBase {
  /**
   * {@inheritdoc}
   *
   */
  public function alterPropertyDefinitions(array &$properties, DatasourceInterface $datasource = NULL) {
    // These fields will not have a Data source associated to them.
    if ($datasource) {
      return;
    }

    // Ensure that our fields are defined.
    $fields = $this->getFieldsDefinition();

    foreach ($fields as $field_id => $field_definition) {
      $properties[$field_id] = new DataDefinition($field_definition);
    }
  }

  /**
   * Helper function for defining our custom fields.
   */
  protected function getFieldsDefinition() {
    $fields['MY_MODULE_field_based_on_nid'] = array(
      'label' => 'Custom field based on nid',
      'description' => 'I will be used to make a text type field with an id if "nid" field exists.',
      'type' => 'text',
      'prefix' => 't', // For Solr fields I think it is ok.
    );
    $fields['MY_MODULE_field_active_standby'] = array(
      'label' => 'Custom field always added, could be used for facets',
      'description' => 'Custom field 2 of type string will be always added with values active/standby.',
      'type' => 'string',
      'prefix' => 's', // For Solr fields I think it is ok.
    );
    $fields['MY_MODULE_field_date_experiment'] = array(
      'label' => 'Custom field of date type, always added',
      'description' => 'I will be added as a time(), but it will be indexed differently.',
      'type' => 'date',
      'prefix' => 'd', // For Solr fields I think it is ok.
    );

    return $fields;
  }
}
```

### 2. preprocessIndexItems()

Here we add our business logic and set our conditions for indexing the fields and values.

```php
<?php
  /**
   * {@inheritdoc}
   */
  public function preprocessIndexItems(array &$items) {

    foreach ($items as $item) {

      // First custom field will only be added if we are indexing "nid" field.

      // Note that here we could check a "field_reference" (instead of the nid) to get an Id, pull data from that referenced entity
      // and add the proper values.
      foreach ($this->filterForPropertyPath($item->getFields(), 'nid') as $field_reference) {
        foreach ($this->filterForPropertyPath($item->getFields(), 'MY_MODULE_field_based_on_nid') as $nid_based_field) {
          $nid_based_field->addValue('Node Id: ' . reset($field_reference->getValues()));
        }
      }

      // We will add always this custom field, with random value.
      foreach ($this->filterForPropertyPath($item->getFields(), 'MY_MODULE_field_active_standby') as $always_added_field) {
        $active_standby = rand(0,1) ? 'active' : 'standby';

        $always_added_field->addValue($active_standby);
      }

      // We will add a time() and see how it is indexed.
      foreach ($this->filterForPropertyPath($item->getFields(), 'MY_MODULE_field_date_experiment') as $date_experiment_field) {
        $date_experiment_field->addValue(time());
      }
    }
  }
```

### 3. preIndexSave()

```php
<?php
  /**
   * {@inheritdoc}
   *
   */
  public function preIndexSave() {
    foreach ($this->getFieldsDefinition() as $field_id => $field_definition) {
      // We can specify or not a type in the 3rd parameter.
      // If you don't specify the type, the user will be able to change it through
      // the user interface (could be very useful), but if you specify it, the user won't
      // be able to alter the type.
      $this->ensureField(NULL, $field_id, $field_definition['type']);
    }
  }
```

"Magically" these fields will be available on the UI when we ensure them.



[Drupal 8](https://metadrop.net/en/articles?text=Drupal%208)

[Search API (Drupal module)](https://metadrop.net/en/articles?text=Search%20API%20%28Drupal%20module%29)

[Solr](https://metadrop.net/en/articles?text=Solr)