Su GLPI 11, "il plugin si è rotto" non è quasi mai un bug del plugin: è la fondazione che è cambiata sotto di esso. Nella manutenzione di ambienti clienti il copione si ripete - il cliente porta su il nuovo core, due o tre plugin spariscono dal menu, uno fa cadere lo schermo con errore 500 e il php-errors.log resta irritantemente vuoto. Questa guida separa ciò che è diventato nativo da ciò che ha davvero smesso di funzionare, mostra il frammento di codice che boccia un plugin su 11 e consegna la checklist che eseguiamo prima di pianificare la finestra di migrazione.
Cosa è cambiato nel core - e perché fa cadere i plugin
11 non è una nuova veste sopra 10. È un cambio di motore. Ogni cambiamento qui sotto invalida uno schema che i plugin di GLPI 10 usavano senza pensarci:
- Frontend in Symfony + Twig. Il vecchio flusso procedurale (
Html::header()e poiechodi HTML) ha lasciato il posto a controller e template Twig. Un plugin che costruiva la pagina "a mano" perde l'intestazione, il menu, a volte l'intero schermo. - L'applicazione viene servita da
public/. Il routing ora è di Symfony. Gli include relativi del tipoinclude("../../../inc/includes.php")dipendono dalla directory di lavoro e smettono di risolversi. - PHP 8.2 minimo, con firme rigide. Un metodo ereditato ha bisogno del return type compatibile. Un
canCreate()senza: boollancia "Declaration must be compatible" e il plugin non si carica nemmeno. - Il driver del database rifiuta l'SQL grezzo. Questo è quello che fa più male.
$DB->query()è stato rimosso e$DB->request()con stringa letterale è bloccato ("Building and executing raw queries is prohibited"). Qualsiasi query nascosta si rompe la prima volta che quel percorso viene eseguito. - Le flag di hook.php sono diventate canoniche. Marcatori come
csrf_compliantsono trattati più rigidamente dal core; dichiarato male, il plugin può non essere riconosciuto come CSRF-compliant e prendere un 403 in POST.
In breve: "compatibile con 11" non è fortuna, è l'autore che ha portato questi schemi. Chi non ha portato si rompe - e di solito si rompe in silenzio.
Plugin diventati core: migra il dato, non reinstallare
Buona parte dei plugin più popolari non è sparita per incompatibilità - è sparita perché la funzione è entrata nel core. Qui il lavoro non è "trovare la versione 11", è portare il dato verso la funzionalità nativa:
- FormCreator - è diventato il modulo Moduli nativo, un nuovo motore. Non c'è un importatore trasparente; esiste solo uno strumento di transizione, e i moduli non si spostano da soli.
- GenericObject - gli oggetti personalizzati ora sono nativi. Rivaluta ogni tipo e mappalo su un asset o un dropdown del core.
- FusionInventory e dashboard di plugin - già sostituiti da 10 dal GLPI Agent e dalle dashboard native. Su 11 non c'è motivo di insistere.
- Webhook in uscita - il core ora notifica i sistemi esterni sugli eventi (apertura ticket, cambio di stato), coprendo parte di ciò che si risolveva con un plugin.
Matrice di compatibilità: perché cade ogni caso
Prima di prenotare la finestra, in manutenzione classifichiamo ogni plugin installato in una di queste righe. A decidere non è il nome, è il motivo tecnico:
| Plugin / caso | Motivo tecnico | Azione prima di migrare |
|---|---|---|
| FormCreator | La funzione è diventata Moduli nativo (nuovo motore) | Inventariare e migrare i moduli che reggono il service desk - non migrano da soli |
| GenericObject | Oggetti personalizzati ora nativi | Mappare ogni tipo su un asset o dropdown del core |
| FusionInventory | Sostituito dal GLPI Agent (da 10) | Spostare prima la raccolta sul GLPI Agent |
| Plugin con SQL grezzo / output procedurale | Usa $DB->query() o Html::header() - rimossi/rotti | Richiede una release portata; senza, disattivare |
Plugin senza return type nei can*() | PHP 8.2 rifiuta la firma; il plugin non si carica | Attendere la versione dell'autore o ritirarlo |
| Fields, DataInjection, PDF, Tag | Hanno una release per 11 | Aggiornare dopo il core, uno a uno, validando tra ciascuno |
| NexTool | Compatibile con 10 e 11 (stesso codice portato) | Aggiornare alla versione 11 |
| Plugin senza release dal 2023 | Probabilmente non portato | Decisione di business: sostituire o ritirare |
Diagnosi: misura, non decidere a memoria
Non classificare a mente. Rileva lo stato reale dei plugin e scansiona il loro codice cercando gli schemi che il core 11 ha rimosso:
# Stato reale dei plugin (esegui su GLPI 10 prima di migrare; sola lettura)
# state: 0=nuovo 1=attivo 2=non installato 3=da configurare
# 4=non attivato 5=da pulire 6=non aggiornato
mysql -u glpi -p glpi -e \
"SELECT name, directory, version, state FROM glpi_plugins ORDER BY state, name;"
# Scansiona il codice dei plugin cercando i pattern che il core 11 ha rimosso
cd /var/www/glpi/plugins
grep -rln '$DB->query(' . --include='*.php' # driver SQL grezzo rimosso in 11
grep -rln 'Html::header' . --include='*.php' # output procedurale, pre-Twig
grep -rln 'includes.php' . --include='*.php' # include relativo fragile con il routing Symfony
L'errore comune è fidarsi solo del bollino del marketplace. Una release taggata "GLPI 11" può ancora nascondere SQL grezzo su un percorso poco usato - che esplode solo quando quel report specifico viene aperto, settimane dopo il go-live.
Il codice che boccia un plugin su 11
Se mantieni un tuo plugin, o devi valutarne uno di terzi con il sorgente in mano, questi sono i tre schemi che compaiono più spesso quando portiamo codice da 10 a 11:
// GLPI 10 (funzionava): SQL grezzo direttamente nel driver
$res = $DB->query("SELECT id FROM glpi_tickets WHERE status = 1");
// GLPI 11: $DB->query() e stato RIMOSSO e request() con stringa grezza e bloccato.
// La SELECT diventa un query builder per criteri:
$rows = $DB->request([
'SELECT' => 'id',
'FROM' => 'glpi_tickets',
'WHERE' => ['status' => 1],
]);
// DDL / SQL letterale inevitabile (ALTER, SHOW INDEX): usa doQuery()
$DB->doQuery("ALTER TABLE glpi_plugin_x ADD COLUMN attivo TINYINT DEFAULT 0");
// PHP 8.2+: un metodo ereditato richiede il return type; senza ": bool" il plugin non si carica
public static function canCreate(): bool
{
return Session::haveRight('plugin_x', CREATE);
}
Nota che anche l'alias di colonna è cambiato: il vecchio trucco del backtick inline che GLPI 10 tollerava ora deve diventare 'name AS figlio', perché il query builder di 11 fa l'escape dei backtick correttamente.
Come testare la compatibilità prima della finestra
Non scoprire mai l'incompatibilità in produzione. La routine che applichiamo in collaudo:
- Clone di produzione. Porta su 11 su una copia del database reale, non su una base di esempio. Un plugin si rompe con i tuoi dati, non con dati puliti.
- Installa e attiva da console.
php bin/console glpi:plugin:install <directory>eglpi:plugin:activate <directory>, come utente del web server. Se il plugin esegue una migrazione all'install/init, è qui che parte. - Apri ogni pagina
front/del plugin. Attivare senza errori non basta; il motore Twig si lamenta solo quando lo schermo viene realmente renderizzato. - Guarda il log giusto. Il fallimento di caricamento non diventa un fatal di PHP - diventa
glpi.ERROR: Error while loading plugin Xnel log di GLPI. Chi guarda solo il php-errors.log conclude, a torto, che "va tutto bene". - Resetta l'OPcache tra i tentativi. Dopo aver sostituito i file, php-fpm serve ancora il vecchio bytecode; ricarica il processo (ad esempio,
kill -USR2sul master php-fpm), non solo Apache.
Cosa ci ha insegnato la manutenzione
L'incidente più insidioso che abbiamo visto non è comparso nella migrazione in sé - è comparso mesi dopo, su un semplice bump di versione di un plugin amministrativo. Eseguiva la sua migrazione di schema dentro plugin_init, uno schema comune e apparentemente innocuo: il blocco viene eseguito solo finché lo schema_version salvato è inferiore alla versione di setup.php. Un bug latente lì è rimasto dormiente fino al bump successivo - e quando finalmente è partito e ha lanciato un'eccezione, GLPI 11 l'ha catturata in Plugin::load e ha disattivato il plugin da solo. Il sintomo per il cliente era quel "si attiva e si disattiva senza errore visibile", con il plugin che oscillava allo stato 4 (non attivato, che sembra normale). Da allora la regola è dura: ogni bump di un plugin con migrazione-nell'init richiede uno smoke test di attivazione dopo il bump, e il blocco di migrazione va sempre in try/catch, con lo schema_version scritto FUORI dal try - altrimenti riprova a ogni richiesta ed entra in loop. È il tipo di dettaglio che solo chi opera GLPI di cliente ogni giorno porta nella memoria muscolare.
Devo migrare adesso?
Se la tua matrice di plugin è verde (release portata per tutti gli essenziali) e hai un collaudo con clone di produzione, sì - 11 è più moderno, sicuro e veloce. Se dipendi da un plugin senza versione 11, la decisione diventa di business: sostituirlo con la funzione nativa, cambiare plugin o rimandare. Ciò che non si può fare è migrare al buio e scoprire l'incompatibilità con l'ambiente in linea.
Se il tuo team non ha una finestra per provare la migrazione e classificare ogni plugin con calma, NexTool guida l'upgrade del tuo GLPI con inventario dei plugin, collaudo su clone e rollback provato. Parla con noi di supporto e manutenzione GLPI.
Revisionato dal team NexTool Solutions.