Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Customizing a CSV export with Entity Export CSV on Drupal 8

The Entity Export CSV module allows us to quickly set up CSV exports for any type of Drupal 8 content entity. Sometimes, we may need to customize the exports we perform, such as exporting 2 different pieces of information from the same Entity Reference field for example. Let's find out how to customize our CSV exports.

And because a good example is sometimes better than a long speech, we will cover a specific need here, by way of illustration. From a Drupal commerce order entity, we want to be able to export the Phone field associated with the Billing Profile. Indeed, order entities have an Entity Reference Revisions field that references the Billing Profile filled in during the purchase tunnel, and we want to be able to extract from this Profile entity a particular field, the phone.

First, we will alter the fields retrieved from the Order entity. Indeed the Entity Export CSV module dispatches an event allowing us to easily alter the fields retrieved from a given entity.

In order to be able to extract the phone we will dynamically add a pseudo field on this entity.

We create an EventSubscriber service in our custom module my_module, and more precisely in the file my_module.services.yml.

my_module.entity_export_csv_billing_phone:
  class: Drupal\my_module\EventSubscriber\EntityExportCsvBillingPhoneEventSubscriber
  tags:
    - { name: event_subscriber }

And our Class to alter the fields available on the Order entity. This alteration allows us to add as many pseudo fields as necessary.

Below our Class EntityExportCsvBillingPhoneEventSubscriber.

namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\entity_export_csv\Event\EntityExportCsvEvents;
use Drupal\entity_export_csv\Event\EntityExportCsvFieldsSupportedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EntityExportCsvBillingPhoneEventSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [];
    $events[EntityExportCsvEvents::ENTITY_EXPORT_CSV_FIELDS_SUPPORTED] = ['alterFields'];
    return $events;
  }

  /**
   * We want to add a pseudo custom field to export the billing phone field..
   *
   * @param \Drupal\entity_export_csv\Event\EntityExportCsvFieldsSupportedEvent $event
   *   The event.
   */
  public function alterFields(EntityExportCsvFieldsSupportedEvent $event) {
    $entity_type_id = $event->getEntityTypeId();
    if ($entity_type_id === 'commerce_order') {
      $fields = $event->getFields();
      if (isset($fields['billing_profile'])) {
        $fields['billing_phone'] = $fields['billing_profile'];
        $event->setFields($fields);
      }
    }
  }

}

We duplicate here the billing_profile field available on the order entity to have a new billing_phone field for which we can set up a specific dedicated export.

Let's create our field export plugin dedicated to this field (see Export content to CSV with Drupal 8).

In the src/Plugin/FieldTypeExport directory of our module, we create our specific BillingPhoneExport Plugin.

namespace Drupal\my_module\Plugin\FieldTypeExport;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\entity_export_csv\Plugin\FieldTypeExportBase;
use Drupal\Core\Field\FieldItemInterface;

/**
 * Defines a billing phone field type export plugin.
 *
 * @FieldTypeExport(
 *   id = "billing_phone_export",
 *   label = @Translation("Billing phone export"),
 *   description = @Translation("Billing phone export"),
 *   weight = 100,
 *   field_type = {
 *     "entity_reference_revisions",
 *   },
 *   entity_type = {
 *    "commerce_order",
 *   },
 *   bundle = {},
 *   field_name = {
 *     "billing_phone",
 *   },
 *   exclusive = FALSE,
 * )
 */
class BillingPhoneExport extends FieldTypeExportBase {

  /**
   * {@inheritdoc}
   */
  public function getSummary() {
    return [
      'message' => [
        '#markup' => $this->t('Billing phone field type exporter.'),
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function massageExportPropertyValue(FieldItemInterface $field_item, $property_name, FieldDefinitionInterface $field_definition, $options = []) {
    if ($field_item->isEmpty()) {
      return NULL;
    }
    $configuration = $this->getConfiguration();
    if (empty($configuration['format'])) {
      return $field_item->get($property_name)->getValue();
    }

    $field = $configuration['format'];
    if ($field) {
      $entity = $field_item->get('entity')->getValue();
      if ($entity instanceof ContentEntityInterface) {
        if ($entity->hasField($field)) {
          return $entity->{$field}->value;
        }
      }
    }

    return $field_item->get($property_name)->getValue();
  }

  /**
   * {@inheritdoc}
   */
  protected function getFormatExportOptions(FieldDefinitionInterface $field_definition) {
    $options = parent::getFormatExportOptions($field_definition);
    $options['field_phone'] = $this->t('Phone');
    return $options;
  }

}

Our Field Export Plugin declares the field_name in its annotations so that it is only available for the pseudo field we created. We use the export formatting options to add the field we want to export (if necessary, we could for example want to export several fields from the Profile entity, we could then use the same Field Export Plugin) then simply, based on the basic Plugin provided by the module for Entity Reference (EntityReferenceExport) fields, we adapt the massageExportPropertyValue() method to export the desired field from the Profile entity.

And in a few moments we have then the possibility to export the phone field from the Profile entity referenced by an order.

Billing phone export

We can then enable our new pseudo field, select the specific export format and extract all the data needed for the job.

These techniques can be used with the help of a Drupal 8 developer to enrich data exports and adapt them to the most specific business needs, without having to redevelop a whole specific export routine.

Author: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web