Qual è il concetto di base dietro i ganci?


120

Sono intermedio in PHP. Per perfezionare le mie capacità, inizio a studiare Drupal 7. Durante l'apprendimento dei concetti di architettura di Drupal, i termini hook e bootstrap mi hanno sconcertato molto. Ho letto il libro "Pro Drupal development" e alcuni documenti su drupal.org, ma è così avanzato per me imparare come funzionano gli hook in Drupal per visualizzare la pagina web.

Qualcuno può dirmi quali ganci sono in parole semplici?

Risposte:


107

Le altre risposte sono fantastiche, precise, dettagliate, ma non sono sicuro che siano le "semplici parole" che spiegano le ossa nude del concetto che il ricercatore stava cercando.

Penso agli hook come a un punto in cui il codice si interrompe e grida " Qualcun altro ha qualcosa da aggiungere qui? ". Qualsiasi modulo può avere una funzione che risponde a questa e viene attivato con i dati appropriati passati ad esso in quel punto del codice.

Un bell'esempio semplice è hook_node_delete () . Qualsiasi modulo può usarlo per far accadere le cose ogni volta che un nodo viene eliminato. I documenti ti dicono che questo hook passa il modulo con cui l'oggetto del nodo eliminato deve lavorare e delinea altre informazioni utili come il momento esatto in cui viene chiamato (ad esempio che è prima che i dati del nodo vengano effettivamente eliminati dal database) e dove nel codice di Drupal viene chiamato l'hook (che può essere più di un posto).

Puoi esplorare quali hook esistono e scoprire quali dati vengono passati esplorando le cose che iniziano con "hook_" nell'API di Drupal .

Gli hook funzionano secondo le convenzioni di un nome: usando hook_node_deletecome nostro esempio, quando il processo di eliminazione del nodo raggiunge il punto in cui viene chiamato l'hook, per ogni modulo con una funzione come questa in [modulename]_node_delete()cui la parola hook nel nome dell'hook viene sostituita con il nome del modulo (es. my_amazing_module_node_delete()), tali funzioni vengono chiamate.

Perché? Quindi qualsiasi modulo può fare qualsiasi cosa in questi punti chiave: ad esempio puoi guardare il nodo cancellato e fare le cose se soddisfa una certa condizione (ad esempio, invia un'email a un amministratore o avvia un lungo processo).

Alcuni hook consentono di modificare le cose che sono state generate appena prima che vengano elaborate. Ad esempio, hook_menu_alter () passa le voci di menu correnti che il sistema ha generato. Qualsiasi modulo può definire una funzione some_modulename_menu_alter () e guardarli, opzionalmente cambiarli (cancellarne alcuni, aggiungerne alcuni, ordinarli ...) e reinserire il menu appena modificato.

È semplice, davvero potente ed è al centro di come Drupal funziona come un sistema modulare. Le implementazioni di hook sono al centro della maggior parte dei moduli Drupal.

Quando si guarda attraverso il codice di un modulo Drupal, è possibile individuare quali funzioni provengono da hook (al contrario di funzioni che sono semplicemente chiamate all'interno del codice del modulo stesso), poiché la comunità Drupal applica una convenzione in base alla quale ogni implementazione di un hook ha un commentalo in questo modo (osserva il bit "Implements hook _..."):

/**
 * Implements hook_some_hook().
 *
 * Some descriptive summary of what this does
 */
function my_amazing_module_some_hook() {

Alcuni moduli che fungono da API definiscono i propri hook. Ad esempio, Views definisce molti hook che consentono di aggiungere, leggere e modificare i dati in vari punti del processo di creazione o visualizzazione di una vista. Puoi trovare informazioni sugli hook creati nei moduli personalizzati da due punti (supponendo che il modulo segua le convenzioni, ecc.):

  • Il codice e i commenti nel modulename.api.phpfile nella cartella del modulo
  • drupalcontrib.org - ad esempio, ecco il loro elenco di moduli D7 su cui hanno informazioni, ed ecco la loro pagina di hook di Views

Il bootstrap è, come hanno spiegato altri, sostanzialmente in fase di avvio: non duplicherò le altre buone spiegazioni chiare.


53

Hook, sono per lo più implementazioni dei modelli Visitor e Observer .

Una delle implementazioni di hook più comuni è hook_menu , che consente ai moduli di registrare nuovi percorsi all'interno di un sistema Drupal.

function my_module_menu() {
  return array('myawesomefrontpage' => array(
    'page callback' => 'function_that_will_render_frontpage'
  ));
}

Un modello molto frequente in Drupal è avere un [DATATYPE]_infogancio e un [DATATYPE]_info_altergancio. Se vuoi creare un nuovo tipo di campo, implementerai il relativo field_info -hook e se vuoi manipolarne uno esistente, implementerai il corrispondente field_info_alter -hook.

Modifica: Come sottolinea Chx nei commenti, il modello di osservatore è orientato agli oggetti , mentre Drupal 7 non lo è ancora. Esiste tuttavia una pagina wiki, la programmazione Drupal da una prospettiva orientata agli oggetti (creata da JonBob il 4 aprile 2005), che spiega come Drupal utilizzi schemi di codici orientati agli oggetti nonostante ciò. È interessante notare che menziona gli osservatori, ma non i visitatori.

Nota su Drupal 8 Questo è ancora piuttosto presto ed è soggetto a modifiche, ma voglio aggiungere che mentre gli hook sono stati per un po 'lo standard di fatto nell'aggiunta di funzionalità a Drupal, il concetto di plugin diventerà molto più visibile in Drupal 8, e ci fornirà nuovi modi di interagire con Core. Problema rilevante e documentazione .


2
Non lasciarti confondere dai motivi di design OOP. Questo non è uno. I ganci Drupal sono AOP. Vedi sotto.

@chx, mentre ammetto liberamente che lo sai meglio di me :) e la tua risposta è corretta (ho votato a favore) non lo interpreto come una mia risposta sbagliata. :) Se non sei d'accordo, vorrei sapere come ho frainteso entrambi i modelli della loro implementazione.
Letharion,

4
Wikipedia: "Il modello di osservatore è un modello di progettazione software in cui un oggetto, chiamato soggetto, mantiene un elenco dei suoi dipendenti, chiamati osservatori" qui non vi sono osservatori di oggetti. Il visitatore è più oscuro ma si applica lo stesso principio generico: ciò che non è OOP non può avere schemi OOP.

33

In parole povere, gli hook sono una sorta di bridge che consente ai moduli di interagire tra loro, alterare la struttura e i dati reciproci, fornire nuovi dati ecc.

Nella maggior parte dei casi, la parola hook_nei nomi delle funzioni viene sostituita dal nome del modulo e ciò consente al modulo di accedere alle operazioni di un altro modulo. Ad esempio un modulo core drupal chiamato "nodo" invoca vari hook. Uno di questi è quello hook_node_updateche viene invocato ogni volta che un nodo esistente viene aggiornato. Quando viene richiamato questo hook, viene chiamata l' mymoduleimplementazione del modulo (diciamo che lo chiamiamo ) hook_node_update, che in questo caso sarà una funzione nel file .module del modulo chiamato mymodule_node_update(Ovviamente questa funzione può essere in qualsiasi file nella cartella del modulo purché è incluso anche nel file .module). A questo hook verranno inoltre passati i parametri necessari (variabili) che può utilizzare, modificare e / o tornare alla funzione che ha invocato l'hook.

Quando ho iniziato a studiare Drupal, mi trovavo nella stessa barca in cui sei adesso, all'inizio è un po 'difficile da capire, ma una volta capito, è davvero così semplice e intuitivo. In bocca al lupo.


1
grazie per la tua risposta. Mi aiuti così tanto. puoi per favore dire qual è il concetto di bootstrap in drupal e come vengono trattati gli hook in bootstrap in parole semplici mentre spieghi la risposta precedente ..
GiLL

@Bayasa, inserisci qui i tuoi pensieri. Sto solo aggiungendo il mio. Puoi pensare al boostrtapping come all'avvio del tuo computer. Drupal ha molte API, tra cui database, file e moduli. Questi sono basati su una "piattaforma". Durante l'avvio, Drupal definisce queste funzioni e le altre impostazioni (connessione al database, cartelle di file, ecc.) In modo che il resto del sistema possa continuare dal resto.
AyeshK,

32

Qualche tempo fa uno degli sviluppatori principali ha scritto un articolo intitolato "Programmazione Drupal da una prospettiva orientata agli oggetti" . Fa un buon lavoro nel spiegare come si possano pensare ai ganci come implementare molti dei modelli di progettazione comuni . La migliore spiegazione degli ami viene dall'articolo:

Il sistema di hook di Drupal è la base per la sua astrazione dell'interfaccia. I hook definiscono le operazioni che possono essere eseguite su o da un modulo. Se un modulo implementa un hook, stipula un contratto per eseguire una determinata attività o restituire un particolare tipo di informazioni quando viene richiamato l'hook. Il codice chiamante non ha bisogno di sapere nulla sul modulo o sul modo in cui viene implementato l'hook per ottenere un utile lavoro invocando l'hook.


1
Ho corretto la paternità di quell'articolo secondo drupal.org/node/19964

@chx, grazie. Sto pensando di eliminare questa risposta ora. L'ho pubblicato in b / c. Facevo molto lavoro OO in C semplice e mi sono abituato ai concetti OO senza oggetti reali. Tuttavia, hai ragione sulla relazione pointcut / weaver. Non sono sicuro, tuttavia, se la citazione sia una descrizione accurata di un aspetto (ignorando la parte "astrazione dell'interfaccia").
mpdonadio

21

Bootstrap è il processo che Drupal attraversa per creare una pagina, fondamentalmente in esecuzione su tutto il core, il tema e il codice del modulo in ordine.
È fondamentalmente come Drupal si avvia e si prepara a fare il suo lavoro come CMS.

È intelligente, in quanto ci consente di mettere gli hook ovunque nei nostri moduli e temi, e il processo bootstrap assicura che vengano eseguiti al punto giusto.
Ad esempio, se si utilizza "hook_form_alter" per aggiungere una casella di controllo personalizzata a un modulo, il bootstrap di Drupal si accerterà che esegua quel codice, appena prima di renderizzare il modulo.

Un problema con il bootstrap è che l'esecuzione dell'intero processo richiede tempo, anche se si restituisce solo una piccola quantità di dati. Quando si utilizza Drupal con il modulo servizi come API e si restituiscono molte piccole risposte XHTML o JSON, l'esecuzione dell'intero bootstrap non è molto performante. Alcune persone intelligenti stanno cercando modi intelligenti per aggirare Drupal 8.

Ma per il rendering delle normali pagine Drupal, il processo di bootstrap funziona benissimo, utilizza il sistema di cache Drupals per velocizzare le cose e ti dà il controllo totale su ogni parte del tuo sito. Se trovi il tuo sito lento, puoi sempre usare qualcosa come APC o MemCached per velocizzare le cose.

Spero che la mia risposta sia stata precisa e spieghi le cose semplicemente per te, non sono un esperto, ma penso che funzioni così.


15

Bootstrap è il processo durante il quale Drupal si inizializza; il processo include effettivamente:

  • Impostazione dell'errore e dei gestori delle eccezioni
  • Inizializzazione del valore di alcune variabili spec-global contenute in $_SERVER
  • Inizializzazione di alcune variabili con init_set()
  • Trovare la versione cache della pagina da pubblicare
  • Inizializzazione del database
  • Impostazione dei gestori che caricano i file quando non viene trovata una classe o un'interfaccia
  • Inizializzazione delle variabili Drupal
  • Inizializzazione della sessione PHP
  • Inizializzazione della variabile lingua
  • Caricamento dei moduli abilitati

Alcune delle operazioni che ho descritto sono specifiche per Drupal 7 o versioni successive, ma la maggior parte delle operazioni sono indipendenti dalla versione di Drupal.

Un hook è una funzione PHP che può essere chiamata da Drupal o moduli di terze parti, quando necessario per eseguire un'attività. Invece di avere un elenco prefissato di funzioni da chiamare, l'elenco viene compilato controllando i moduli abilitati e le funzioni che implementano.
Ad esempio, Drupal usa hook_node_update(); quando un nodo viene salvato con node_save () , viene eseguito il seguente codice.

// Call the node specific callback (if any). This can be
// node_invoke($node, 'insert') or
// node_invoke($node, 'update').
node_invoke($node, $op);

Cosa fa node_invoke () è il seguente:

  • Ottenere l'elenco di tutti i moduli abilitati
  • Verifica se i moduli abilitati hanno una funzione il cui nome termina in "_node_update" e inizia con il nome breve del modulo
  • Chiamando quella funzione, passando $nodecome parametro

Gli hook possono salvare i propri dati in un database o modificare il valore restituito da una funzione. L'ultimo caso è, ad esempio, ciò che accade con hook_form_alter () , che modifica il valore di $formpassato come riferimento a drupal_prepare_form () .

Gli hook Drupal sono generalmente invocati usando tre funzioni:

drupal_alter()è la funzione usata per invocare hook specifici il cui scopo è quello di modificare i dati passati come riferimento, come hook_form_alter () , hook_hook_info_alter () e hook_tokens_alter () .

Esistono altre funzioni che vengono utilizzate per richiamare hook, ad esempio node_invoke(), ma quelle funzioni utilizzano essenzialmente una delle funzioni che ho elencato prima.


12

I ganci sono tagli di punti ed module_invoke_allè il tessitore (purtroppo non siamo chiari nell'implementazione e ci sono altre funzioni di tessitura). Per quanto ne so, Drupal è l'unico sistema per implementare AOP con funzioni PHP.

Vedi un'altra spiegazione su Come funziona AOP in Drupal?


Pensi che l'articolo di jhodgdon (menzionato nella mia risposta) sia accurato?
mpdonadio

2
Questo è l'articolo di Jonbob del 2005, l'attribuzione è sbagliata. Ne discuterei, sì.

6

Se vuoi vedere gli hook che Drupal ti consente di chiamare, vai su api.drupal.org , vai alla casella di ricerca e digita 'hook_'. Questo ti darà un grande elenco della maggior parte degli hook definiti da Drupal. Fai la stessa cosa per "_alter" e vedi ancora di più.

La pagina Hook dell'API Node offre un elenco cronologico di tutti gli hook richiamati durante le operazioni del nodo. Puoi vedere il modulo Node e i sistemi Entity and Field che si scambiano invocazioni a turno.

Ad esempio, se scorri verso il basso e osservi la sezione per node_load(): Il modulo Node ti darà un hook_load (), quindi passerà il controllo al sistema di entità che carica alcuni campi. Esistono molti hook di campo non elencati, quindi quando viene richiamato il sistema di entità hook_entity_load(), prima di passare il controllo al Nodo che invoca hook_node_load().

Questo dà al tuo codice la possibilità di agire sul nodo in questione mentre viene caricato, pezzo per pezzo. Imparare questi hook e quando e perché vengono chiamati fa parte dell'avventura della programmazione Drupal. :-)

Anche altri sistemi hanno ganci. Come hook_init()e hook_boot(). Questo arriva alla parte bootstrap della tua domanda. hook_boot()viene richiamato da Drupal prima che il sistema di memorizzazione nella cache sia stato caricato. Quindi, se il tuo modulo deve fare qualcosa prima che Drupal si sia davvero avviato e desideri che il tuo codice venga eseguito indipendentemente dalla memorizzazione nella cache, allora dovresti implementarlo hook_boot(). Altrimenti, se ti interessano solo le pagine che non sono memorizzate nella cache, le implementeresti hook_init().

Questo ti dà la possibilità di implementare qualcosa all'inizio del processo di caricamento, prima che Drupal si sia avviato completamente, dandoti una certa flessibilità su quale punto del processo che vuoi intercettare.

Se devi assicurarti che Drupal si sia avviato ad un certo punto prima di procedere, puoi chiamare drupal_bootstrap(). Facendo clic su tale documentazione, è possibile visualizzare i livelli di bootstrap disponibili, dal nulla a tutto.

E, infine, puoi vedere del codice ampiamente documentato per ogni dato sottosistema nel progetto Esempi .


L'OP chiede una definizione di hook, non un elenco di hook utilizzati da Drupal.
kiamlaluno

6

Gli hook sono funzioni php, elementi costitutivi basati sulle convenzioni di denominazione "yourmodulename_hookname", hanno lo scopo di facilitare la capacità degli sviluppatori di creare moduli .

I moduli sono un vero affare perché abilitano sia CORE che funzionalità personalizzate nel tuo sistema Drupal. Pertanto, i moduli sono costituiti da hook e quando un modulo viene attivato nell'installazione di Drupal, le sue funzioni hook possono essere richiamate da altri moduli grazie alla funzione module.inc module_invoke_all ($ hook) o module_invoke.

Pertanto, per comprendere correttamente cosa sono gli hook, dovresti davvero sporcarti le mani e provare lo sviluppo del modulo. A questo scopo, inizia scaricando e provando alcuni degli esempi di Drupal per sviluppatori , dovresti anche familiarizzare con la creazione dei moduli .

Ecco alcuni degli utili esempi di Drupal per gli sviluppatori sopra menzionati:

hook_block_view () esempio di implementazione nel modulo block_example

/**
 * @file examples/block_example/block_example.module line 127
 *
 * Implements hook_block_view().
 *
 * This hook generates the contents of the blocks themselves.
 */
function block_example_block_view($delta = '') {
  //The $delta parameter tells us which block is being requested.
  switch ($delta) {
    case 'example_configurable_text':
      // The subject is displayed at the top of the block. Note that it
      // should be passed through t() for translation. The title configured
      // for the block using Drupal UI supercedes this one.
      $block['subject'] = t('Title of first block (example_configurable_text)');

Questo hook ti dà accesso alla creazione di blocchi di Drupal per visualizzare blocchi personalizzati sul tuo sito web. È possibile perché block.module ha una funzione _block_render_block che consente a tutti i moduli di definire la propria vista hook_block (notare l'ultima riga di module_invoke):

/**
 * @file modules/block/block.module, line 838
 *
 * Render the content and subject for a set of blocks.
 *
 * @param $region_blocks
 *   An array of block objects such as returned for one region by _block_load_blocks().
 *
 * @return
 *   An array of visible blocks as expected by drupal_render().
 */
function _block_render_blocks($region_blocks) {
  ...
  foreach ($region_blocks as $key => $block) {
    ...
    $array = module_invoke($block->module, 'block_view', $block->delta);

hook_menu () esempio di implementazione nel modulo render_example

/**
 * @file examples/render_example/render_example.module line 22
 * 
 * Implements hook_menu().
 */
function render_example_menu() {
  ...
  $items['examples/render_example/arrays'] = array(
    'title' => 'Render array examples',
    'page callback' => 'render_example_arrays',
    'access callback' => TRUE,
  );

Questo hook è collegato al sistema di routing dell'URL di Drupal e definisce i pattern dell'URL con i callback di rendering associati utilizzati dal modulo. Viene richiamato da system.module .

Per quanto riguarda il bootstrap, in pratica, devi solo sapere che viene eseguito su ogni richiesta di pagina. Ti consiglio davvero di leggere questa risposta di StackOverflow , spiega come bootstrap e hook sono correlati ma separati.

Per quanto riguarda la visualizzazione della pagina Web, la visualizzazione html del sito Web di Drupal si ottiene principalmente con array di rendering e temi.


3

Ovunque un modulo chiama module_implements () http://api.drupal.org/api/drupal/includes%21module.inc/function/module_implements/7 Drupal lancerà tutte le funzioni correttamente nominate nell'ordine giusto in base al loro peso. Queste sono chiamate funzioni hook perché nella documentazione per i moduli che usano module_implements vedi cose come hook_menu (per quando il menu chiama tutte le funzioni progettate per restituire voci di menu). La parola "hook" deve solo essere sostituita con il nome del modulo che lo implementa e Drupal fa il resto.

Esiste anche una funzione drupal_alter () che attiva tutte le funzioni alter nominate correttamente, con l'intenzione di farti modificare cose precedentemente registrate da un altro hook.

Generalmente gli alter passeranno gli argomenti per riferimento in modo da poter modificare direttamente l'oggetto, mentre gli hook "normali" di solito ti portano a restituire cose nuove.

L'idea è che qualsiasi modulo (incluso il tuo) può essere facilmente esteso chiedendo a Drupal di chiamare tutte le funzioni di hook richieste e recuperare ciò che restituiscono per essere elaborato. Il modulo che chiama le funzioni hook non ha bisogno di sapere nulla sui moduli che implementano gli hook, e i moduli che implementano l'hook non hanno davvero bisogno di sapere nulla sul modulo che chiama hook. L'unica cosa che entrambi i moduli devono sapere è la struttura dei dati restituiti o modificati.

In pratica, i ganci sono più comunemente usati per:

  • rispondere agli eventi, come hook_user_login viene chiamato quando un utente accede
  • registra qualcosa di nuovo che può essere usato per estendere il sistema come hook_menu
  • tema / rendering HTML o compilare / convalidare / inviare moduli

1

Hai un sacco di risposte sopra, ma voglio dare una risposta in modo molto più semplice per capire il concetto di base alla base dei ganci. Gli hook sono in realtà funzioni incorporate nel core drupal per gestire cose diverse e svolto diversi lavori nel core, puoi sincronizzare le tue funzioni con queste funzioni integrate del core drupal per aggiungere la loro funzionalità nelle tue funzioni chiamando hook diversi.

Spero che otterrai il punto!


1

Per me è tutto sulla funzione module_implements quando si tratta di hook e core (D7). Una cosa che penso sia cruciale da capire è che scrivendo un hook per modificare qualcosa, non hai assolutamente l'ultima parola su ciò che accade alle strutture di dati con cui hai a che fare. Il tuo hook si inserisce semplicemente nella linea (coda) di funzioni che agiscono ANCHE sulle stesse strutture di dati, che siano menu, link_di_ menu, blocchi, nodi, utenti o qualsiasi entità o elemento di rendering.

Quindi, per vedere davvero i tuoi ganci essere utilizzati nel modo previsto, devi sapere o essere consapevole di dove tu (il tuo gancio) sei in linea. Questo è determinato dal peso del tuo campionato. Il core di Drupal chiama semplicemente i ganci correttamente nominati nell'ordine di peso crescente e qualunque cosa accada ai dati accade.

Ho già scritto ganci che non hanno avuto alcun effetto, solo per sapere dopo ore di headbanging che il mio peso del modulo era troppo leggero e che i ganci successivi stavano effettivamente facendo ciò che ho fatto o trascurando tutto insieme.

Un hook ben scritto non "manometterà" o "forzerà" se stesso ad essere l'ultimo, ma "si sistemerà bene con gli altri" assicurandosi che mantengano le strutture di dati come previsto dal resto degli hook lungo la linea.

E parlando di "The Line" di ganci. Nel corso degli anni ho trollato google per roba Drupal, questa immagine sembra essere una buona rappresentazione della lista delle possibilità di pre-elaborazione e processo.
inserisci qui la descrizione dell'immagine


1

In modo molto più semplice, gli hook aiutano lo sviluppatore a modificare la funzionalità esistente in base ai requisiti senza apportare modifiche al codice esistente. Più come la funzione astratta in php.

Esempio: è stato creato un modulo per la prenotazione di un biglietto dell'autobus. Secondo il tuo codice se il biglietto è stato prenotato una volta, la posizione di ritiro non è modificabile quale era il tuo requisito per quel progetto. Supponi che il tuo amico abbia bisogno dello stesso modulo per requisiti simili con l'eccezione che l'utente può cambiare il luogo di ritiro. In qualche modo deve usare il tuo modulo e non vuoi che faccia cambiamenti di codice. Quindi fornisci un'interfaccia (hook nel nostro caso) in cui potrebbe implementare le sue modifiche senza apportare modifiche al tuo modulo.

In drupal fino a drupal-7 abbiamo ganci per moduli e temi. Per sapere come funziona l'hook, controlla gli hook di drupal.org per creare un hook personalizzato controlla questo link


0

Ganci. Consenti ai moduli di interagire con il core Drupal. Il sistema di moduli di Drupal si basa sul concetto di "ganci". Un hook è una funzione PHP che si chiama foo_bar (), dove "foo" è il nome del modulo (il cui nome file è quindi foo.module) e "bar" è il nome dell'hook.

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.