Drupal 9: Get List Of Content Types

Getting a list of content types out of a Drupal 9 site is useful in a few situations. Mostly, I find that when creating a service of some kind that I will also create an administration form for that service to allow it to be restricted to certain content types. This list can be saved to configuration so that when the service is run it only effects certain content types, based on the saved configuration.

To get a an array containing a list of the content types on a Drupal site you can use the following code.

$entityTypeManager = \Drupal::service('entity_type.manager');

$types = [];
$contentTypes = $entityTypeManager->getStorage('node_type')->loadMultiple();
foreach ($contentTypes as $contentType) {
  $types[$contentType->id()] = $contentType->label();
}

This generates a list of content types that are currently installed on your system. This is a list of \Drupal\node\Entity\NodeType entities so we can extract the machine name of the content type using the id() method, and the human readable name of the content type using the label() method. The above code will produce something like the following on a standard install of Drupal.

Array
(
    [article] => Article
    [page] => Page
)

You can also include this as a function in a form to generate a list of checkboxes that can be saved to configuration. If you extend from ConfigFormBase you can easily generate a form that will save a the list of content types to the system configuration. The following block of code is a form class that will print out a list of the content types as checkboxes.

<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

class MyModuleSettingsForm extends ConfigFormBase {

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * Constructs an AutoParagraphForm object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entityTypeManager.
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager) {
    $this->entityTypeManager = $entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'mymodule_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return ['mymodule.settings'];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('mymodule.settings');

    $existingContentTypeOptions = $this->getExistingContentTypes();

    $form['content_types'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Content Types'),
      '#options' => $existingContentTypeOptions,
      '#empty_option' => $this->t('- Select an existing content type -'),
      '#default_value' => $config->get('content_types', []),
      '#required' => TRUE,
    ];

    return parent::buildForm($form, $form_state);
  }


  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $config = $this->config('mymodule.settings');

    $config->set('content_types', $form_state->getValue('content_types'))
    $config->save();

    parent::submitForm($form, $form_state);
  }

  /**
   * Returns a list of all the content types currently installed.
   *
   * @return array
   *   An array of content types.
   */
  public function getExistingContentTypes() {
    $types = [];
    $contentTypes = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
    foreach ($contentTypes as $contentType) {
      $types[$contentType->id()] = $contentType->label();
    }
    return $types;
  }
}

Once the form has been saved you can extract the content types array from config using something like the following.

$config = \Drupal::config('mymodule.settings');
$contentTypes = $config->get('content_types');

I frequently use this block of code so I thought it might come in handy for other people.

Comments

Thanks Philip, but tried implemting this on a controller for a custom module and it didn't work. Any pointers?

Permalink

Hi Tony,

I can't see anything wrong with putting this in a controller. 

In fact, I did just that. Here's the code that prints out the list of content types in markup field

<?php

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * Controller for the content type page.
 */
class ContentTypeController extends ControllerBase {

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * ContentTypeController constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entityTypeManager.
   */
  public function __construct(EntityTypeManagerInterface $entityTypeManager) {
    $this->entityTypeManager = $entityTypeManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager')
    );
  }

  /**
   * Renders the page.
   *
   * @return array
   *   The page render array.
   */
  public function page() {
    $output = [];

    $existingContentTypeOptions = $this->getExistingContentTypes();

    $output['content_types'] = [
      '#markup' => implode(', ', $existingContentTypeOptions),
    ];

    return $output;
  }

  /**
   * Returns a list of all the content types currently installed.
   *
   * @return array
   *   An array of content types.
   */
  public function getExistingContentTypes() {
    $types = [];
    $contentTypes = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
    foreach ($contentTypes as $contentType) {
      $types[$contentType->id()] = $contentType->label();
    }
    return $types;
  }

}

I hope that helps! Let me know if you need more info.

Name
Philip Norton
Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
11 + 1 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.