Field API - Eigene Felder in Drupal 7 erstellen

So, 16.10.2011 - 19:43 -- Daniel Espendiller

In Drupal7 wurden die CCK Fields, bekannt aus Drupal 6, in den Core mit aufgenommen. Hiermit lassen sich pro Inhaltstypen eigene Felder wie Bilder, Dateien, Links , .. anhängen. Es gibt mittlerweile eine recht große Auswahl an zusätzlichen Module, die neue Feldertypen bereit stellen. Logischerweise kann man auch eigene Felder mittels einem Module erstellen. Hierzu findet sich unten ein einfaches Template zur Einbindung.

Hierzu muss man allerdings einige hooks einbinden, die doch recht aufwändig sind. Jedes Feld besteht aus mehreren Funktionen und Ausgaben. Neben der einfachen Felddefinition (hook_widget_info) und den Datenbankfelder (hook_field_schema) werden Felder über sogenannte Widgets (hook_widget_info) definiert. Pro Widget können dann wieder unterschiedliche Formulare zur Dateneingabe angeboten werden, die Ausgabe kann dann wiederum über Formatter (hook_field_formatter_info) geändert und angepasst werden.

Wer übrigens nur einen zusätzlichen Formatter, also die Ausgabe für bereits vorhandenes Feld, ändern will kann auch auf die Erweiterung http://drupal.org/project/custom_formatters zurückgreifen.

Weitere Informationen

Da das Thema doch recht komplex ist und diverse Drupal typischen Funktionsaurufe nutzt hier zusätzlich noch ein paar hilfreichen Links:

Datenbankfelder

Damit Daten aus einem Formular für ein Feld eingeben werden können, müssen diese per hook_field_schema eingebunden werden, dazu wird im Moduleordner eine Datei mit Endung .install angelegt mit folgendem Inhalt:

/**
 * Implements hook_field_schema().
 */
function vcsfield_field_schema($field) {
  return array(
    'columns' => array(
      'file' => array(
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
        'sortable' => TRUE
      ),
      'project' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
        'sortable' => TRUE
      ),
    ),
  );
}

Fertige Vorlage

Dieses PHP-Skript legt man dann noch in die .module Datei des eigenen Modules und man hat ein zusätzliches Feld, welches an beliebigen Inhaltstypen an gehangen werden kann. Mit einem Editor sollte man einfach mymodule entsprechend seinem gewünschten Namen ändern. Es wurde dafür bereits alles vorbereitet.

function mymodule_projects() {
  return array(
    0 => 'empty',
    1 => 'inventorplotclass',
    2 => 'dboxonlinestreams',
    3 => 'phptools',
    4 => 'inventor_printbuttons',
    5 => 'vbnettools',
    6 => 'streamode_dev',
    7 => 'jquery',
  );
}
 
/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mymodule_formatter_mymodule_text' => array(
       'render element' => 'element',
    ),
  );
}
 
/**
 * Implementation of hook_field_info().
 */
function mymodule_field_info() {
  return array(
    'mymodule' => array(
      'label' => t('mymodule'),
      'description' => t('mymodule'),
      'default_widget' => 'mymodule',
      'default_formatter' => 'mymodule_text',
    ),
  );
} 
 
/**
 * Implements hook_field_formatter_info().
 */
function mymodule_field_formatter_info() {
  return array(
    'mymodule_text' => array(
      'label' => 'mymodule',
      'description' => t('test'),
      'field types' => array('mymodule'),
    ),
  );
}
 
/**
 * Implementation of hook_elements_info().
*/
function mymodule_element_info() {
  $elements = array(
    'mymodule' => array(
      '#input' => TRUE,
      '#process' => array('mymodule_text_process'),
    ),
  );
  return $elements;
}
 
/**
 * Implementation of hook_widget_info().
 */
function mymodule_field_widget_info() {
  return array(
    'mymodule' => array(
      'label' => t('text'),
      'field types' => array('mymodule'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
  );
 
}
 
/**
 * Process callback for geshifield_textarea widget.
 */
function mymodule_text_process($element, $form_state, $complete_form) {
 
 
  $defaults = $element['#value'];
  $field = field_widget_instance($element, $form_state);
 
  $element['project'] = array(
    '#type' => 'select',
    '#title' => t('Project'),
    '#default_value' => isset($defaults['project']) ? $defaults['project'] : '',
    '#required' => $element['#required'],
    '#options' => mymodule_projects(),
    '#description' => t($field['description']),
  );
 
  $element['file'] = array(
    '#type' => 'textfield',
    '#title' => t('File'),
    '#default_value' => isset($defaults['file']) ? $defaults['file'] : '',
    '#required' => $element['#required'],
    '#description' => t($field['description']),
  );    
 
  return $element;
}
 
/**
 * Implements hook_field_widget_form().
 */
function mymodule_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $element += array(
    '#type' => $instance['widget']['type'],
    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
  );
  return $element;
}
 
 
/**
 * Implements hook_field_formatter_view().
 */
function mymodule_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $elements = array();
 
  foreach ($items as $delta => $item) {
    $elements[$delta] = array(
      '#markup' => theme('mymodule_formatter_'. $display['type'], array('element' => $item, 'field' => $instance)),
    );
  }
  return $elements;
}
 
/**
 * Implementation of hook_content_is_empty().
 */
function mymodule_field_is_empty($item, $field) {
  if ($item['project'] == 0) return true;
  return empty($item['project']);
}
 
function theme_mymodule_formatter_mymodule_text($variables) {
  $output = $variables['element']['project'];
  return $output;
}