Fix: Updating Wipe Catalog Command to force delete products instead of the soft delete
This commit is contained in:
@@ -50,7 +50,12 @@ class WipeCatalogCommand extends Command
|
||||
|
||||
public function handle(OtpService $otp): int
|
||||
{
|
||||
$productCount = Product::count();
|
||||
// withTrashed() — a prior soft-delete-only bug in this command
|
||||
// (fixed in wipe() below) could leave ghost rows a plain count()
|
||||
// would never see, silently reporting "nothing to do" while they
|
||||
// sit there breaking other things (e.g. the admin's own global
|
||||
// search, which assumes every returned product has variants).
|
||||
$productCount = Product::withTrashed()->count();
|
||||
|
||||
if ($productCount === 0) {
|
||||
$this->info('No products exist — nothing to do.');
|
||||
@@ -146,7 +151,16 @@ class WipeCatalogCommand extends Command
|
||||
ImportMapping::whereIn('source_type', ['product', 'variant', 'image'])->delete();
|
||||
|
||||
while (true) {
|
||||
$products = Product::with(['variants', 'associations', 'inverseAssociations'])
|
||||
// withTrashed(): Product/ProductVariant both use SoftDeletes
|
||||
// — a plain query would stop seeing a product the moment
|
||||
// forceDelete() below actually removes it, which is fine, but
|
||||
// WITHOUT withTrashed() here this loop would never even
|
||||
// fetch a row that a previous, buggy run of this command
|
||||
// (or any other code) had already soft-deleted without
|
||||
// force-deleting it. Ghost rows like that are exactly what
|
||||
// this command exists to remove.
|
||||
$products = Product::withTrashed()
|
||||
->with(['variants' => fn ($query) => $query->withTrashed(), 'associations', 'inverseAssociations'])
|
||||
->limit(100)
|
||||
->get();
|
||||
|
||||
@@ -161,10 +175,22 @@ class WipeCatalogCommand extends Command
|
||||
|
||||
foreach ($product->variants as $variant) {
|
||||
$variant->prices()->delete();
|
||||
$variant->delete();
|
||||
// NOT delete() — Product/ProductVariant both use
|
||||
// SoftDeletes, and a plain delete() only sets
|
||||
// deleted_at, leaving the row (and, for Product, its
|
||||
// media) sitting in the table. This command's whole
|
||||
// purpose is an irreversible wipe; a soft-deleted
|
||||
// ghost row is the opposite of that. Caught in
|
||||
// practice — a prior run's plain delete() left 185
|
||||
// ghost Product rows with zero real variants, which
|
||||
// then crashed the admin's own global search
|
||||
// (Lunar\Admin\Filament\Resources\ProductResource::
|
||||
// getGlobalSearchResultDetails() assumes
|
||||
// $record->variants->first() is never null).
|
||||
$variant->forceDelete();
|
||||
}
|
||||
|
||||
$product->delete();
|
||||
$product->forceDelete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user