Fix: HTTP 500 bei Foto ohne Preis (price_decimal NULL + Foto-Validierung)

- Migration: price_decimal sicher nullable (Mediathek/Foto-only)

- Validierung: mimes statt File::types, max 15360 KB

Made-with: Cursor
This commit is contained in:
Stefan Zwischenbrugger 2026-03-30 17:58:12 +02:00
parent 8e11f3efca
commit a590a74cab
3 changed files with 30 additions and 14 deletions

View File

@ -2,8 +2,8 @@
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\File;
class ToggleShoppingItemRequest extends FormRequest
{
@ -25,7 +25,7 @@ class ToggleShoppingItemRequest extends FormRequest
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
@ -37,11 +37,7 @@ class ToggleShoppingItemRequest extends FormRequest
'price_decimal' => ['nullable', 'numeric', 'min:0', 'max:999999.99'],
'tier_min_qty' => ['nullable', 'integer', 'min:2', 'max:999999'],
'tier_price_decimal' => ['nullable', 'numeric', 'min:0', 'max:999999.99'],
'photo' => [
'nullable',
File::types(['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'])
->max(15 * 1024),
],
'photo' => ['nullable', 'file', 'max:15360', 'mimes:jpeg,jpg,png,gif,webp,heic,heif'],
];
}
@ -63,6 +59,7 @@ class ToggleShoppingItemRequest extends FormRequest
'tier_price_decimal.min' => 'Der Staffelpreis darf nicht negativ sein.',
'tier_price_decimal.max' => 'Der Staffelpreis ist zu gross.',
'photo.max' => 'Das Foto darf maximal 15 MB gross sein.',
'photo.mimes' => 'Das Foto muss ein Bild sein (jpg, png, gif, webp, heic, heif).',
'photo.uploaded' => 'Das Foto konnte nicht hochgeladen werden. Haeufig: Datei zu gross fuer die PHP-Grenze auf dem Server (upload_max_filesize / post_max_size). Bitte ein kleineres Bild waehlen oder die Server-Limits erhoehen (siehe scripts/apache-einkauf-debian-setup.sh, Abschnitt PHP-Uploads).',
];
}

View File

@ -2,8 +2,8 @@
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\File;
class UpdateShoppingItemRequest extends FormRequest
{
@ -20,7 +20,7 @@ class UpdateShoppingItemRequest extends FormRequest
}
/**
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
@ -33,11 +33,8 @@ class UpdateShoppingItemRequest extends FormRequest
'price_decimal' => ['nullable', 'numeric', 'min:0', 'max:999999.99'],
'tier_min_qty' => ['nullable', 'integer', 'min:2', 'max:999999'],
'tier_price_decimal' => ['nullable', 'numeric', 'min:0', 'max:999999.99'],
'photo' => [
'nullable',
File::types(['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'])
->max(15 * 1024),
],
// max = Kilobyte (15360 = 15 MB). mimes: zuverlaessiger als File::types bei iOS/Mediathek-MIME.
'photo' => ['nullable', 'file', 'max:15360', 'mimes:jpeg,jpg,png,gif,webp,heic,heif'],
];
}
@ -59,6 +56,7 @@ class UpdateShoppingItemRequest extends FormRequest
'tier_price_decimal.min' => 'Der Staffelpreis darf nicht negativ sein.',
'tier_price_decimal.max' => 'Der Staffelpreis ist zu gross.',
'photo.max' => 'Das Foto darf maximal 15 MB gross sein.',
'photo.mimes' => 'Das Foto muss ein Bild sein (jpg, png, gif, webp, heic, heif).',
'photo.uploaded' => 'Das Foto konnte nicht hochgeladen werden. Haeufig: Datei zu gross fuer die PHP-Grenze auf dem Server (upload_max_filesize / post_max_size). Bitte ein kleineres Bild waehlen oder die Server-Limits erhoehen (siehe scripts/apache-einkauf-debian-setup.sh, Abschnitt PHP-Uploads).',
];
}

View File

@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
/**
* Absicherung: Foto ohne Preis speichern (price_decimal NULL).
* Falls 2026_03_30_000400 auf einem Server nicht lief, verhindert MySQL sonst HTTP 500.
*/
return new class extends Migration
{
public function up(): void
{
DB::statement('ALTER TABLE item_price_logs MODIFY price_decimal DECIMAL(10,2) NULL');
}
public function down(): void
{
// Kein NOT NULL-Rollback: sonst Konflikt mit bestehenden Zeilen ohne Preis (nur Foto).
}
};