Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

🔄 WordPress in una sottocartella: come spostare l'installazione dalla radice e viceversa

🔄 WordPress in una sottocartella: come spostare l'installazione dalla radice e viceversa

Una situazione familiare: imposti un sito di sviluppo, costruisci il tema, colleghi i contenuti tramite WP Migrate DB Pro e, dopo il push, scopri stili rotti, immagini mancanti e un wp-admin non funzionante. Il motivo è quasi sempre lo stesso: il sito di produzione risiede nella root mentre quello di sviluppo è in una sottodirectory (o viceversa), e un semplice search-replace degli URL nel database non corregge questa differenza.

Il problema è più profondo di quanto appaia: in un'installazione nella root, WordPress usa lo stesso dominio per tutti i link (sia alle pagine sia ai file media). In un'installazione in sottodirectory, i link ai contenuti provengono dall'indirizzo del sito, mentre i link alle risorse (css, js, immagini) provengono dall'indirizzo di WordPress. Un search-replace standard sul database sostituisce tutto in modo uniforme e rompe metà dei percorsi.

In questa guida troverai due rotte di migrazione comprovate (andata e ritorno) con impostazioni specifiche di search-replace, preparazione del file wp-config.php e la corretta sequenza di trasferimento dei file. Dopo la lettura, potrai uniformare sviluppo e produzione allo stesso schema oppure eseguire consapevolmente una migrazione tra tipi di installazione diversi senza rompere il frontend.

💡 Panoramica rapida:

  • Determina il tuo tipo di installazione: verifica se "Indirizzo WordPress" e "Indirizzo sito" coincidono in Impostazioni → Generali
  • Per migrare da sottodirectory a root: imposta in modo fisso WP_SITEURL in wp-config, esegui una sostituzione di /subdir/ nel database, sposta i file al livello superiore, aggiorna il file index.php della root
  • Per migrare da root a sottodirectory: sostituisci solo i percorsi di /wp-content nel database, aggiorna l'indirizzo WordPress nelle impostazioni, crea la sottodirectory, copia index.php e .htaccess nella root
  • Dopo ogni migrazione, vai su Impostazioni → Permalink e clicca "Salva": questo ricostruisce la struttura degli URL e svuota la cache

Come determinare dove è installato WordPress

Se hai installato WordPress manualmente, probabilmente ricordi se era nella root del dominio o in una sottodirectory come /wp o /blog. Ma se il sito è stato ereditato da uno sviluppatore precedente, distribuito dal provider di hosting con un clic, o sono passati diversi anni, i dettagli si affievoliscono.

Il modo più rapido: vai nell'amministrazione di WordPress, apri Impostazioni → Generali e guarda i campi "Indirizzo WordPress (URL)" e "Indirizzo sito (URL)". Se i valori coincidono, hai un'installazione nella root:

I campi dell'indirizzo WordPress e dell'indirizzo del sito coincidono

Se i campi sono diversi, WordPress è installato in una sottodirectory (nell'esempio sotto, è /subdir):

L'indirizzo WordPress differisce dall'indirizzo del sito

Un segno aggiuntivo di un'installazione in sottodirectory: quando accedi all'amministrazione, l'URL contiene una sottodirectory, ad esempio example.com/wp/wp-admin/ invece di example.com/wp-admin/.

Perché non puoi semplicemente trasferire in modo diretto

La radice del problema sta nel doppio sistema di URL che WordPress utilizza con le installazioni in sottodirectory. Analizziamolo con esempi concreti.

Supponi di avere un'installazione nella root su example.com. Assolutamente tutti i link nel database, sia a un articolo /2025/about-page sia a un'immagine /wp-content/uploads/photo.jpg, iniziano con //example.com. Un search-replace standard //example.local//example.com funziona perfettamente.

Ora prendi un'installazione nella sottodirectory /wp. Il link allo stesso articolo appare come //example.com/about-page (tramite l'indirizzo del sito), mentre il link alla stessa immagine è //example.com/wp/wp-content/uploads/photo.jpg (tramite l'indirizzo WordPress con la sottodirectory). Una semplice sostituzione //example.local//example.com romperà i file media: il sistema li cercherà senza /wp nel percorso e otterrà un 404.

La tabella sotto mostra quali gruppi di URL devono essere aggiornati in ciascuna direzione di migrazione:

Direzione

URL di pagine e articoli

URL di media e risorse

Percorsi file nel database

Sottodirectory → root

Sostituisci /subdir → `` (rimuovi la sottodirectory)

Sostituisci /subdir/wp-content/wp-content

Sostituisci /app/public/subdir/app/public

Root → sottodirectory

Lascia invariato

Sostituisci /wp-content/subdir/wp-content

Sostituisci /app/public/app/public/subdir

Oltre al database, devi spostare fisicamente i file e aggiornare index.php nella root, altrimenti WordPress non troverà wp-blog-header.php. Vediamo ora entrambe le procedure passo dopo passo.

Metodo 1: spostare WordPress da una sottodirectory alla root

Questa è la direzione più semplice: rimuovi la sottodirectory dai percorsi e tutti gli URL diventano «piatti», come in un'installazione standard.

Passo 0: diagnosticare cosa andrà storto

Prima di intervenire, è utile vedere con i propri occhi la portata del problema. Lo screenshot qui sotto mostra le impostazioni di migrazione da wp-in-a-subdirectory.local (WordPress in /subdir) a wp-standard-install.local (installazione nella root). Le impostazioni di WP Migrate DB Pro sono quelle standard, più una sostituzione del titolo del sito a scopo dimostrativo:

Impostazioni di migrazione da sottodirectory di WP Migrate DB Pro

Il risultato è prevedibilmente desolante: le pagine si aprono ma senza stili e con immagini non funzionanti:

Risultato della migrazione senza stili e con immagini non caricate

Nell'HTML puoi vedere i link alle risorse con un percorso /subdir inesistente che sul server di destinazione non c'è più. Provando ad accedere a wp-admin si viene reindirizzati a wp-standard-install.local/subdir/wp-login.php, ma quel file non esiste. Ora sistemiamo la situazione.

Passo 1: preparazione

Per prima cosa, proteggi l'accesso all'amministrazione durante la migrazione. Aggiungi a wp-config.php delle costanti che sovrascriveranno le impostazioni del database, così WordPress continuerà a farti entrare in admin tramite il vecchio percorso con la sottodirectory, anche dopo aver pulito il database:

1define( 'WP_SITEURL', 'http://wp-in-a-subdirectory.local/subdir' );
2define( 'WP_HOME', 'http://wp-in-a-subdirectory.local' );

Poi metti il sito in modalità manutenzione: modifica index.php nella root pubblica, commenta la riga require( dirname( __FILE__ )... e dopo il tag di chiusura ?> inserisci un segnaposto html con un breve messaggio di fermo temporaneo. I visitatori vedranno questo:

Pagina di manutenzione con messaggio di lavori tecnici

Nel frattempo, tu continui ad accedere all'admin su http://wp-in-a-subdirectory.local/subdir/wp-admin/ perché la costante WP_SITEURL è attiva.

Passo 2: cerca e sostituisci nel database

Ora pulisci il database. Esegui un cerca-sostituisci con queste coppie (mostrate nell'interfaccia di WP Migrate DB Pro, ma lo stesso principio vale con search-replace di WP-CLI o con query SQL via phpMyAdmin):

  • //wp-in-a-subdirectory.local/subdir//wp-in-a-subdirectory.local
  • /app/public/subdir/app/public (percorso file sul server)
Finestra cerca e sostituisci di WP Migrate DB Pro per rimuovere la sottodirectory

Subito dopo la migrazione, l'aspetto non cambierà (la pagina di manutenzione è ancora attiva, l'admin funziona tramite la costante hardcoded). Ma se guardi il contenuto dei post, le immagini non vengono ancora caricate e i link interni hanno «perso» la sottodirectory, che è esattamente ciò che volevamo in questa fase:

Contenuto dell'articolo dopo la pulizia della sottodirectory dal database

Step 3: trasferimento fisico dei file

Rimuovi (o commenta) le righe con WP_SITEURL e WP_HOME da wp-config.php. L'admin ora smetterà di funzionare, quindi sposta immediatamente i file dalla sottodirectory al livello superiore.

Via SSH o riga di comando sul server, si fa con tre comandi:

1rm index.php && mv subdir/* . && rm -rf subdir

Via FTP o file manager dell'hosting, trascina tutto il contenuto della sottodirectory nella root pubblica, sostituendo index.php:

Spostamento dei file di WordPress nella cartella principale tramite FTP

Fatto. Il sito si apre all'URL root; immagini e stili sono al loro posto:

Sito correttamente funzionante dopo lo spostamento nella root

Tocco finale: vai nell'admin (ora su http://wp-in-a-subdirectory.local/wp-admin senza la sottodirectory), apri Impostazioni → Permalink e clicca «Salva modifiche», anche se non hai cambiato nulla. WordPress ricostruirà la struttura degli URL e svuoterà la cache.

Metodo 2: spostare WordPress dalla root a una sottodirectory

Molti sviluppatori considerano installare WordPress in una sottodirectory una buona pratica: i file core non affollano la root, la gestione tramite Git/Composer è semplificata e il dominio stesso può essere usato per altre applicazioni. Ma migrare un sito esistente in una sottodirectory è oggettivamente più complesso del contrario, perché ora alcuni link DEVONO mantenere la sottodirectory mentre altri no.

Fase 0: diagnostica

Stesso punto di partenza: proviamo una migrazione standard dall'installazione nella root wp-standard-install.local all'installazione in sottodirectory wp-in-a-subdirectory.local (WordPress in /subdir):

Impostazioni di migrazione dalla root alla sottodirectory di WP Migrate DB Pro

Il risultato è del tutto prevedibile: le pagine si aprono ma fogli di stile e immagini si rompono perché /subdir non è stato aggiunto ai loro percorsi:

Stili e immagini non caricati dopo la migrazione nella sottodirectory

A differenza del primo scenario, i link a post e pagine funzionano correttamente (non devono contenere la sottodirectory). A rompersi sono specificamente le risorse (css, js, media), i cui percorsi ora devono includere /subdir.

Fase 1: preparazione

In questa fase, NON impostiamo le costanti WP_SITEURL e WP_HOME, perché il nostro search-replace non toccherà questi valori e aggiorneremo l'indirizzo WordPress manualmente poco dopo.

Impostate la pagina di manutenzione allo stesso modo: commentate require(...) in index.php e aggiungete un placeholder html. I visitatori vedono il messaggio di manutenzione mentre voi continuate ad accedere all'admin su http://wp-standard-install.local/wp-admin/.

Fase 2: search-replace selettivo nel database

La differenza chiave rispetto al primo metodo: sostituiamo SOLO i percorsi di file e risorse, SENZA toccare gli URL delle pagine. Per farlo, mirate la sostituzione usando il pattern /wp-content:

  • //wp-standard-install.local/wp-content//wp-standard-install.local/subdir/wp-content
  • /app/public/app/public/subdir (percorso sul server)
Configurazione della sostituzione selettiva per aggiungere la sottodirectory

Dopo la migrazione, verificate il contenuto dei post: i link ad altre pagine del sito NON contengono la sottodirectory (corretto), mentre le immagini incorporate la contengono (anch'esso corretto):

Articolo dopo la sostituzione selettiva: immagini con sottodirectory

Fase 3: aggiornamento dell'indirizzo WordPress e spostamento dei file

Ora andate su Impostazioni → Generali e aggiungete la sottodirectory in fondo a "Indirizzo WordPress (URL)", ad esempio http://wp-standard-install.local/subdir. Subito dopo aver salvato, l'admin si romperà perché WordPress cercherà i file nel nuovo percorso, ma non sono ancora lì:

Aggiornamento dell'indirizzo WordPress con sottodirectory aggiunta

Create la sottodirectory subdir nella root pubblica e spostateci dentro TUTTI i file di WordPress. Poi copiate index.php e .htaccess INDIETRO nella root, così la pagina di manutenzione continua a essere visualizzata mentre finite:

File di WordPress spostati nella sottodirectory

Ripristinate index.php ALL'INTERNO della sottodirectory al suo stato originale: rimuovete il placeholder html e decommentate la riga require:

1<?php
2define( 'WP_USE_THEMES', true );
3require( dirname( __FILE__ ) . '/wp-blog-header.php' );

Ora l'admin è di nuovo accessibile su http://wp-standard-install.local/subdir/wp-admin/:

Amministrazione di WordPress funzionante dopo lo spostamento nella sottodirectory

Verificate i contenuti: le immagini sono al loro posto, gli stili vengono caricati:

Contenuto dell'articolo verificato: tutte le immagini sono al loro posto

Tocco finale: index.php nella root

Non resta che aggiornare index.php nella root pubblica. Rimuovete la pagina di manutenzione e specificate il percorso corretto di wp-blog-header.php tenendo conto della sottodirectory:

1<?php
2define( 'WP_USE_THEMES', true );
3require( dirname( __FILE__ ) . '/subdir/wp-blog-header.php' );

Il sito si apre all'URL root con tutte le risorse caricate dalla sottodirectory:

Sito correttamente funzionante dopo lo spostamento nella sottodirectory

Di nuovo, andate su Impostazioni → Permalink e salvate senza modifiche, così WordPress aggiorna la struttura degli URL.

Strumenti alternativi e il metodo ufficiale

L'approccio descritto sopra con WP Migrate DB Pro è comodo ma non è l'unica opzione. Ecco altri strumenti con cui potete lavorare:

  • *WP-CLI search-replace.* Il comando wp search-replace '//oldsite.local/subdir' '//newsite.com' con il flag --dry-run mostrerà prima quante occorrenze verranno sostituite. Per una sostituzione selettiva (root → sottodirectory), restringete il pattern: wp search-replace '//newsite.com/wp-content' '//newsite.com/subdir/wp-content'.

  • Metodo ufficiale di WordPress. La documentazione su developer.wordpress.org descrive la procedura "Dare a WordPress una propria directory", con configurazioni dettagliate per Apache (.htaccess), nginx (server block) e IIS (web.config). Il metodo non richiede plugin e funziona su qualsiasi hosting.

  • SQL manuale. Se il volume delle modifiche è ridotto, potete eseguire UPDATE wp_posts SET post_content = REPLACE(post_content, '/subdir/', '/') direttamente in phpMyAdmin, ma sempre con un backup preventivo, perché una sostituzione del genere distruggerà i dati serializzati in wp_options e wp_postmeta.

Qualunque strumento scegliate, la regola è la stessa: quando migrate ROOT → SOTTODIRECTORY, sostituite solo /wp-content e i percorsi dei file; quando migrate SOTTODIRECTORY → ROOT, sostituite tutto ciò che fa riferimento alla sottodirectory.

⁉️🤔 Domande frequenti

WP Migrate DB Pro è obbligatorio per questo tipo di migrazione?

No. WP Migrate DB Pro offre semplicemente un'interfaccia comoda per il search-replace con comprensione dei dati serializzati PHP. Tecnicamente, potete eseguire le stesse sostituzioni via WP-CLI (anche il comando wp search-replace gestisce correttamente le stringhe serializzate) o usare il metodo ufficiale di WordPress con trasferimento manuale dei file e modifica di index.php. Il plugin fa risparmiare tempo su progetti medio-grandi con molte occorrenze.

Cosa fare se alcune immagini ancora non vengono caricate dopo la migrazione?

La causa più comune: nel database sono rimasti URL cablati con percorsi assoluti del vecchio server che non corrispondevano al pattern di sostituzione. Verificate il contenuto dei post via phpMyAdmin: SELECT ID, post_content FROM wp_posts WHERE post_content LIKE '%/subdir/%' (o il vecchio dominio). Il secondo indiziato è la cache del browser e della CDN: svuotate entrambe e verificate in modalità incognito.

Devo aggiornare.htaccess dopo il trasferimento?

Se usate i permalink avanzati, sì, ma WordPress lo fa automaticamente quando cliccate "Salva" nella pagina Impostazioni → Permalink. Se il server non ha i permessi di scrittura, WordPress mostrerà il contenuto pronto del file.htaccess da copiare manualmente. Quando migrate verso una sottodirectory, assicuratevi che il file.htaccess della root (non quello dentro la sottodirectory) non contenga regole in conflitto con la nuova struttura.

È possibile eseguire la migrazione con zero downtime?

Tecnicamente sì, se usate il metodo con i redirect.htaccess (Metodo I della documentazione ufficiale di WordPress, "Senza cambiare gli URL"). Con questo approccio, i file vengono spostati nella sottodirectory mentre il file.htaccess della root dirige tutte le richieste in modo trasparente verso la nuova posizione. I visitatori non si accorgono dello spostamento. Lo svantaggio: restate sullo stesso dominio e l'URL del sito formalmente non cambia (la sottodirectory non è visibile nella barra degli indirizzi).

Perché WP Migrate DB Pro non supporta nativamente la migrazione tra diversi tipi di installazione?

Gli sviluppatori di Delicious Brains hanno discusso la questione su GitHub per quasi tre anni. La radice del problema: il plugin applica UNA coppia search-replace all'INTERO database, ma la migrazione tra root e sottodirectory richiede sostituzioni DIVERSE per gruppi di URL differenti (pagine vs risorse). Determinare automaticamente a quale gruppo appartiene un URL richiederebbe l'analisi della struttura del contenuto, andando oltre il semplice search-replace. Pertanto, la raccomandazione attuale è: portate i siti a uno schema di installazione unificato PRIMA della migrazione.

Discussione sul supporto alla migrazione su GitHub di Delicious Brains

In conclusione: root o sottodirectory?

La scelta tra installazione WordPress in root o in sottodirectory si riduce essenzialmente a un compromesso. L'installazione in root è più semplice: meno elementi in gioco, compatibilità diretta tra sviluppo e produzione, nessuna sorpresa con URL doppi. L'installazione in sottodirectory è architetturalmente più pulita: i file core sono isolati, nella root risiede solo index.php, aggiornare WordPress via Git/Composer è più facile e ospitare più applicazioni sullo stesso dominio è più sicuro.

Se hai un sito di produzione e un sito di sviluppo, porta entrambi a uno schema unificato (uno qualsiasi dei due) e dimentica il problema. Se lavori in un team dove alcuni progetti sono storicamente in root mentre altri sono in sottodirectory, ora conosci gli esatti pattern di search-replace per ciascuna direzione.

La regola principale da tenere a portata di mano: quando migri ROOT → SOTTODIRECTORY, tocca solo /wp-content e i percorsi dei file; quando migri SOTTODIRECTORY → ROOT, sostituisci tutto ciò che contiene la sottodirectory. E ricorda sempre, sempre di cliccare «Salva» nei Permalink dopo lo spostamento.