在自定义模块中通过文件字段以编程方式创建内容类型


9

我正在编写一个自定义模块,这是我之前做过的,但这是我第一次尝试使用字段创建内容类型。我实现了hook_node_info,内容类型显示在admin_menu下拉列表中的内容类型列表中,但是当我浏览到admin/structure/types它时未列出。

我实现了hook_install,并获取了在另一个SO问题上发现的一些代码。我已经将代码打印出一些调试信息到我的错误日志中,并且看起来一切正常,但是当我浏览到“结构内容类型”时,它没有显示我添加的字段。

这是钩子:

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));
}

我可以看到field_data_field_mymod_myfile数据库中有一个表,所以我知道第一部分已经工作了。但是,该表为空。

错误日志显示field_create_instance()方法返回了以下内容:

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

为什么我的字段没有显示在此内容类型上?


1
您不喜欢功能吗?我发现最简单的方法是使用FieldUI创建内容类型,然后将功能导出到自定义“功能”(模块)。...这只是使数组使用您在此处具有的hook_info以及用于字段定义的数组。您可以通过这种方式交叉检查工作。
tenken 2013年

Answers:


7

这并不是一个答案,而是对先前答案的扩展。

我发现这两个链接对于确定系统需要将自定义字段添加到自定义模块节点类型中非常有用。

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

良好的附加信息:http : //public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api

我遇到的问题是,这些(以及我可以在网上找到的所有其他示例)都是非常具体的示例,没有足够的文档来帮助我为自己的使用案例找到解决方案。

Tenken对OP的评论是有关使用功能模块获取自定义字段的数组的。

因此,我下载了功能模块并启用了它:https : //drupal.org/project/features

然后,像通常一样,使用Drupal中的管理界面在我的内容类型上创建字段,我希望模块可以创建。然后,我浏览到“结构”>“特征”>“创建特征”,并为该特征输入一个假名称(我使用“ test”),然后在组件区域中单击“字段实例”,然后选中自定义字段的复选框。这些字段都被命名为诸如node- [您的节点类型机器名称]-[字段名称]之类的名称,因此在我的情况下,由于我想要一个图像字段,所以它是node-novel_section-field_image。

在为我的节点类型选择了自定义字段之后,我只需单击“下载功能”,然后将.tar文件保存到我的桌面,将其打开,打开“ test”文件夹,然后查看test.features.field_base.inc并进行测试。 features.field_instance.inc获取我的字段所需的数组。

然后,我只使用了我发布的第一个链接所概述的结构,此后它完美地起作用了。为了我。

我找不到有关图像字段和分类法参考字段之类的东西所需的数组结构的任何文档,似乎其他所有在线教程和帮助请求都集中在诸如文本字段之类的特定事物上。

希望任何遇到我同样麻烦的人都能看到这一点,并能够像我一样使用这些示例和功能模块来进行设置。

感谢tenken指出了功能模块的此功能,我从未使用过它,也不知道它会这样做。


4

此代码将创建新的内容类型,应添加到.install文件中。

添加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);
}
?>

您应该发出drupal消息并将此事件写入日志:

<?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')); 
  }
}
?>

提供hook_uninstall()删除您的内容类型

<?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');
}
?>

感谢您的非常详细的答复,但是创建内容类型后如何在内容类型中添加文件字段?
肯尼·怀兰德

我在上面使用了您的代码,并说内容类型已添加,但未显示出来admin/structure/types
Kenny Wyland 2013年

1
为了使它起作用,您需要在模块中实现hook_form(),否则,如果您查看数据库中的node_type表,您会注意到禁用了新创建的类型。实现hook_form()似乎可以激活它(为什么是这种方式,我不知道,而且没有多大意义)。顺便说一下,这解决了您的第二条评论。
2013年

1

这篇文章有点过时了,但是如果有帮助,我发现这篇文章很清楚。它向您展示如何逐步创建新的内容类型。

链接到教程

<?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);

    }

}

请包括它的相关报价在你的答案
Pierre.Vriens
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.