Come rimuovere a livello di programmazione un campo da un nodo?


16

Come si rimuove un campo da un nodo a livello di codice? Ho una migrazione inhook_update_N che sposta i contenuti da un campo a una tabella personalizzata. Dopo quella migrazione, voglio rimuovere il campo con quella stessa funzione.

Esistono API di campo che soddisfano la rimozione di campi?

Modifica, soluzione : poiché le risposte mancano del codice effettivo, ecco cosa ho fatto per spostare i campi dai $ utenti nei miei record e successivamente rimuovere il campo dal database;

function my_module_update_7005(&$sandbox) {
  $slice = 100;
  //Fetch users from database;
  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['current_uid'] = 0;
    // We'll -1 to disregard the uid 0...
    $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
  }
  if (empty($users)) {
    $sandbox["current_uid"] += $slice;
  }
  $users = db_select('users', 'u')
    ->fields('u', array('uid', 'name'))
    ->condition('uid', $sandbox['current_uid'], '>')
    ->range(0, $slice)
    ->orderBy('uid', 'ASC')
    ->execute();
  //Loop trough users;
  foreach ($users as $user) {
    $foo = new Foo();
    // Warning: drupal's fields return mixed values; e.g. NULL versus an int.
    $foo->debits = (int) $user->user()->field_credits["und"][0]["value"];
    $foo->save();

    $sandbox['progress']++;
    $sandbox['current_uid'] = $user->uid;
  }

  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);

  // Remove the field.
  field_delete_field("field_credits"); //note that the name for Foo is field_foo
  field_purge_batch($sandbox['max']+1);//Drupal seems to have an offbyone problem.
}

Risposte:


29

field_delete_field($field_name)segnerà $field_nameper la cancellazione alla prossima esecuzione cron.

È possibile utilizzare field_purge_batchper eseguire l'eliminazione, se non si desidera farlo durante l'esecuzione cron.

EDIT: field_delete_field() dovrebbe essere usato quando è necessario eliminare il campo anche da altri bundle. Se desideri eliminare il campo solo da un determinato pacchetto, dovresti utilizzare field_delete_instance()come indicato da @Clive.


4
Attento, questo rimuoverà anche il campo da qualsiasi altro pacchetto a cui potrebbe essere collegato :) Buono a sapersi field_purge_batchperò
Clive

@Clive: giusto, eliminerà il campo da tutti i pacchetti. Grazie per aver corretto :) Ho modificato la risposta.
AjitS

Volevo rimuovere completamente il campo, cioè da tutti i pacchetti. Ma l'avvertimento è buono. Grazie.
Berkes,

1
field_delete_instance () è la strada da percorrere.
Ryan McVeigh,

field_purge_batch () in realtà eliminerà solo tutti gli elementi del campo quanti sono le dimensioni del batch che gli vengono passate. Questo può essere d'aiuto quando il campo ha solo pochi elementi, in modo da eliminare completamente l'istanza del campo, non è necessario attendere che cron lo ripulisca. Se hai molti valori nel campo, non essere tentato di aumentare le dimensioni del batch troppo in alto (il "batch" nel nome non significa che farà alcun batch stesso, significa solo che fa un singolo batch di tutti gli articoli a cui lo chiedi); potresti finire per imbatterti nella memoria PHP o nei limiti di tempo.
Eelke Blok,

24

Per rimuovere un campo da un particolare pacchetto è possibile utilizzare field_delete_instance()

Contrassegna un'istanza di campo e i suoi dati per l'eliminazione.

Esempio:

function my_module_update_7001() {
  if ($instance = field_info_instance('node', 'field_name', 'page'))  {
    field_delete_instance($instance, TRUE);
    field_purge_batch(1);
  }
}

Per rimuovere completamente un campo dal sistema, è possibile utilizzare field_delete_field()

Contrassegna un campo e le sue istanze e i dati per l'eliminazione.

Esempio:

function my_module_update_7001() {
  field_delete_field('field_name');
  field_purge_batch(1);
}

I campi / istanze sono contrassegnati solo per l'eliminazione, i dati verranno effettivamente eliminati durante le successive esecuzioni cron. Per eliminarlo manualmente eseguire:

field_purge_batch(1);

1
Mentre chiama field_delete_field()e field_purge_batch()funziona, mantiene i record in field_config_instancee field_config. Perché?
Berkes,

Non capisco perché la chiamata a field_purge_batch con un valore di 1 eliminerà tutti i dati del campo. Se capisco correttamente il codice, ottiene i dati del campo per le entità $ batchsize e lo lascia a quello (cioè non chiama la funzione ricorsivamente o altro); sembra che spetti al chiamante verificare se tutti i dati sono spariti e, in caso contrario, continuare a chiamare la funzione. Ma forse sto fondamentalmente fraintendendo qualcosa.
Eelke Blok,

In realtà, questo commento in field_ui.admin.inc spiega molto: // I campi vengono eliminati su cron. Tuttavia, il modulo di campo impedisce la disabilitazione dei moduli // quando i tipi di campo forniti vengono utilizzati in un campo fino a quando non vengono completamente // eliminati. Nel caso in cui un campo abbia un contenuto minimo o assente, una singola chiamata // a field_purge_batch () lo rimuoverà dal sistema. Chiamalo con un limite di batch // basso per evitare che gli amministratori debbano attendere l'esecuzione di cron quando // rimuovono le istanze che soddisfano questi criteri.
Eelke Blok,

@Clive, mi fido del tuo consiglio praticamente implicitamente, ma non riesco a capire quanto mi sembra strano avere una dichiarazione in una condizione if. È apposta? Mi riferisco a $instance = field_info_instance('node', 'field_name', 'page'). Non dovrebbe invece essere $instance = field_info_instance('node', 'field_contact', 'job');e quindi rilasciare l'istruzione if?
cdmo,

1
@cdmo si chiama "assegnazione in condizione", e sì, ha dei problemi . Ma Drupal core lo usa liberamente, anche nell'ultima versione, quindi ha almeno un precedente. Ad essere sincero, questo è stato 5 anni fa e ora sono un po 'più saggio, o non lo uso, o se per qualsiasi motivo lo farò, concluderò l'incarico (ad esempio, if ( ($foo = $bar) ) {quindi l'intenzione è ovvia e il potenziale per errore è limitato. L'istruzione if è necessaria perché field_delete_instancenon controlla null
Clive

5

Per rispondere alla domanda @berkes:

field_delete_field()contrassegna il campo per l'eliminazione, provocando la sua eliminazione alla successiva esecuzione cron. Tuttavia lo fa dati aspettativa per field_config_instancequanto riguarda il campo di caduta. Eseguendo cron o field_purge_batch()non rimuoverai questi dati dalla field_config_instancetabella, anche se la colonna eliminata è impostata su1 per il campo.

Per me l'utilizzo field_delete_instance()seguito da un field_purge_batch()per ogni campo rimosso ha funzionato - rimuovendo immediatamente entrambi i campi dal database (senza richiedere cron), nonché eliminando ilfield_config_instance tabella di tutti i dati dei campi (per il campo eliminato).

Ecco la soluzione:

/**
 * Implements hook_uninstall().
 */
function hook_uninstall() {
  // Delete all fields for all xyz entity bundles.

  // Retrieve all bundles for an entity.
  $bundles = field_info_bundles('XYZ'); // The name of your entity type, for example, 'node'.
  foreach ($bundles as $bundle => $properties) {

    // Retrieve all the fields for a given bundle.
    $instances = field_info_instances('XYZ', $bundle);
    foreach ($instances as $instance) {
      field_delete_instance($instance, TRUE);
      field_purge_batch(1);
    }
  }
}

Nota TRUEon field_delete_instance(), poiché indica che l'API di campo deve eseguire operazioni di pulizia.


Come usare questo codice? Voglio eliminare il campo del titolo da un tipo di contenuto
Umair l'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.