在Laravel中创建备份控制器

时间:2018-07-12 16:45:53

标签: php mysql laravel

我没有编程经验。我试图在laravel中创建一个备份表的控制器。这些表已正确备份,但是我收到一些评论说我的代码很容易被破坏。我一直在尽力而为,但是我真的很精疲力尽,感到沮丧。 我有一个表,表中的每一行占用1到10 MB的内存。表100中的总行。最大内存量(memory_limit)设置为35 MB。什么是解决此问题的最佳方法?我真的很感谢任何建议或帮助。这是我的代码:

  1. BackupController类

    <?php
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Storage;
    use Illuminate\Database\Events\StatementPrepared; // set the fetch mode
    use Illuminate\Support\Facades\Cache;
    use Carbon\Carbon;
    use Illuminate\Support\Facades\Schema;
    use DB;
    use App\Post;
    use App\User;
    use App\Jobs\BackupTableJob;
    use Artisan;
    
    class BackupController extends Controller
    {
        const MAX_VALUE = 35000; //kilobytes 
    
        public function lockTable()
        {
            // lock all tables
            DB::unprepared('FLUSH TABLES WITH READ LOCK;');
        }
    
        public function setQueueJob(User $user, Post $post)
        {
            BackupTableJob::dispatch($user, $post)
                ->delay(Carbon::now()
                ->addSeconds(5));
            // Artisan::call('queue:work');     
        }
    
        public function unlockTable()
        {
            // unlock all tables
            DB::unprepared('UNLOCK TABLES');
        }
    
        public function queryFetch($data)
        {
            $pdo  = DB::connection()->getPdo();
            $stmt = $pdo->prepare($data);
            $stmt->execute();
            // $stmt = $pdo->query($data);
            $results = $stmt->fetch();
            return $results;
        }
    
        public function create(Request $request)
        {
            $this->setPdoMode();
            $numTables = DB::select("SHOW TABLES");
            $countUserRecords = User::count();
            $countPostRecords = Post::count();
    
            return view('backup', compact('numTables','countUserRecords', 'countPostRecords'));
        }
    
        public function setPdoMode()
        {
            \Event::listen(StatementPrepared::class, function($event) {
            $event->statement->setFetchMode(\PDO::FETCH_ASSOC);});
        }
    
        // public function backup(Request $request, User $user, Post $post)
        public function backup(Request $request, User $user, Post $post)
        {
           $this->setQueueJob($user, $post);          
           if ($request->all()) {
               $tables = request('table');
               $output = '';     
               foreach ($tables as $key => $table) {  
                   $this->lockTable();
                   $show_table_query = $this->queryFetch("SHOW CREATE TABLE {$table}");
                   $output .="\n" . $show_table_query[1] . ";\n";
                   $this->setPdoMode();
                   $single_result = DB::select("SELECT * FROM {$table}");
                   $output .= $this->getTableData($single_result, $table);
                   $output .= $this->cacheData($table, $output); 
               }
               if ($this->checkFileSize($output)) {
                   return redirect()->route('create'); 
               }                  
            }             
            return redirect()->route('backupError'); 
        }
    
        // Stores the file in this location: storage/app
        public function download($output)
        {
            $dt = Carbon::now();
            $file_name = 'backup_on[' . $dt->format('y-m-d H-i-s') . '].sql';
            Storage::disk('local')->put($file_name, $output);
        }
    
        public function getTableData($single_result, $table) 
        {
            $this->unlockTable();
            $output = '';
            foreach ($single_result as $key => $table_val) {
                if ($table === "posts" || $table === "users") {
                    $output .= "\nINSERT INTO $table("; 
                    $output .= "" .addslashes(implode(", ", array_keys($table_val))) . ") VALUES(";
                    $output .= "'" . addslashes(implode("','", array_values($table_val))) . "');\n";
                }  
            }
            // $output .= $this->cacheData($table, $output);   
            return $output;
        }
    
        public function checkFileSize($file)
        {
            $file_size = strlen($file);
            // convert bytes to kilobytes 
            $file_size = round($file_size / 1024, 0, PHP_ROUND_HALF_UP);
            if ($file_size <= self::MAX_VALUE) {
                $this->download($file);
                return true;
            } 
            return false;               
        }
    
        public function cacheData($table, $data)
        {
            // $table = $table;
            $start = microtime(true);
            $data = Cache::remember('table', 10, function() use ($table){
                return DB::table($table)->get();
            });
            $duration = (microtime(true) -$start) * 1000;
    
            \Log::info("From cache: " . $duration .' ms');
            return $data;
        }
     }
    
  2. BackupTableJob类

    <?php
    
    namespace App\Jobs;
    
    use App\User;
    use App\Post;
    use App\Http\Controllers\BackupController;
    use Illuminate\Http\Request;
    
    use Illuminate\Bus\Queueable;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Foundation\Bus\Dispatchable;
    
    class BackupTableJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable; //SerializesModels;
    
        protected $user;
        protected $post;
    
        /**
         * Create a new job instance.
         *
         * @return void
         */
        public function __construct(User $user, Post $post)
        // public function __construct()
        {
            $this->user = $user;
            $this->post = $post;
        }
    
        /**
         * Execute the job.
         *
         * @return void
         */
        public function handle()
        {
            // $this->user->save();
            // $this->post->save();
        }
    }
    

1 个答案:

答案 0 :(得分:0)

您不需要使用PHP处理该数据。您可以在laravel中简单地使用原始SQL查询:

SELECT *
INTO tableToBeBackedUp
FROM currentTable;