9

I'm writing a custom module, which I've done before, but this is the first time I've tried to create a content type with fields. I implemented hook_node_info and the Content Type is showing up in the list of Content types in the dropdown from admin_menu, however, when I browse to admin/structure/types it is not listed.

I implemented hook_install and grabbed some code I found on another SO question. I have the code print out some debug info to my error log and it LOOKS like it all works, but when I browse to the Structure Content Type it doesn't show the field I added.

Here are hooks:

function mymod_node_info() {
  return array(
    'mymod_content' => array(
      'name' => t('My Mod'),
      'base' => 'mymod_content',
      'description' => t('A Description'),
    )
  );
}

function mymod_install() {
    error_log('mymod_install');
    $types = node_type_get_types();

    if ( ! field_info_field('field_mymod_myfile') ) {
        $field = array(
            'field_name' => 'field_mymod_myfile',
            'type' => 'file',
        );
        $created_field = field_create_field($field);
        error_log('---- field_create_field -----');
        error_log(var_export($created_field, true));
    }

    $instance = array(
        'field_name' => 'field_mymod_myfile',
        'entity_type' => 'mymod_content',
        'bundle' => 'mymod_content',
        'required' => TRUE,
    );
    $created_instance = field_create_instance($instance);
    error_log('---- field_create_instance -----');
    error_log(var_export($created_instance, true));
}

I can see a table called field_data_field_mymod_myfile in the database, so I know the first part worked. However, the table is empty.

The error log shows the field_create_instance() method returned this:

array (
  'field_name' => 'field_mymod_myfile',
  'entity_type' => 'mymod_content',
  'bundle' => 'mymod_content',
  'required' => true,
  'field_id' => '5',
)

Why doesn't my field show up on this content type?

  • 1
    do you not like Features? I find it easiest to make the Content Type using the FieldUI then export the Feature to a custom "Feature" (module). ... it just making the arrays used the hook_info you have here -- and the arrays for field definitions. You could cross check your work that way. – tenken Jun 14 '13 at 5:07
6

This isn't so much an answer as it is an expansion on the previous answer.

I found these two links very helpful in figuring out what the system needs for custom fields to be added to your custom module node type.

Best: http://www.sitepoint.com/creating-a-new-drupal-node-type/

Good additional info: http://public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api

The problem I had was that these (and every other example I can find online) are very specific examples without enough documentation to help me figure out a solution to my own usage case.

What helped was tenken's comment to the OP about using the Features module to get the arrays for the custom fields.

So I downloaded the Features module and enabled it: https://drupal.org/project/features

Then I created the fields on my content type, using the admin interface in Drupal like you normally would, that I wanted the module to create. Then I browsed to Structure > Features > Create feature and put in a bogus name (I used "test") for the feature and then over in the components area click on "Field Instances" and check the boxes for the custom fields. The fields are all named something like node-[your node type machine name]-[field name], so in my case since I wanted an image field it was node-novel_section-field_image.

After selecting the custom fields for my node type I then just clicked on "Download feature" and saved the .tar file to my desktop, opened it, opened the "test" folder then viewed the test.features.field_base.inc and test.features.field_instance.inc to get the arrays I needed for my fields.

Then I just used the structure outlined by that first link I posted and after that it worked perfectly. For me.

I could not find any documentation on the array structures needed for things like image fields and taxonomy reference fields and it seemed all other tutorials and help requests online are focused on specific things like text fields.

Hopefully anyone having the same trouble I was having will see this and be able to make their setup work using these examples and the Features module like I did.

Thanks to tenken for pointing out this functionality of the Features module, I'd never used it and didn't know it would do that.

4

This code that will be created new content type that should add into .install file.

Adding hook_install():

<?php
function your_module_name_install() {
  // use get_t() to get the name of our localization function for translation
  // during install, when t() is not available.
  $t = get_t();

  // Define the node type.
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );

  // Complete the node type definition by setting any defaults not explicitly
  // declared above.
  // http://api.drupal.org/api/function/node_type_set_defaults/7
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);

  // Save the content type
  node_type_save($content_type);
}
?>

You should make drupal message and write this event to the log:

<?php
function your_module_name_install() {
  $t = get_t();
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);
// Check if we create content type or update.
  $status = node_type_save($content_type);
// Replacement rule for the messages.
  $t_args = array('%name' => $content_type->name);
  if ($status == SAVED_UPDATED) { // update case
    drupal_set_message($t('The content type %name has been updated.', $t_args));
  } 
  elseif ($status == SAVED_NEW) { // create case
    drupal_set_message($t('The content type %name has been added.', $t_args));
    watchdog('node', 'Added content type %name.', $t_args, WATCHDOG_NOTICE, l($t('view'), 'admin/structure/types')); 
  }
}
?>

Provide hook_uninstall() to remove your content type :

<?php
function your_module_name_uninstall() {
  // Gather all the example content that might have been created while this
  // module was enabled.  Simple selects still use db_query().
  // http://api.drupal.org/api/function/db_query/7
  $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
  $result = db_query($sql, array(':type' => 'node_example'));
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
  // Delete all the nodes at once
  // http://api.drupal.org/api/function/node_delete_multiple/7
  node_delete_multiple($nids);
  // Delete our content type
  // http://api.drupal.org/api/function/node_type_delete/7
  node_type_delete('node_example');
}
?>
  • Thank you for a very detailed response, but how do I add a File field to the content type after it has been created? – Kenny Wyland Jun 14 '13 at 21:15
  • I used your code above and it says the content type was added, but it doesn't show up admin/structure/types – Kenny Wyland Jun 14 '13 at 21:29
  • 1
    To get this to work, you need to implement hook_form() in your module otherwise if you look in the node_type table in the database, you will notice that your newly created type is disabled. Implementing hook_form() seems to activate it (why it is this way, I have no idea and it doesn't make much sense). This addresses your second comment by the way. – user5013 Oct 9 '13 at 1:39
1

This post is a bit out-dated, but if it helps, I’ve found this article to be very clear. It shows you how to create a new content type step-by-step.

Link to tutorial

<?php

/**
 * Implements hook_install().
 */
function book_install()
{

    $t = get_t();

    // Step 1 - Define the custom content type

    $content_type = array(

        'type'          => 'book',
        'name'          => $t('Book'),
        'description'   => $t('Create a new book'),
        'title_label'   => $t('Book title'),
        'base'          => 'node_content',
        'custom'        => TRUE,

    );

    $node_type = node_type_set_defaults($content_type);

    node_type_save($node_type);

    // Step 2 - Create new fields

    $fields = array(

        // Author’s name

        'book_author_name'  => array(

            'field_name'    => 'book_author_name',
            'type'          => 'text',
            'cardinality'   => 1,

        ),

        // Description

        'book_description'  => array(

            'field_name'    => 'book_description',
            'type'          => 'text_long',
            'cardinality'   => 1,

        ),

    );

    foreach( $fields as $field ) {

        field_create_field($field);

    }

    // Step 3 - Attach fields to content type

    $instances = array(

        // Author’s name

        'book_author_name'  => array(

            'field_name'   => 'book_author_name',
            'label'        => $t('Author Name'),
            'required'     => TRUE,
            'widget'       => array(
                'type'  => 'text_textfield'
            ),

        ),

        // Description

        'book_description'  => array(

            'field_name'   => 'book_description',
            'label'        => $t('Description'),
            'required'     => TRUE,
            'widget'       => array(
                'type'  => 'text_textarea'
            ),

        ),

    );

    foreach( $instances as $instance ) { // Loop through our instances

        $instance['entity_type']   = 'node';
        $instance['bundle']        = 'book'; // Attach the instance to our content type

        field_create_instance($instance);

    }

}
  • Please include a relevant quote of it in your answer – Pierre.Vriens Jul 21 '16 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.