2026-08-20-01-add-category-id.php 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. <?php
  2. declare(strict_types=1);
  3. // Beispielmigration für ein Projekt mit JSON-Dateien:
  4. // ergänzt ein neues Feld in allen bestehenden Datensätzen.
  5. //
  6. // Idempotent: bereits ergänzte Datensätze bleiben unverändert, damit die
  7. // Migration nach einem Teilfehler gefahrlos erneut laufen kann.
  8. return function (array $context): void {
  9. $file = $context["app_root"] . "/data/products.json";
  10. if (!is_file($file)) {
  11. return;
  12. }
  13. $data = json_decode((string) file_get_contents($file), true);
  14. if (!is_array($data)) {
  15. throw new RuntimeException("products.json ist nicht lesbar oder kein gültiges JSON.");
  16. }
  17. $changed = false;
  18. foreach ($data as $index => $product) {
  19. if (is_array($product) && !array_key_exists("category_id", $product)) {
  20. $data[$index]["category_id"] = null;
  21. $changed = true;
  22. }
  23. }
  24. if (!$changed) {
  25. return;
  26. }
  27. $json = json_encode(
  28. $data,
  29. JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
  30. );
  31. if ($json === false) {
  32. throw new RuntimeException("products.json konnte nicht kodiert werden.");
  33. }
  34. // Atomar schreiben, damit ein Abbruch keine halbe Datei hinterlässt.
  35. $tmpFile = $file . ".tmp";
  36. if (file_put_contents($tmpFile, $json, LOCK_EX) === false || !rename($tmpFile, $file)) {
  37. @unlink($tmpFile);
  38. throw new RuntimeException("products.json konnte nicht geschrieben werden.");
  39. }
  40. };