Como criar programaticamente campos?

56

Como posso abordar a implementação do seguinte no Drupal 7?

O que eu preciso fazer é criar um módulo que defina uma nova entidade de campo, chamada 'Empresa'. Eu tenho uma lista de, digamos, 20 campos que precisam ser preenchidos por cada instância da empresa. Essas perguntas são predefinidas e algumas podem conter validação personalizada.

No momento, estou no momento em que posso adicionar novos campos à entidade da empresa. Isso funciona bem no momento. Meu problema é que preciso que todos esses campos estejam lá assim que o módulo for instalado, portanto, adicioná-los pela interface não é uma opção.

Fiquei me perguntando como posso abordar isso? Eu diria que é possível fazer o que pode ser feito usando a interface do usuário 'Gerenciar campos' programaticamente.

NRaf
fonte
Não sou claro sobre o escopo completo de suas necessidades, mas acho que esse segmento será útil para você: drupal.org/node/721552 Ele mostra um código de exemplo para criar um tipo de conteúdo personalizado com campos quando um módulo é instalado pela primeira vez. Você provavelmente precisará pesquisar na API para obter as configurações exatas de campo necessárias, mas esse seria um bom ponto de partida. Basicamente, você precisará examinar node_type_set_defaults()e node_type_save(), claro, também hook_install().
handsofaten
Se você estiver fazendo isso no código, em vez de Recursos, dê uma olhada no Exemplo de Campos e no Exemplo de Nó no Projeto Exemplos .
Rfay
Algumas palavras de orientação. Se você deseja manter um nível de controle sobre a configuração dos campos, use Recursos para registrá-los e aplicá-los. Se você deseja defini-los como uma operação única e permitir que sua configuração seja substituída livremente no futuro, escolha uma solução de código em um arquivo .install.
Alfred Armstrong

Respostas:

41

Use field_create_field () para criar o próprio campo e field_create_instance () para ter uma instância para o pacote configurável de entidade especificado.

Ao criar campos como parte de um módulo personalizado, você pode ou não desejar excluir o campo quando o módulo for desinstalado. Para fazer isso, você pode usar field_delete_field () se desejar excluir o campo e toda a instância do campo, ou se desejar excluir instâncias específicas, poderá usar field_delete_instance () .

tamasd
fonte
Como excluímos os campos que criamos ao desinstalar o módulo?
Ashok KS
Ashok, adicionei um esclarecimento para você em uma edição que acabei de fazer na resposta.
Lester Peabody #
9

Exemplo de como adicionar programaticamente campos ao perfil do usuário e como utilizá-los, ou não, no formulário Registro do Usuário.


function MYMODULE_enable() {
  // Check if our field is not already created.
  if (!field_info_field('field_myField')) {

    // Create the field base.
    $field = array(
      'field_name' => 'field_myField', 
      'type' => 'text', 
    );
    field_create_field($field);

    // Create the field instance on the bundle.
    $instance = array(
      'field_name' => 'field_myField', 
      'entity_type' => 'user', 
      'label' => 'My Field Name', 
      'bundle' => 'user', 
      // If you don't set the "required" property then the field wont be required by default.
      'required' => TRUE,
      'settings' => array(
        // Here you inform either or not you want this field showing up on the registration form.
        'user_register_form' => 1,
      ),
      'widget' => array(
        'type' => 'textfield',
      ), 
    );
    field_create_instance($instance);
  }
}
Francisco Luz
fonte
3
Isso deve ser implementado em hook_install ().
revagomes
Se tudo o que você deseja fazer é adicionar um novo campo a um tipo de conteúdo existente e, a partir daí, continuar no back-end, essa abordagem é totalmente adequada. Ative o módulo, desative-o, pronto. O novo campo está lá, editável, o módulo pode ser excluído.
Leymannx
8

Se você precisar criar / excluir rapidamente campos de um Tipo ou Entidade de conteúdo existente, sem usar a interface do usuário nem a programação, poderá usar estes comandos Drush pouco conhecidos:

drush field-create <bundle(for nodes)> <field_name>,<field_type>,[widget_name] --entity_type: Tipo de entidade (por exemplo, nó, usuário, comentário). O padrão é o nó.

Por exemplo: crie dois novos campos para o artigo:

drush field-create article city,text,text_textfield subtitle,text,text_textfield

Outros comandos:

drush field-delete <field_name> [--bundle] [--entity_type]
drush field-info [field | types]
drush field-update <field_name> Return URL for field editing web page.
drush field-clone <source_field_name> <dst_field_name>
Interdruper
fonte
4

Conforme indicado por outras pessoas, você pode usar as funções da API de campo na implementação hook_install () do seu módulo para criar campos e suas instâncias para o seu tipo de conteúdo. Consulte o node_example_install () para exemplo de uso da função.

Outra solução é usar o módulo Recursos . Os recursos podem exportar vários componentes do site para codificar em um módulo. Os tipos e campos de conteúdo estão entre esses exportáveis. Você pode gerar um módulo de Recursos e substituir o código existente. Os Recursos farão o possível para evitar a quebra do código. Ou você pode gerar um módulo fictício e copiar. / Cole o código relacionado aos campos no seu módulo. Isso requer um entendimento básico de como os Recursos funcionam.

Pierre Buyle
fonte
3

No seu arquivo de instalação, você precisará definir o 'hook_install' e o 'hook_uninstall'. Exemplo incluído, mas leia tudo sobre as chaves extras nas referências da API (o código não foi testado, portanto pode haver erros de digitação).

No hook_installvocê pode adicionar os campos usando:

field_create_field , Esta função cria um modelo para um campo.

field_create_instance Pode ser usado após a criação do campo para adicioná-lo ao content_types (também conhecido como bundles).

OBSERVAÇÃO Os nomes dos vários tipos de campos podem ser encontrados nos módulos que os geram (é a chave do item da matriz em hook_field_info). Você pode encontrar todos os módulos de implementação de campo principal na pasta modules / field / modules.

As configurações também podem ser derivadas dos módulos de campo. As configurações definidas em field_create_fieldsão as de todo o site. Os que você define field_instance_createsão os específicos do node_type

    MY_MODULE_install(){
      // Generate the base for the field
      $field = array( 
        'field_name' => 'FIELD_MACHINE_NAME', 
        'type' => 'FIELD_TYPE' // See note above for what to put here
      );
      // Instance 
      $instance = array(
        'field_name' => 'FIELD_MACHINE_NAME', 
        'entity_type' => 'node', 
      ); 

      // Create instances of the field and add them to the content_types
      $node_types = node_type_get_types(); 
      foreach($node_types as $node_type){
         $instance['bundle'] = $node_type->type; 
         field_create_instance($instance); 
      }
    }

No hook_uninstall

field_delete_instance e field_delete_field podem ser usados ​​para removê-los novamente. field_delete_fieldÉ chamado automaticamente se você excluir a última instância (normalmente).

    MY_MODULE_uninstall(){
      $node_types = node_type_get_types(); 
      foreach($node_types as $node_type){
        if($instance = field_info_instance('node', 'FIELD_MACHINE_NAME', $node_type->type)) {
          field_delete_instance($instance);
        }
      }
    }
Suranga Panagamuwa Gamage
fonte
2

Recentemente, tive uma necessidade semelhante de um projeto, eis como eu o abordei, espero que ajude alguém.

Basicamente, você criará os campos necessários usando a interface do usuário dos campos, exportará para o código e os incluirá em seu módulo personalizado. Você precisará do módulo Devel ativado.

Eu também criei um Gist com esta informação.

Aqui vamos nós....

  1. Crie os campos necessários, usando a interface do usuário Drupal usual.
  2. No mesmo site, vá para example.com/devel/php
  3. Cole o seguinte código na caixa de texto "PHP code to execute".
  4. Defina as 3 primeiras variáveis ​​e clique em executar

    $entity_type = 'node';    
    $field_name = 'body';    
    $bundle_name = 'article'; 
    
    $info_config = field_info_field($field_name);
    $info_instance = field_info_instance($entity_type, $field_name, $bundle_name);
    unset($info_config['id']);
    unset($info_instance['id'], $info_instance['field_id']);
    include_once DRUPAL_ROOT . '/includes/utility.inc';
    $output = "\$fields['" . $field_name . "'] = " . drupal_var_export($info_config) . ";\n";
    $output .= "\$instances['" . $field_name . "'] = " . drupal_var_export($info_instance) . ";";
    drupal_set_message("<textarea rows=30 style=\"width: 100%;\">" . $output . '</textarea>');
    
  5. Você receberá 2 matrizes, algo assim, espero que com todas as propriedades preenchidas.

$fields['field_some_field'] = array(
  'properties of the field'
);

$instances['field_some_field'] = array(
  'properties of the instance'
);

Agora adicione o seguinte código ao seu arquivo .install. Substitua todas as instâncias do mymodule pelo nome real do módulo. Cole o código da saída devel nos _mymodule_field_data e _mymodule_instance_data, conforme observado nas respectivas funções abaixo. Você pode fazer isso para quantos campos quiser, basta colocar todas as matrizes $ fields na função _mymodule_field_data e todas as instâncias $ na função _mymodule_instance_data.

function mymodule_install() {

  // Create all the fields we are adding to our entity type.
  // http://api.drupal.org/api/function/field_create_field/7
  foreach (_mymodule_field_data() as $field) {
    field_create_field($field);
  }

  // Create all the instances for our fields.
  // http://api.drupal.org/api/function/field_create_instance/7
  foreach (_mymodule_instance_data() as $instance) {
    field_create_instance($instance);
  }
}

// Create the array of information about the fields we want to create.
function _mymodule_field_data() {
  $fields = array();
  // Paste $fields data from devel ouput here.
  return $fields;
  }

// Create the array of information about the instances we want to create.
function _mymodule_instance_data() {
  $instances = array();
  // Paste $instances data from devel output here.
  return $instances;
}
John Laine
fonte
h / t steindom.com/articles/…
MikeNGarrett 10/10
0

Você também pode considerar usar o módulo Recursos para criar os campos no momento da instalação.

Como o Features gera código para os campos, uma opção é usar o módulo Feature para gerar o código em um módulo fictício e depois copiar e colar no arquivo .install do módulo.

O benefício é que o módulo não depende do módulo Recursos em seu ambiente de destino.


fonte
11
O Altough Features é uma boa maneira de exportar campos para código, não é assim que se usa o Features. Os recursos não usam o CRUD da API do campo para criar campos a partir do .install gerado.
Pierre Buyle
0

Você pode usar o código do módulo da empresa personalizado fornecido abaixo para criar programaticamente um tipo de conteúdo com seus vários campos.

Você pode adicionar esse código em um arquivo .install do seu módulo personalizado. Ele adiciona programaticamente um tipo de conteúdo chamado "empresa" e seus vários tipos de campos (texto, numérico, data (nota: você precisará instalar o módulo Data, pois o campo Data não é fornecido por padrão), imagem, lista).

Também adicionei o código de desinstalação que removerá o tipo de conteúdo "empresa" junto com todos os seus campos e dados quando você desinstalar o módulo 'customcompanymodule'.

Você pode modificar / remover esses campos conforme suas necessidades:

function customcompanymodule_install() {
     $t = get_t();
     node_types_rebuild();
     $company = array(
    'type' => 'company',
    'name' => $t('Company'),
    'base' => 'node_content',
    'module' => 'node',
    'description' => $t('Content type to handle companys.'),
    'body_label' => $t('Company Description'),
    'title_label' => $t('Company Title'),
    'promote' => 0,
    'status' => 1,
    'comment' => 0,
);
$content_type = node_type_set_defaults($company);

node_type_save($content_type);

foreach (_company_installed_fields() as $field) {
    field_create_field($field);
}

foreach (_company_installed_instances() as $instance) {
    $instance['entity_type'] = 'node';
    $instance['bundle'] = 'company';
    field_create_instance($instance);
}

$weight = db_query("SELECT weight FROM {system} WHERE name = :name",    array(':name' => 'categories'))->fetchField();
db_update('system')->fields(array(
            'weight' => $weight + 1,
        ))
        ->condition('name', 'company')
        ->execute();
}

function _company_installed_fields() {
$t = get_t();
$fields = array(
    'company_startdate' => array(
        'field_name' => 'company_startdate',
        'label' => $t('Company Start Date'),
        'cardinality' => 1,
        'type' => 'datetime',
        'module' => 'date',
        'settings' => array(
            'granularity' => array(
                'month' => 'month',
                'day' => 'day',
                'hour' => 'hour',
                'minute' => 'minute',
                'year' => 'year',
                'second' => 0,
            ),
            'tz_handling' => 'site',
            'timezone_db' => 'UTC',
            'cache_enabled' => 0,
            'cache_count' => '4',
            'todate' => 'required',
        ),
    ),
    'company_totalwinners' => array(
        'field_name' => 'company_totalwinners',
        'label' => $t('Maximum Company Winners'),
        'cardinality' => 1,
        'type' => 'number_integer',
        'module' => 'number',
        'settings' => array(
            'max_length' => 10000,
        ),
    ),
    'company_minwinner' => array(
        'field_name' => 'company_minwinner',
        'label' => $t('Minimum Entries for Company to Activate'),
        'cardinality' => 1,
        'type' => 'number_integer',
        'module' => 'number',
        'settings' => array(
            'max_length' => 10000,
        ),
    ),
    'company_totalentries' => array(
        'field_name' => 'company_totalentries',
        'label' => $t('Company Total Entries'),
        'cardinality' => 1,
        'type' => 'number_integer',
        'module' => 'number',
        'settings' => array(
            'max_length' => 10000,
        ),
    ),
    'company_points' => array(
        'field_name' => 'company_points',
        'label' => $t('Company Points'),
        'cardinality' => 1,
        'type' => 'number_integer',
        'module' => 'number',
        'settings' => array(
            'max_length' => 10000,
        ),
    ),
    'company_image' => array(
        'field_name' => 'company_image',
        'label' => $t('Image'),
        'cardinality' => 1,
        'type' => 'image',
        'settings' => array(
            'default_image' => 0,
            'uri_scheme' => 'public',
        ),
    ),
    'company_description' => array(
        'field_name' => 'company_description',
        'label' => $t('Company Description'),
        'cardinality' => 1,
        'type' => 'text',
        'module' => 'text',
        'length' => '255'
    ),
    'company_winner' => array(
        'field_name' => 'company_winner',
        'label' => $t('Company Description'),
        'cardinality' => 1,
        'type' => 'text',
        'module' => 'text',
        'length' => '255'
    ),
    'field_autowinnerselection' => array(
        'field_name' => 'field_autowinnerselection',
        'label' => $t('Auto Company Winner Selection'),
        'type' => 'list_boolean',
        'module' => 'list',
        'active' => '1',
        'locked' => '0',
        'cardinality' => '1',
        'deleted' => '0'
    ),
);
return $fields;
}

function _company_installed_instances() {
$t = get_t();
$instances = array(
    'company_startdate' => array(
        'field_name' => 'company_startdate',
        'label' => $t('Company Lifespan'),
        'cardinality' => 1,
        'widget' => array(
            'type' => 'date_popup',
            'module' => 'date',
            'settings' => array(
                'input_format' => 'm/d/Y - H:i:s',
                'input_format_custom' => '',
                'year_range' => '-3:+3',
                'increment' => '15',
                'label_position' => 'above',
                'text_parts' => array(),
            ),
        ),
    ),
    'company_totalwinners' => array(
        'field_name' => 'company_totalwinners',
        'label' => $t('Maximum Company Winners'),
        'cardinality' => 1,
        'widget' => array(
            'type' => 'number',
            'module' => 'number',
            'settings' => array('size' => 60),
        ),
    ),
    'company_minwinner' => array(
        'field_name' => 'company_minwinner',
        'label' => $t('Minimum Number of Entries for Company to Activate'),
        'cardinality' => 1,
        'required' => 1,
        'widget' => array(
            'type' => 'number',
            'module' => 'number',
            'settings' => array('size' => 60),
        ),
    ),
    'company_totalentries' => array(
        'field_name' => 'company_totalentries',
        'label' => $t('Company Total Entries'),
        'cardinality' => 1,
        'required' => 1,
        'widget' => array(
            'type' => 'number',
            'module' => 'number',
            'settings' => array('size' => 60),
        ),
    ),
    'company_points' => array(
        'field_name' => 'company_points',
        'label' => $t('Company Points'),
        'cardinality' => 1,
        'required' => 1,
        'widget' => array(
            'type' => 'number',
            'module' => 'number',
            'settings' => array('size' => 60),
        ),
    ),
    'company_image' => array(
        'field_name' => 'company_image',
        'label' => $t('Image'),
        'cardinality' => 1,
        'required' => 1,
        'type' => 'company_image',
        'settings' => array(
            'max_filesize' => '',
            'max_resolution' => '213x140',
            'min_resolution' => '213x140',
            'alt_field' => 1,
            'default_image' => 0
        ),
        'widget' => array(
            'settings' => array(
                'preview_image_style' => 'thumbnail',
                'progress_indicator' => 'throbber',
            ),
        ),
        'display' => array(
            'default' => array(
                'label' => 'hidden',
                'type' => 'image',
                'settings' => array('image_style' => 'medium', 'image_link' => ''),
                'weight' => -1,
            ),
            'teaser' => array(
                'label' => 'hidden',
                'type' => 'image',
                'settings' => array('image_style' => 'thumbnail', 'image_link' => 'content'),
                'weight' => -1,
            ),
        ),
    ),
    'company_description' => array(
        'field_name' => 'company_description',
        'label' => $t('Company Description'),
        'cardinality' => 1,
        'widget' => array(
            'weight' => '-3',
            'type' => 'text_textfield',
            'module' => 'text',
            'active' => 1,
            'settings' => array(
                'size' => '1000',
            ),
        ),
    ),
    'company_winner' => array(
        'field_name' => 'company_winner',
        'label' => $t('Company Winner'),
        'cardinality' => 1,
        'widget' => array(
            'weight' => '-3',
            'type' => 'text_textfield',
            'module' => 'text',
            'active' => 1,
            'settings' => array(
                'size' => '60',
            ),
        ),
    ),
    'field_autowinnerselection' => array(
        'field_name' => 'field_autowinnerselection',
        'required' => 1,
        'label' => $t('Auto Company Winner Selection'),
        'widget' => array(
            'weight' => '-3',
            'type' => 'options_buttons',
            'module' => 'options',
            'active' => 1,
            'settings' => array(),
        ),
    ),
);
return $instances;
}

function customcompanymodule_uninstall() {
$content_types = array(
    'name1' => 'company',
);
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type1';
$result = db_query($sql, array(':type1' => $content_types['name1']));
$nids = array();
foreach ($result as $row) {
    $nids[] = $row->nid;
}
node_delete_multiple($nids);
node_type_delete($content_types['name1']);
field_purge_batch(1000);
}
Nadeem Khan
fonte