stackprogramer wrote a reply+100 XP
4mos ago
stackprogramer liked a comment+100 XP
4mos ago
stackprogramer liked a comment+100 XP
4mos ago
stackprogramer wrote a reply+100 XP
4mos ago
Hi, I work on a custom CMS based on Laravel. I want to develop a package restore (alike duplicator Wordpress) for Laravel. Our restore package is GUI and easy to use for end users. Really my goal is reverse engineering duplicator wp for our custom CMS. In duplicator it had a chunk to chunk importing (files and database).
Thanks, Rather we need create our custom package for Custom CMS. I checked it before. https://packagist.org/packages/spatie/laravel-backup
stackprogramer wrote a reply+100 XP
4mos ago
stackprogramer wrote a reply+100 XP
4mos ago
stackprogramer started a new conversation+100 XP
4mos ago
I need a chunk restore method, because db and files are too big, files extracts successfully. but for db after ajax request time 2 and 3 we had error in provider....middlewares.... I added exception for restore method but it wasn't fixed.....
Error:
[2025-12-18 14:53:53] local.ERROR: Attempt to read property "headers" on null {"userId":1,"exception":"[object] (ErrorException(code: 0): Attempt to read property \"headers\" on null at /home/adam/public_html/local/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php:191)
[stacktrace]
Solutio that i tested but not solved it.
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
//
'/restore', // or whatever your actual route path is
'restore', // Matches your /restore/ path
'restore/*', // Matches any sub-paths if necessary
];
}
Restore method
public function restore(Request $request)
{
// 1. Prevent Timeouts
@set_time_limit(0);
@ini_set('memory_limit', '512M');
$fileName = $request->input('backup_file');
$phase = $request->input('phase', 'extract');
$fileIndex = (int)$request->input('file_index', 0);
$offset = (int)$request->input('offset', 0);
$zipPath = storage_path("app/backups/$fileName");
$sqlTempPath = storage_path("app/backups/temp_restore.sql");
// --- PHASE 1: EXTRACT FILES ---
if ($phase === 'extract') {
$zip = new ZipArchive;
if ($zip->open($zipPath) === TRUE) {
$totalFiles = $zip->numFiles;
$batchSize = 150; // Increased batch size for speed
for ($i = $fileIndex; $i < $totalFiles && ($i - $fileIndex) < $batchSize; $i++) {
$entryName = $zip->getNameIndex($i);
if ($entryName === 'database.sql') {
File::put($sqlTempPath, $zip->getFromIndex($i));
} else {
$dest = str_starts_with($entryName, 'local/')
? base_path(substr($entryName, 6))
: dirname(base_path()) . '/' . $entryName;
if (!str_ends_with($entryName, '/')) {
File::ensureDirectoryExists(dirname($dest));
File::put($dest, $zip->getFromIndex($i));
}
}
}
$zip->close();
if ($i >= $totalFiles) {
$this->sendRawJson([
'status' => 'progress',
'phase' => 'database',
'percent' => 50,
'message' => 'Files OK. Preparing Database...'
]);
}
$this->sendRawJson([
'status' => 'progress',
'phase' => 'extract',
'file_index' => $i,
'percent' => round(($i / $totalFiles) * 50),
'message' => "Extracting: $i/$totalFiles"
]);
}
}
// --- PHASE 2: DATABASE IMPORT (RAW PDO) ---
if ($phase === 'database') {
if (!file_exists($sqlTempPath)) {
$this->sendRawJson(['status' => 'error', 'message' => 'SQL File missing.']);
}
// Use RAW PDO to bypass Laravel's Model/Provider checks
$pdo = \DB::connection()->getPdo();
$pdo->exec("SET FOREIGN_KEY_CHECKS=0;");
$handle = fopen($sqlTempPath, 'r');
fseek($handle, $offset);
$startTime = microtime(true);
// Run for 4 seconds per request to stay safe from server timeouts
while (!feof($handle) && (microtime(true) - $startTime) < 4) {
$line = fgets($handle);
$trimmedLine = trim($line);
if ($trimmedLine && !str_starts_with($trimmedLine, '--') && !str_starts_with($trimmedLine, '/*')) {
try {
$pdo->exec($line);
} catch (\Exception $e) {
\Log::error("SQL Import Line Error: " . $e->getMessage());
}
}
}
$newOffset = ftell($handle);
$done = feof($handle);
$totalSize = filesize($sqlTempPath);
fclose($handle);
if ($done) {
@unlink($sqlTempPath);
$this->sendRawJson([
'status' => 'done',
'html' => '<div class="alert alert-success"><h3>Success!</h3><p>System Restored Successfully.</p><a href="' . url('/') . '" class="btn btn-primary">Go to Home</a></div>'
]);
}
$this->sendRawJson([
'status' => 'progress',
'phase' => 'database',
'offset' => $newOffset,
'percent' => 50 + round(($newOffset / $totalSize) * 50),
'message' => 'Importing Database Records...'
]);
}
}
stackprogramer wrote a reply+100 XP
5mos ago
stackprogramer liked a comment+100 XP
5mos ago
stackprogramer started a new conversation+100 XP
5mos ago