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

Dokan woocommerce, where is {site_name} in email placeholder

Sometimes can happen that the email sent through woocommerce have incorrect data. Where are placeholders data stored, for instance {site_name}, {site_address}, {order_number}, used in Dokan email templates? And, how to modifify {site_name} placeholder?

In my case {site_name} placeholder value was referring to an old site name, still present after a migration, due to this I bumped into the necessity of change placeholder value.

Uno screenshot del file wp-config.php dove è presente il prefisso del nome delle tabelle del database.
A screenshot WordPress wp-config.php file, where the database table prefix is defined.

To get the job done I was obliged to do the modification at mariadb/mysql database level. More specifically “{site_name}” was defined in “PREFIX_options” table, where PREFIX is your database table prefix defined in wp-config.php file at installation time.

The option to find out in my case was “woocommerce_email_from_name“, that represents {site_name} placeholder in Dokan email templates.

I came across it through phpmyadmin search functionality, searching for the name, the wrong one I want to replace, appearing on the email sent to users.

HINT!

The aim of this post is to explain how to replace Dokan email template placeholders ({site_name}), if you are trying to customize Dokan email templates, you can check out this link: https://wedevs.com/docs/dokan/tutorials/customize-e-mail-template/

An example of how Dokan is translating placeholder into bare text is the method trigger, defined in plugins/dokan-pro/modules/rma/includes/emails/class-dokan-rma-send-coupin-email.php php file:

<?php
/**
     * Trigger the sending of this email.
     *
     * @param int $product_id The product ID.
     * @param array $postdata.
     */
    public function trigger( $coupon, $data ) {
        if ( ! $this->is_enabled() || ! $this->get_recipient() ) {
            return;
        }

        $this->object = $coupon;

        if ( $data ) {
            $coupon_id      = isset( $data['request_id'] ) ? $data['request_id'] : '';
            $vendor_id      = isset( $data['refund_vendor_id'] ) ? $data['refund_vendor_id'] : '';
            $vendor         = dokan()->vendor->get( $vendor_id );
            $customer_email = $coupon->get_email_restrictions();
            $customer_email = is_array( $customer_email ) ? $customer_email[0] : $customer_email;
        }

        $this->find['site_name']      = '{site_name}';
        $this->find['vendor_name']    = '{vendor_name}';

        $this->replace['site_name']   = $this->get_from_name();
        $this->replace['vendor_name'] = $vendor->get_name();
        $this->replace['coupon_id']   = $coupon_id;

        $this->setup_locale();
        $this->send( "{$customer_email}, {$this->get_recipient()}", $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
        $this->restore_locale();
    }

In particoular, pay attention at these two lines:

...
$this->find['site_name']      = '{site_name}';
...
$this->replace['site_name']   = $this->get_from_name();
...

The get_from_name method is defined in a superclass and is the function in which the substitution is done.

I strongly suggest you to explore source code through Visual Studio Code or an equivalent product, to better understand how your specific case works.

Fell free to post a comment to submit your case.