Snippet PHP per scaricare un intero database da un server remoto

Quando si tratta di proteggere i dati del tuo database, l’esecuzione regolare di un backup è fondamentale. Inoltre è a volte necessario creare una copia del database, per ragioni di sviluppo oltre che di sicurezza, di un’applicazione web che è accessibile solo via FTP.

Ebbene, quando l’accesso alla console MySQL o a phpMyAdmin è interdetto, ma è disponibile un’accesso in scrittura via FTP, è possibile provare i metodi che passiamo ad illustrare.

L’dea è avere una URL come example.org/dump-database.php, che invocata da browser faccia partire il download di un file sql, ottenendo così una copia dei dati del database.

Ovviamente dovrai avere le credenziali di accesso al database per poter effettuare il dump.

Script PHP che sfrutti la console mysql per il dump del database

Questo script è più performante del precedente, ma non disponibile su tutti gli hosting, in quanto utilizza il comando MySQL tramite exec (che è la funzione che esegue i comandi direttamente sulla console del sistema operativo).

<?php
// Configurazione dei parametri
$host = 'localhost'; // Host del database
$username = 'username'; // Nome utente del database
$password = 'password'; // Password del database
$dbname = 'database_name'; // Nome del database
$tables = '*'; // Tabelle da includere nel dump (puoi specificarne una lista separata da virgole o usare '*' per tutte le tabelle)

// Crea il nome del file di dump
$filename = 'database_dump_' . date('Y-m-d_H-i-s') . '.sql';

// Esegui il dump del database
exec("mysqldump -h{$host} -u{$username} -p{$password} {$dbname} {$tables} > {$filename}");

// Forza il download del file di dump
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($filename) . "\"");
readfile($filename);

// Rimuovi il file di dump dal server
unlink($filename);
?>

NOTA BENE:

  • Se tutti possono accedere alla URL su cui gira il tuo snippet tutti potranno scaricare il tuo database (vedi “Implicazioni di sicurezza”);
  • Se il database è molto grande potresti, nel navigare la URL, non ottenere l’agognato file o ritrovarti con una copia incompleta del database a causa del timeout dell’esecuzione di processi in PHP (il famoso max_execution_time).

Script in PHP puro per il dump del database

Questo script necessita solo che sul server che lo esegue, ci sia l’interprete PHP, cosa che è effettivamente possibile su praticamente tutti gli hosting sparsi per l’infosfera.

<?php
// Configurazione dei parametri
$host = 'localhost'; // Host del database
$username = 'username'; // Nome utente del database
$password = 'password'; // Password del database
$dbname = 'dbname'; // Nome del database
$tables = '*'; // Tabelle da includere nel dump (puoi specificarne una lista separata da virgole o usare '*' per tutte le tabelle)


// Connessione al database
$mysqli = new mysqli($host, $username, $password, $dbname);

// Verifica della connessione
if ($mysqli->connect_errno) {
    die('Failed to connect to MySQL: ' . $mysqli->connect_error);
}

// Recupero dei nomi delle tabelle nel database
$tables = array();
$result = $mysqli->query("SHOW TABLES");
while ($row = $result->fetch_row()) {
    $tables[] = $row[0];
}

// Creazione del dump del database
$dump = '';
foreach ($tables as $table) {
    $result = $mysqli->query("SELECT * FROM `$table`");
    $numColumns = $result->field_count;

    $dump .= "DROP TABLE IF EXISTS `$table`;\n";
    $row2 = $mysqli->query("SHOW CREATE TABLE `$table`")->fetch_row();
    $dump .= $row2[1] . ";\n\n";

    while ($row = $result->fetch_row()) {
        $dump .= "INSERT INTO `$table` VALUES (";
        for ($i = 0; $i < $numColumns; $i++) {
            $row[$i] = $mysqli->real_escape_string($row[$i]);
            $row[$i] = "'" . $row[$i] . "'";
        }
        $dump .= implode(',', $row);
        $dump .= ");\n";
    }

    $dump .= "\n";
}

// Impostazione dell'header per il download del file
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"database_dump_" . date('Y-m-d_H-i-s') . ".sql\"");

// Output del dump del database
echo $dump;

// Chiusura della connessione al database
$mysqli->close();

Implicazioni di sicurezza

Quando hai a che fare con i database stai avendo a che fare con la tua base dati, dove la parola dati dovrebbe spaventarti un poco! 😀

Pertanto assicurati di proteggere adeguatamente il file PHP che contiene lo script, ad esempio, posizionandolo in una directory non accessibile al pubblico o dandogli un nome al file, praticamente impossibile da raggiungere per caso. Se dovevi solo scaricare il dump per lavorarci altrove, allora ricordati di cancellare il file che contiene il tuo snippet!

Come mettere lo script in un file PHP

Per utilizzare lo script PHP per il dump del database, segui questi semplici passaggi. Prima di tutto, crea un nuovo file PHP sul tuo server web. Quindi, copia il codice dello script fornito in questo articolo e incollalo nel file PHP appena creato. Assicurati di configurare correttamente i parametri, come l’host del database, il nome utente, la password e il nome del database. Salva il file PHP e caricalo sul tuo server. Prendi nota del nome del file e usalo nella URL per lanciare lo script e scaricare il tuo database tramite il browser.

Sper di esserti stato utile

Testare Drupal 10 in locale

Risolvere il problema del 404 not found che si verifica quando si tenta di effettuare il CRUD di un campo su un’entità di Drupal 10.

Quasi sicuramente se sei arrivato qui significa che all’aggiunta di un campo su un tipo di contenuto di Drupal 10, hai ricevuto un errore 404 e lo stesso ti sarà successo in modifica o delete del campo di un entità.

Se sei fortunato, come descritto da Halt nell’issue #2743633 su drupal.org il problema potrebbe essere generato dal comando php che ti consente di lanciare il webserver in ascolto su una certa porta.

Normalmente il comando che si lancia è:

php -S localhost:8000

Che ti consente, navigando con il browser su quell’host, di vedere la tua installazione Drupal 10. Tuttavia tale comando risulta insufficiente, in quanto bisogna dargli in pasto un file che è incluso nell’installazione Drupal, ovvero “.ht.router.php“.

TODO immagine boyscout che giura

Utilizzando il comando il problema non si verifica più, parola di boy scout.

php -S localhost:8888 .ht.router.php

Aprendo il file .ht.router.php scopriamo subito il suo proposito leggendo il commento in testa:

/**
 * @file
 * Router script for the built-in PHP web server.
 *
 * The built-in web server should only be used for development and testing as it
 * has a number of limitations that makes running Drupal on it highly insecure
 * and somewhat limited.
 *
 * Note that:
 * - The server is single-threaded, any requests made during the execution of
 *   the main request will hang until the main request has been completed.
 * - The web server does not enforce any of the settings in .htaccess in
 *   particular a remote user will be able to download files that normally would
 *   be protected from direct access such as .module files.
 *
 * The router script is needed to work around a bug in PHP, see
 * https://bugs.php.net/bug.php?id=61286.
 *
 * Usage:
 * php -S localhost:8888 .ht.router.php
 *
 * @see http://php.net/manual/en/features.commandline.webserver.php
 */

Cosa che significa sostanzialmente:

  • che questo file andrebbe lanciato solo per finalità di testing e sviluppo
  • che non è sicuro
  • che è limitato, ad esempio dal fatto che è single thread

Buon Drupal 10 🙂

Dump di variabili per finalità di debug e vedere un log file in tempo reale con tail -f

Il debug è uno stress? Con questi piccoli accorgimenti non vi peserà più tanto.

Un mio collega di qualche tempo fa, l’ottimo G. Bove, si portava sempre dietro la sua cassetta degli attrezzi chiamata GBTools, una libreria di funzioni e snippet PHP in cui compariva anche la funzione dumpa (letto dampa), che effettuava un semplice dump su file di quello che gli passavi (variabili, oggetti, array, stringhe eccetera).

In suo omaggio, utilizzerò lo stesso nome per la mia funzione di log su file, ecco il codice che potrete scrivere dove vi pare, ma che vi consiglio di mettere in un file sempre richiamato nel vostro progetto.

<?php
if(!function_exists('dumpa')){
    function dumpa($var){
        $req_dump = print_r($var, TRUE);
        $fp = fopen(__DIR__ . '/my.log', 'a');
        fwrite($fp, $req_dump);
        fwrite($fp, "\n");
        fclose($fp);
    }
}

Questa funzione scriverà quello che gli verrà passato sul file my.log (nella directory in cui viene dichiarata la funzione). Ad onor del vero non ricordo come fosse strutturata quella da cui ho tratto ispirazione, ma alla fine fa il suo sporco lavoro.

Per poter leggere il file my.log, potete ovviamente aprirlo con un qualunque editor, o fare una cosa più figa e, soprattutto, più efficiente.

Se siete su ambiente Linux e (ancora) non conoscete il comando tail, provate a lanciare da bash quanto segue:

tail -f my.log

Lasciate la console aperta e affiancatela al vostro editor o browser per vedere i risultati del vostro debug in tempo reale.

Ho trovato, ma non testato, anche un modo per ottenere il comando tail su ambiente windows, fatemi sapere nei commenti se funziona.