简体   繁体   English

在没有第三方库的情况下在 Laravel 中备份 MySQL 表

[英]Backup MySQL tables in Laravel without third-party libraries

I new to Laravel.我是 Laravel 的新手。 I've been trying to create a controller that backups tables in the form of backup_date_.sql format without using any third-party library at all, but I'm getting frustrated.我一直在尝试创建一个控制器,以 backup_date_.sql 格式的形式备份表,而根本不使用任何第三方库,但我感到很沮丧。 I've searched and I found some code examples.我进行了搜索并找到了一些代码示例。 I've tried to use them within my BackupsController, but things are getting more and more difficult.我尝试在我的 BackupsController 中使用它们,但事情变得越来越困难。 Any help is really appreciated.非常感谢任何帮助。 This is my code, Thanks in advance.这是我的代码,在此先感谢。

    <?php

public function query($data, $mode = \PDO::FETCH_ASSOC)
{
    $pdo  = DB::connection()->getPdo();
    $stmt = $pdo->query($data);
    $results = $stmt->fetchAll($mode);
    // $results = $stmt->fetch($mode);
    return $results;
}

public function backup(Request $request)
{


    if ($request->all())  {

        $output = '';

      foreach (request('table') as $table) {

        $show_table_query = $this->query("SHOW CREATE TABLE " . stripslashes($table) . "");


        foreach ($show_table_query as $show_table_row)
        {
             array_shift($show_table_row);

             $output .= implode(", ", $show_table_row);

        }

          $single_result = DB::select('select * from ' . stripslashes($table));


          foreach ($single_result as $key => $value)
          {
            $value = array_map(function($obj) {
                return (array) $obj;
            }, $single_result);


            $keys = array_keys($value[$key]);
            $val = array_values($value[$key]);
            $get_keys = array_shift($keys);
            $get_values = array_shift($val);

            $table_column = implode(",", $keys);
            // $table_value ="'" . implode("','", $val) . "'\n";
            $table_value ="'" . implode("','", $val) . "'";

            $output .= DB::insert(
            "INSERT INTO " . stripslashes($table) . "("
           . $table_column . ") VALUES(" . $table_value . ")"
         );

    }
}
?>

This is a function I found and later modified to export my databases including all the data and stored procedures and functions if any exists in the database.这是我发现并修改后的一个函数,用于导出我的数据库,包括所有数据以及存储过程和函数(如果数据库中存在)。 The code was written for a codeigniter application but you can easily convert it to laravel.该代码是为 codeigniter 应用程序编写的,但您可以轻松地将其转换为 laravel。

Codeigniter version:代码点火器版本:

    <?php
    if(!function_exists("export_database")){
    function export_database($bkpFileName = null){

        $ci =& get_instance();
        $targetTables = [];
        $newLine = "\r\n";

        $queryTables = $ci->db->query('SHOW TABLES');

        foreach($queryTables->result() as $table){
            $targetTables[] = $table->Tables_in_my_db;
        }

        foreach($targetTables as $table){
            $tableData = $ci->db->query('SELECT * FROM '.$table);
            $res = $ci->db->query('SHOW CREATE TABLE '.$table);

            $cnt = 0;
            $content = (!isset($content) ?  '' : $content) . $res->row_array()["Create Table"].";" . $newLine . $newLine;
            foreach($tableData->result_array() as $row){
                $subContent = "";
                $firstQueryPart = "";
                if($cnt == 0 || $cnt % 100 == 0){
                    $firstQueryPart .= "INSERT INTO {$table} VALUES ";
                    if($tableData->num_rows() > 1)
                        $firstQueryPart .= $newLine;
                }

                $valuesQuery = "(";
                foreach($row as $key => $value){
                    $valuesQuery .= $ci->db->escape($value) . ", ";
                }

                $subContent = $firstQueryPart . rtrim($valuesQuery, ", ") . ")";

                if( (($cnt+1) % 100 == 0 && $cnt != 0) || $cnt+1 == $tableData->num_rows())
                    $subContent .= ";" . $newLine;
                else
                    $subContent .= ",";

                $content .= $subContent;
                $cnt++;
            }
            $content .= $newLine;
        }

        $content = trim($content);

        //check for stored procedures
        $storedProcedures = $ci->db->query("SHOW PROCEDURE STATUS WHERE Db = '{$ci->db->database}'");
        if($storedProcedures->num_rows() > 0){
            foreach($storedProcedures->result() as $procedure){
                $data = $ci->db->query("SHOW CREATE PROCEDURE {$procedure->Name}");
                if($data->num_rows() > 0){
                    $dropProcedureSQL = "DROP PROCEDURE IF EXISTS {$procedure->Name};";
                    $sqlQuery = $data->row_array()["Create Procedure"];
                    $sqlQuery = preg_replace("/CREATE DEFINER=.+? PROCEDURE/", "CREATE PROCEDURE IF NOT EXISTS", $sqlQuery);
                    $sqlQuery = "\r\n" . $sqlQuery . "//";
                    $content .=  $newLine . $newLine . $dropProcedureSQL . $sqlQuery ;
                }
            }
        }

        //check for functions
        $functions = $ci->db->query("SHOW FUNCTION STATUS WHERE Db = '{$ci->db->database}';");
        if($functions->num_rows() > 0){
            foreach($functions->result() as $function){
                $data = $ci->db->query("SHOW CREATE FUNCTION {$function->Name}");
                if($data->num_rows() > 0){
                    $dropFunctionSQL = "DROP function IF EXISTS {$function->Name};";
                    $sqlQuery = $data->row_array()["Create Function"];
                    $sqlQuery = preg_replace("/CREATE DEFINER=.+? FUNCTION/", "CREATE FUNCTION IF NOT EXISTS", $sqlQuery);
                    $sqlQuery = "\r\n" . $sqlQuery . "//";
                    $content .=  $newLine . $newLine . $dropFunctionSQL . $sqlQuery ;
                }
            }
        }

        $dbBackupFile = FCPATH . BKP_FILE_DIR;
        if(is_null($bkpFileName))
            $dbBackupFile .= "{$ci->db->database}.sql";
        else
            $dbBackupFile .= "{$bkpFileName}.sql";

        $handle = fopen($dbBackupFile, "w+");
        fwrite($handle, $content);
        fclose($handle);

        return $dbBackupFile;
    }
}

Laravel version: Laravel 版本:

<?php
if(!function_exists("export_database")){
    function export_database($bkpFileName = null){

        //$ci =& get_instance();
        $targetTables = [];
        $newLine = "\r\n";

        $queryTables = DB::select(DB::raw('SHOW TABLES'));

        foreach($queryTables->result() as $table){
            $targetTables[] = $table->Tables_in_my_database;
        }

        foreach($targetTables as $table){
            $tableData = DB::select(DB::raw('SELECT * FROM '.$table));
            $res = DB::select(DB::raw('SHOW CREATE TABLE '.$table));

            $cnt = 0;
            $content = (!isset($content) ?  '' : $content) . $res->row_array()["Create Table"].";" . $newLine . $newLine;
            foreach($tableData as $row){
                $subContent = "";
                $firstQueryPart = "";
                if($cnt == 0 || $cnt % 100 == 0){
                    $firstQueryPart .= "INSERT INTO {$table} VALUES ";
                    if(count($tableData) > 1)
                        $firstQueryPart .= $newLine;
                }

                $valuesQuery = "(";
                foreach($row as $key => $value){
                    $valuesQuery .= $value . ", ";
                }

                $subContent = $firstQueryPart . rtrim($valuesQuery, ", ") . ")";

                if( (($cnt+1) % 100 == 0 && $cnt != 0) || $cnt+1 == count($tableData))
                    $subContent .= ";" . $newLine;
                else
                    $subContent .= ",";

                $content .= $subContent;
                $cnt++;
            }
            $content .= $newLine;
        }

        $content = trim($content);

        //check for stored procedures
        $storedProcedures = DB::select(DB::raw("SHOW PROCEDURE STATUS WHERE Db = '{$ci->db->database}'");
        if($storedProcedures->count() > 0){
            foreach($storedProcedures->result() as $procedure){
                $data = DB::select(DB::raw("SHOW CREATE PROCEDURE {$procedure->Name}"));
                if($data->count() > 0){
                    $dropProcedureSQL = "DROP PROCEDURE IF EXISTS {$procedure->Name};";
                    $sqlQuery = $data->row_array()["Create Procedure"];
                    $sqlQuery = preg_replace("/CREATE DEFINER=.+? PROCEDURE/", "CREATE PROCEDURE IF NOT EXISTS", $sqlQuery);
                    $sqlQuery = "\r\n" . $sqlQuery . "//";
                    $content .=  $newLine . $newLine . $dropProcedureSQL . $sqlQuery ;
                }
            }
        }

        //check for functions
        $functions = DB::select(DB::raw("SHOW FUNCTION STATUS WHERE Db = '{$ci->db->database}';"));
        if($functions->count() > 0){
            foreach($functions->result() as $function){
                $data = DB::select(DB::raw("SHOW CREATE FUNCTION {$function->Name}");
                if($data->count() > 0){
                    $dropFunctionSQL = "DROP function IF EXISTS {$function->Name};";
                    $sqlQuery = $data->row_array()["Create Function"];
                    $sqlQuery = preg_replace("/CREATE DEFINER=.+? FUNCTION/", "CREATE FUNCTION IF NOT EXISTS", $sqlQuery);
                    $sqlQuery = "\r\n" . $sqlQuery . "//";
                    $content .=  $newLine . $newLine . $dropFunctionSQL . $sqlQuery ;
                }
            }
        }

        /*$dbBackupFile = FCPATH . BKP_FILE_DIR;
        if(is_null($bkpFileName))
            $dbBackupFile .= "{$ci->db->database}.sql";
        else
            $dbBackupFile .= "{$bkpFileName}.sql";

        $handle = fopen($dbBackupFile, "w+");
        fwrite($handle, $content);
        fclose($handle);*/

        return $content;
    }
}

Note: I have tried my best to convert the above code from codeigniter to laravel.注意:我已尽力将上述代码从 codeigniter 转换为 laravel。 But since I don't have running instance of laravel to test it out I'm not sure it will work但是由于我没有运行 laravel 的实例来测试它,我不确定它会起作用

Write a写一个

command https://laravel.com/docs/5.6/artisan#writing-commands命令https://laravel.com/docs/5.6/artisan#writing-commands

with SSH mysqldump -uUSERNAME -p DATABASE > backup.sql and使用 SSH mysqldump -uUSERNAME -p DATABASE > backup.sql

schedule https://laravel.com/docs/5.6/scheduling and安排https://laravel.com/docs/5.6/scheduling

DONE :))完毕 :))

I refactored @Igor Ilic's answer to be laravel compatible and improved it a little bit, I hope it is useful :)我将@Igor Ilic 的答案重构为与laravel 兼容并对其进行了一些改进,我希望它有用:)

It is well tested with laravel 9使用 laravel 9 进行了很好的测试

function ExportDatabase(array $tablesToBackup = null, string $backupFilename = null): string
{
    $targetTables = [];
    $newLine = "\n";

    if ($tablesToBackup == null)
    {
        $queryTables = DB::select(DB::raw('SHOW TABLES'));
        foreach ($queryTables as $table)
        {
            $targetTables[] = $table->Tables_in_my_database;
        }
    }
    else
    {
        foreach ($tablesToBackup as $table)
        {
            $targetTables[] = $table;
        }
    }

    foreach ($targetTables as $table)
    {
        $tableData = DB::select(DB::raw('SELECT * FROM ' . $table));
        $res = DB::select(DB::raw('SHOW CREATE TABLE ' . $table))[0];

        $cnt = 0;
        $content = (!isset($content) ?  '' : $content) . $res->{"Create Table"} . ";" . $newLine . $newLine;
        foreach ($tableData as $row)
        {
            $subContent = "";
            $firstQueryPart = "";
            if ($cnt == 0 || $cnt % 100 == 0)
            {
                $firstQueryPart .= "INSERT INTO {$table} VALUES ";
                if (count($tableData) > 1)
                {
                    $firstQueryPart .= $newLine;
                }
            }

            $valuesQuery = "(";
            foreach ($row as $key => $value)
            {
                $valuesQuery .= "'$value'" . ", ";
            }

            $subContent = $firstQueryPart . rtrim($valuesQuery, ", ") . ")";

            if ((($cnt + 1) % 100 == 0 && $cnt != 0) || $cnt + 1 == count($tableData))
            {
                $subContent .= ";" . $newLine;
            }
            else
            {
                $subContent .= ",";
            }

            $content .= $subContent;
            $cnt++;
        }

        $content .= $newLine;
    }

    $content = trim($content);

    if (is_null($backupFilename))
    {
        return $content;
    }

    $dbBackupFile = storage_path('backups/database/');
    if (!File::exists($dbBackupFile))
    {
        File::makeDirectory($dbBackupFile, 0755, true);
    }

    $dbBackupFile .= "{$backupFilename}.sql";

    $handle = fopen($dbBackupFile, "w+");
    fwrite($handle, $content);
    fclose($handle);

    return $content;
}

I created this specifically to clone WordPress subsite tables from one database to another (hence, the $prefix parameter).我创建这个专门用于将 WordPress 子站点表从一个数据库克隆到另一个数据库(因此, $prefix参数)。 Leaving the default value of $prefix ('%') will get all tables in the source database.保留$prefix ('%') 的默认值将获取源数据库中的所有表。

This has been tested with Laravel 9.x.这已通过 Laravel 9.x 测试。

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection;

class CloneService
{
    public function clone(string $sourceDb, string $destDb, string $prefix): void
    {
        $tables = $this->getTables($sourceDb, $prefix);

        if ($tables->count() > 0) {
            $tables->each(function ($table) use ($sourceDb, $destDb) {
                $success = DB::statement("CREATE TABLE {$destDb}.{$table} LIKE {$sourceDb}.{$table};");

                if ($success) {
                    $this->insertData($sourceDb, $destDb, $table);
                }
            });
        }
    }

    public function getTables(string $dbName, string $prefix = '%'): Collection
    {
        $tables = collect();

        // Escape underscores
        $prefix = str_replace('_', '\_', $prefix);
        collect(DB::select("SHOW TABLES FROM {$dbName} LIKE '{$prefix}%';"))
            ->each(function ($result) use (&$tables) {
                // Convert the stdClass to an array, and get the first element
                $table = current((array)$result);
                $tables->push($table);
            });

        return $tables;
    }

    protected function insertData(string $sourceDb, string $destDb, string $table): void
    {
        $tableData = DB::select(DB::raw("SELECT * FROM {$sourceDb}.{$table};"));

        collect($tableData)->each(function ($row) use ($destDb, $table) {
            $rowData = get_object_vars($row);
            // Create a comma-separated string of the columns
            $columns = implode(',', array_keys($rowData));
            $values = array_values($rowData);
            // Create a comma-separated string of "?'s"
            $prep = implode(',', array_fill(0, count($values), '?'));

            $query = "INSERT INTO {$destDb}.{$table} ({$columns}) VALUES ({$prep})";

            DB::insert($query, $values);
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM