Instantly share code, notes, and snippets.

Embed
What would you like to do?
Laravel Spatie backup with controller routes and views
<?php
namespace App\Http\Controllers;
use Alert;
use Artisan;
use Carbon\Carbon;
use Log;
use Spatie\Backup\Helpers\Format;
use Storage;
class BackupController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$disk = Storage::disk(config('backup.backup.destination.disks')[0]);
$files = $disk->files(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' => Carbon::createFromTimestamp($disk->lastModified($f)),
];
}
}
// reverse the backups, so the newest one would be on top
$backups = array_reverse($backups);
return view("admin.backups")->with(compact('backups'));
}
public function create()
{
try {
// start the backup process
Artisan::call('backup:run', ['--only-db' => 'true']);
$output = 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;
$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.");
}
}
}
@if (count($backups))
<table class="table table-striped table-bordered">
<thead class="thead-dark">
<tr>
<th>File</th>
<th>Size</th>
<th>Date</th>
<th>Age</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach($backups as $backup)
<tr>
<td>{{ $backup['file_name'] }}</td>
<td>{{ $backup['file_size'] }}</td>
<td>
{{ date('d/M/Y, g:ia', strtotime($backup['last_modified'])) }}
</td>
<td>
{{ diff_date_for_humans($backup['last_modified']) }}
</td>
<td class="text-right">
<a class="btn btn-primary" href="{{ url('backup/download/'.$backup['file_name']) }}">
<i class="fas fa-cloud-download"></i> Download</a>
<a class="btn btn-xs btn-danger" data-button-type="delete" href="{{ url('backup/delete/'.$backup['file_name']) }}">
<i class="fal fa-trash"></i>
Delete
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<div class="text-center py-5">
<h1 class="text-muted">No existen backups</h1>
</div>
@endif
@extends('layouts.crud')
@section('content')
<div class="container -body-block pb-5">
@card(['title' => 'Backups de la base de datos'])
@component('ui.menu-nav')
<li class="nav-item active mr-3">
<a href="{{ url('backup/create') }}" class="nav-link text-primary" title="Crear nuevo backup">
<i class="far fa-plus" aria-hidden="true"></i> Crear nuevo backup
</a>
</li>
@endcomponent
<div class="py-4"></div>
@include('admin.backups-table')
<div class="py-3"></div>
@endcard
</div>
@endsection
<div class="row">
<div class="col">
<div class="card">
@isset($title)
<div class="card-header">{{$title}}</div>
@endisset
<div class="card-body">
{{ $slot }}
</div>
</div>
</div>
</div>
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Sunnyface.com') }}</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<script>
window.AppRootData = {!! json_encode([
'csrfToken' => csrf_token(),
'state' => ['user' => Auth::user()]
]) !!};
</script>
</head>
<body>
<div id="app" class="boxx-wrapper">
@include('parts.header.admin')
<div class="album py-5 bg-light">
@include('ui.errors')
@yield('content')
</div>
@include('parts.footer')
@stack('modals')
</div>
<!-- Scripts -->
@if (app()->isLocal())
<script src="{{ mix('js/app.js') }}"></script>
@else
<script src="{{ mix('js/manifest.js') }}"></script>
<script src="{{ mix('js/vendor.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
@endif
@stack('scripts')
</body>
</html>
<?php
use Carbon\Carbon;
function diff_date_for_humans(Carbon $date) : string
{
return (new Jenssegers\Date\Date($date->timestamp))->ago();
}
function diff_string_for_humans($stringDate) : string
{
$date = Jenssegers\Date\Date::createFromFormat('Y-m-d H:i:s', $stringDate);
return (new Jenssegers\Date\Date($date))->ago();
}
function scannerTableLabel($stringDate) : string
{
$now = Jenssegers\Date\Date::now();
$date = Jenssegers\Date\Date::createFromFormat('Y-m-d H:i:s', $stringDate);
$printDate = (new Jenssegers\Date\Date($date))->ago();
$color = $now > $date ? 'info' : 'danger';
$res = '<span class="badge badge-'.$color.'" style="color:white;">SCANNER: ';
$res .= $printDate ;
$res .= '</span>';
return $res;
}
<nav class="navbar navbar-expand-md navbar-light bg-light">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#table-actions-nav-menu" aria-controls="table-actions-nav-menu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="table-actions-nav-menu">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
{{ $slot }}
</ul>
</div>
</nav>
Route::get('backup', 'BackupController@index');
Route::get('backup/create', 'BackupController@create');
Route::get('backup/download/{file_name}', 'BackupController@download');
Route::get('backup/delete/{file_name}', 'BackupController@delete');
@kikoseijo

This comment has been minimized.

Show comment
Hide comment
@kikoseijo

kikoseijo Feb 22, 2018

No está al completo, pero le falta lo mínimo.

Credits

Special thanks to supporters and clients that provide me with enough time to work on contributing to develop this packages for the WWW.

DevOps Web development
AppDev Mobile aplications
SocialApp Residents mobile application
KikoSeijo.com Freelance senior programmer


Created by Kiko Seijo
Owner

kikoseijo commented Feb 22, 2018

No está al completo, pero le falta lo mínimo.

Credits

Special thanks to supporters and clients that provide me with enough time to work on contributing to develop this packages for the WWW.

DevOps Web development
AppDev Mobile aplications
SocialApp Residents mobile application
KikoSeijo.com Freelance senior programmer


Created by Kiko Seijo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment