اذهب إلى المحتوى
  • 0

عمل Backup لقاعدة البيانات في laravel

Mahmoud Alrashidi

السؤال

Recommended Posts

  • 0

يُمكنك إنشاء أمر artisan خاص يقوم بعمل النُسخة التي تريدها عند تنفيذه و لإنشاء ذلك الأمر نقوم بدايةً بتنفيذ الأمر التالي:

php artisan make:command DatabaseBackUp

سيُنشئ لك الأمر صنف بالإسم DatabaseBackUp في المسار:  app/Console/Commands/DatabaseBackUp تقوم بالتعديل عليه ليُصبح بالشكل التالي:

<?php

namespace App\Console\Commands;

use Carbon\Carbon;
use Illuminate\Console\Command;

class DatabaseBackUp extends Command
{

  protected $signature = 'database:backup';

  protected $description = 'create database backup';

  public function __construct()
  {
    parent::__construct();
  }

  public function handle()
  {
    $filename = "backup-" . Carbon::now()->format('Y-m-d') . ".gz";

    $command = "mysqldump --user=" . env('DB_USERNAME') ." --password=" . env('DB_PASSWORD') . " --host=" . env('DB_HOST') . " " . env('DB_DATABASE') . "  | gzip > " . storage_path() . "/app/backup/" . $filename;

    $returnVar = NULL;
    $output  = NULL;

    exec($command, $output, $returnVar);
  }
}

بعد ذلك تقوم بإنشاء مُجلد backup في المسار: storage/app/backup

و عندما تريد إنشاء نُسخة من قاعدة البيانات فقط تقوم بتنفيذ الأمر:

php artisan database:backup

و هذا الأمر سيقوم بإنشاء نُسخة من قاعدة البيانات بنفس تاريخ تنفيذ الأمر. في المُجلد الذي أنشأناه.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

يمكنك استخدام حزمة spatie/laravel-backup والموقع الرسمي لها هنا

بحيث يمكنك استخدام الأمر التالي لاستدعاء الحزمة 

composer require spatie/laravel-backup

ومن ثم بعد استدعاء الحزمة نريد إضافة ملف backup.php إلى مجلد config عن طريق الأمر التالي 

php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"

ويمكنك من ملف app/Console/Kernel.php وضع امر لأخذ نسخة احتياطية بشكل تلقائي عن طريق إضافة 

protected function schedule(Schedule $schedule)
{
   $schedule->command('backup:clean')->daily()->at('01:00');
   $schedule->command('backup:run')->daily()->at('01:30');
}

ومن ثم تشغيل الأمر التالي

php artisan backup:run

ويمكنك انشاء Controller لحفظ و تنزيل نسخة احتياطية عن طريق مثلا لوحة التحكم فيكون شكل الcontroller هكذا 

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

use Alert;
use App\Http\Requests;
use Artisan;
use Log;
use Storage;
use Spatie\Backup\Helpers\Format;

class BackupController extends Controller
{
    public function index()
    {
        $disk = Storage::disk(config('backup.backup.destination.disks')[0]);
        //$disk = storage_path('app');
		//dd(storage_path('app') . DIRECTORY_SEPARATOR . config('backup.backup.name'));
        //$disk = Storage::disk(config('backup.backup.name')[0]);
		//dd(config('backup.name'));
		//dd(config('backup.name.backup.destination.disks')[0]);
		//echo (config('CropFix.backup.destination.disks')[0]);
        $files = $disk->files(config('backup.backup.name'));
        //$files = storage_path('app') . DIRECTORY_SEPARATOR . config('backup.backup.name');
        $backups = [];
        // make an array of backup files, with their filesize and creation date
        foreach ($files as $k => $f) {
            // only take the zip files into account
            if (substr($f, -4) == '.zip' && $disk->exists($f)) {
                $backups[] = [
                    'file_path' => $f,
                    'file_name' => str_replace(config('backup.backup.name') . '/', '', $f),
                    'file_size' => Format::humanReadableSize($disk->size($f)),
                    'last_modified' => date('m/d/Y  H:i:s', $disk->lastModified($f)),
                ];
            }
        }
        // reverse the backups, so the newest one would be on top
        $backups = array_reverse($backups);

        return view("admin.backups.index")->with(compact('backups'));
    }

    public function create()
    {
        try {
            // start the backup process
            //Artisan::call('backup:run');
			$parameters = [];
			$outputBuffer = null;
			Artisan::call('backup:run', $parameters, $outputBuffer);
            //Artisan::call('backup:run');
            $output = Artisan::output();
			//dd(Artisan::output());
            // log the results
            //Log::info("Backpack\BackupManager -- new backup started from admin interface \r\n" . $output);
            // return the results as a response to the ajax call
            //Alert::success('New backup created');
            return redirect()->back();
        } catch (Exception $e) {
            Flash::error($e->getMessage());
            return redirect()->back();
        }
    }

    /**
     * Downloads a backup zip file.
     *
     * TODO: make it work no matter the flysystem driver (S3 Bucket, etc).
     */
    public function download($file_name)
    {
        //$file = config('backup.backup.name') . '/' . $file_name;
        $file = config('backup.backup.name') . '/' . $file_name;
        $disk = Storage::disk(config('backup.backup.destination.disks')[0]);
        if ($disk->exists($file)) {
            $fs = Storage::disk(config('backup.backup.destination.disks')[0])->getDriver();
            $stream = $fs->readStream($file);

            return \Response::stream(function () use ($stream) {
                fpassthru($stream);
            }, 200, [
                "Content-Type" => $fs->getMimetype($file),
                "Content-Length" => $fs->getSize($file),
                "Content-disposition" => "attachment; filename=\"" . basename($file) . "\"",
            ]);
        } else {
            abort(404, "The backup file doesn't exist.");
        }
    }

    /**
     * Deletes a backup file.
     */
    public function delete($file_name)
    {
        $disk = Storage::disk(config('backup.backup.destination.disks')[0]);
        if ($disk->exists(config('backup.backup.name') . '/' . $file_name)) {
            $disk->delete(config('backup.backup.name') . '/' . $file_name);
            return redirect()->back();
        } else {
            abort(404, "The backup file doesn't exist.");
        }
    }
	
	function humanFilesize($size, $precision = 2) 
	{
		$units = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
		$step = 1024;
		$i = 0;

		while (($size / $step) > 0.9) {
			$size = $size / $step;
			$i++;
		}
		
		return round($size, $precision).$units[$i];
	}
}

و ملف view الخاص controller يكون بالشكل التالي 

@extends('admin.layout.app')
@section('content_header')
	<h1>النسخ الاحتياطية</h1>
      <ol class="breadcrumb">
        <li><a href="{{ route('dashboard') }}"><i class="fa fa-dashboard"></i> لوحة التجكم</a></li>
        <li><a href="{{ route('users.index') }}">أدارة النسخ الاحتياطية</a></li>
        <li class="active">النسخ الاحتياطية</li>
      </ol>
@endsection

@section('content')
<div class="row">
	<div class="col-md-12">
	  <div class="box">
		<div class="box-header with-border">
			<a href="{{ route('backups.create') }}" class="btn btn-danger float-left" style="width: 200px; float: left;">أنشاء نسخة أحتياطية</a>
		</div><!-- /.box-header -->
		<div class="box-body">	
			@if (count($backups))		
			<table class="table table-bordered">
				<tbody>
					<tr>
						<th>الملف</th>
						<th>الحجم</th>
						<th>التاريخ</th>
						<th>المدة</th>
						<th></th>
					</tr>
					@foreach($backups as $backup)
						<tr>
							<td>{{ $backup['file_name'] }}</td>
							<td>{{ ($backup['file_size']) }}</td>
							<td>
								{{ ($backup['last_modified']) }}
							</td>
							<td>
								{{ ($backup['last_modified']) }}
							</td>
							<td class="text-right">
								<a class="btn btn-xs btn-default"
								   href="{{ route('backups.download', $backup['file_name']) }}"><i
										class="fa fa-cloud-download"></i> تحميل</a>
								<a class="btn btn-xs btn-danger" data-button-type="delete"
								   href="{{ route('backups.delete', $backup['file_name']) }}"><i class="fa fa-trash-o"></i>
									حذف</a>
							</td>
						</tr>
					@endforeach
					@else 
						<tr>
						  <td colspan="4">لا توجد نسخ احتياطية</td>
						</tr>
					@endif
				</tbody>
			</table>
		</div><!-- /.box-body -->
	  </div><!-- /.box -->
	</div><!-- /.col -->
</div>
@endsection

طبعا هذه الأكواد عبارة عن أمثلة. 

يمكنك زيارة التوثيق الرسمي للحزمة و متابعة جميع المميزات التي تقدمها الحزمة أيضا.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...