Hello,

I am french so i ll try to explain my problem with simple word.

I make a module in Drupal 8 who create a new content type programmatically.
Module name : Annonce

In config/install i add this file :

node.type.annonce_type.yml

type: annonce_type
name: 'Ajouter une annonce'
description: 'Formulaire pour ajouter une annonce'
help: ''
new_revision: false
display_submitted: true
preview_mode: 0
status: true
langcode: fr

All is good, my new content type is create in backoffice.
But now i ll add some fields programmatically, and i don't find a core module who are doing that.

if someone can tell me the way for add fields for this new content type i ll be happy :)

Thanks
Best Regards
Kevin

Comments

mikejw’s picture

This covers doing it programmatically as opposed to doing it with yml.

wluisi’s picture

I had to do something similar today, programmatically add an existing field to multiple content types. The node module's node_add_body_field() has a good example of this [starts on line 322 of node.module]:

/**
 * Adds the default body field to a node type.
 *
 * @param \Drupal\node\NodeTypeInterface $type
 *   A node type object.
 * @param string $label
 *   (optional) The label for the body instance.
 *
 * @return \Drupal\field\Entity\FieldConfig
 *   A Body field object.
 */
function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
   // Add or remove the body field, as needed.
  $field_storage = FieldStorageConfig::loadByName('node', 'body');
  $field = FieldConfig::loadByName('node', $type->id(), 'body');
  if (empty($field)) {
    $field = entity_create('field_config', array(
      'field_storage' => $field_storage,
      'bundle' => $type->id(),
      'label' => $label,
      'settings' => array('display_summary' => TRUE),
    ));
    $field->save();
    // Assign widget settings for the 'default' form mode.
    entity_get_form_display('node', $type->id(), 'default')
      ->setComponent('body', array(
        'type' => 'text_textarea_with_summary',
      ))
      ->save();
    // Assign display settings for the 'default' and 'teaser' view modes.
    entity_get_display('node', $type->id(), 'default')
      ->setComponent('body', array(
        'label' => 'hidden',
        'type' => 'text_default',
      ))
      ->save();
    // The teaser view mode is created by the Standard profile and therefore
    // might not exist.
    $view_modes = \Drupal::entityManager()->getViewModes('node');
    if (isset($view_modes['teaser'])) {
      entity_get_display('node', $type->id(), 'teaser')
        ->setComponent('body', array(
          'label' => 'hidden',
          'type' => 'text_summary_or_trimmed',
        ))
        ->save();
    }
  }
  return $field;
}
bribread22’s picture

Hi, below is yaml approach. To add a custom field, you'll need to create two custom yml files inside the config/install directory. Below is an example of adding a field called Last Name for a content type called "Person":

Yaml File #1: field.field.node.person.last_name.yml

langcode: en
status: true
dependencies:
  config:
    - field.storage.node.last_name
    - node.type.person
id: node.person.last_name
field_name: last_name
entity_type: node
bundle: person
label: 'Last Name'
description: 'The last name of the person.'
required: false
translatable: true
default_value: {  }
default_value_callback: ''
settings: {  }
field_type: string_long

Yaml File #2: field.storage.node.last_name.yml

langcode: en
status: true
dependencies:
  module:
    - people_finder
id: node.person.last_name
field_name: last_name
entity_type: node
type: string_long
settings:
  case_sensitive: false
module: core
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

Also, make sure to add this field in your existing entity_view_display and entity_form_display files. See https://www.drupal.org/node/2629550 for more details.

Once you add these files, go ahead and install the module as you would for any other module. I hope this helps!

mjsilverman’s picture

This worked perfectly and was simple to understand.

damondt’s picture

Thanks for the solution.  Just wanted to add that if you want to add a field to a third party entity you won't be able to edit the entity_view_display and entity_form_display yml files, but you can load and edit that configuration in a hook_install assuming the entity type is fieldable.

<?php 

$formField = array(
            'type' => 'number',
            'weight' => 9,
            'region' => 'content',
            'settings' => array(
                'placeholder' => '',
            ),
            'third_party_settings' =>  array(),

        );

$formDisplayConfig = \Drupal::configFactory()->getEditable('core.entity_form_display.[entity_type].[entity_bundle].default');
        
$formDisplayConfig->set('content.[field_name]', $formField);
$formDisplayConfig->save();
raajkumar.kuru’s picture

Its working fine,
can we have the same for taxonomy too
also please explain where do you find this techniques

damondt’s picture

In Drupal 8 Taxonomy Terms are Entities just like Nodes.  So in the code above just replace "node" with "taxonomy_term", as both of those are "Entity Types".  If you want to read up on it I would recommend the entity api documentation, but it's a lot of reading.

jackellis’s picture

What if the module is already installed. How do you add the fields to an existing content type without re-installing the module? Can you run update.php or something?

Jaypan’s picture

drush entity-update

jackellis’s picture

I added my new field yml files to config/install and ran drush entity-update. However, drush reported "No entity schema updates required". Do I need to do something else to make drupal recognize the addition to config/install?

jackellis’s picture

After about 2 weeks of searching I found the command I was looking for:

drush cim --partial --source=~/path/to/directory/of/new/yml/files
rockthedrop’s picture

Hello everyone.  This is soo very close to what I need. I hope any of you can help:

Please tell me how you would go about setting up an entity reference field programmatically.  I'm just now starting on this migration from D7 to D8 and, while learning a lot, I'm learning a lot about what's missing as well.

Thank you for any assistance.

damondt’s picture

Adding an entity reference field is much the same, the difference is just in the field and field definition settings.  You want the type to be 'entityreference'. See https://www.drupal.org/project/entityreference/issues/1264160

rockthedrop’s picture

Hi.. .So I managed to get my reference fields (nodereference) migrated without coding. 

Using a backup of the D7 database, https://www.drupal.org/project/entityreference_migration installation and following README instructions worked like a charm.

Unfortunately, the Taxonomy Entity reference "Form Display" settings didn't transfer properly. So I need to figure that part out next.  THanks for your suggestion.

I'm not sure how to do it yet - still getting my D8 coding chops together... but I wanna submit a patch to make that happen properly.

matthieuscarset’s picture

You can create fields programmatically with this module from custom YAML or JSON files:

https://drupal.org/project/field_create

You can use the provided hook to add your fields to the list:

function mymodule_field_create_alter(&$definitions) {}

And simply run the drush command: drush field_create