ithilbert / laravel-kit
Tools für das Programmieren mit Laravel
Requires
- php: ^8.5
- illuminate/console: ^12.0 || ^13.0
- illuminate/contracts: ^12.0 || ^13.0
- illuminate/database: ^12.0 || ^13.0
- illuminate/http: ^12.0 || ^13.0
- illuminate/routing: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- illuminate/view: ^12.0 || ^13.0
Requires (Dev)
- orchestra/testbench: ^10.0 || ^11.0
- phpunit/phpunit: ^11.5 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-13 21:03:55 UTC
README
Beschreibung: Tools für das Programmieren mit Laravel.
Dokumentation
Die ausführliche Dokumentation befindet sich im Ordner .project/doku/:
Vue-Komponenten (Tailwind)
- DataTable-Komponente — generische DataTables.net-Kapselung mit Filter-Zeile, Aktions-Spalte und Server-/Client-side Modus
Installation
composer require ithilbert/laravel-kit
Kit-Components (Blade)
Kit-Components sind Blade-Components mit dem Präfix kit. Aufruf: <x-kit::NAME …>. Der Name entspricht der gleichnamigen Vue-Komponente (<x-kit::card-main> entspricht <card-main>). Ihre Attribute stimmen mit der Vue-Komponente überein. Weitere Attribute wie class, id, required oder data-* landen am Hauptelement.
Das Markup kommt aus dem Template des konfigurierten Themes. Kit-Components erzeugen keine Vue-Tags und keine v-- oder :-Attribute. Ein Ausdruck wie {{ 7*7 }} in einem Attribut wird als Text ausgegeben.
Theme-Schalter
Das Theme legt die Config laravelkit.theme fest (Env LARAVELKIT_THEME, Paket-Config src/Config/laravelkit.php):
tailwind(Default, wennLARAVELKIT_THEMEnicht gesetzt ist)bootstrap5
Jeder andere Wert führt beim Rendern einer Kit-Component zu einer ITHilbert\LaravelKit\Kit\UnbekanntesThemeException. Die Meldung nennt den Wert und die erlaubten Werte. Ein leerer Wert (LARAVELKIT_THEME= oder null) gilt ebenfalls als unbekannt. Ein Rückfall auf ein anderes Theme erfolgt nicht.
LARAVELKIT_THEME=bootstrap5
Verfügbare Kit-Components
- Karten:
card-main,card-main-header,card-body,card-footer - Buttons:
button-create,button-edit,button-show,button-delete,button-save,button-back,button-submit,button-cancel,button(variantergibt die Klassebtn-<variant>, Defaultprimary;typeden Typ, Defaultbutton) - Formularfelder:
label,input-text,input-email,input-password,input-date,input-euro,input-number,input-hidden,input-file,input-file-img,text-area,checkbox,combobox,selectcombobox:optionsals Array, Collection oder JSON-Text mitcbKey/cbCaption;valuewählt die Option.select:optionswiecombobox, zusätzlich als Schlüssel→Text-Array (['a' => 'Alpha']);valuewählt die Option, beimultiplealle Optionen aus einem Array.placeholderergibt eine erste Option mit leerem Wert.label:forsetzt das Ziel; der Text wird escaped.- Theme
bootstrap5:input-text,input-email,input-password,input-date,input-number,input-euro,text-areaundcomboboxerzeugen mitlabel="Text"davor ein<label for="<feld-id>" class="form-label">(überkit::label, Text escaped, leer = kein Label).forzeigt auf die id des Feldes; diecomboboxbekommt mitlabelohneiddie id aus dem Namen. input-file:accept,multipleundrequiredgehen an das<input>. Ein Wert wird nie vorbelegt.
- Tabs:
tabs-header,tab-header,tabs-body,tab-body - Sonstiges:
breadcrumb,show-euro,show-date
Fehlt ein Pflicht-Attribut, das die Vue-Komponente mit Default hat (z. B. button-save ohne Text), gilt derselbe Default.
Beispiel
<x-kit::card-main> <x-kit::card-main-header>Kunde anlegen</x-kit::card-main-header> <x-kit::card-body> <form method="POST" action="{{ route('kunden.store') }}"> @csrf <x-kit::input-text name="name" label="Name" :value="old('name')" required /> <x-kit::input-euro name="stundensatz" :value="old('stundensatz')" /> <x-kit::button-save /> </form> </x-kit::card-body> </x-kit::card-main>
Log-Tabelle abschalten
Die Migration der Tabelle log wird standardmäßig geladen. Mit der Config laravelkit.log_tabelle (Env LARAVELKIT_LOG_TABELLE=false) entfällt sie; alle anderen Migrationen laufen weiter.
old() und Fehleranzeige
Die Felder input-text, input-email, input-date, input-number, input-euro, text-area, combobox und select belegen ihren Wert aus old(<Feldname>) vor, wenn kein value übergeben ist (bei text-area auch kein Slot-Inhalt). Ein übergebenes value hat Vorrang. In Bearbeiten-Formularen schreibt man deshalb:
<x-kit::input-text name="name" label="Name" :value="old('name', $kunde->name)" />
Feldnamen in Array-Schreibweise werden in Punktschreibweise gelesen: adresse[ort] liest old('adresse.ort'), tags[] liest old('tags'). Liefert old() ein Array für ein Einzelfeld, bleibt das Feld leer. input-password, input-file und input-file-img werden nie vorbelegt.
Die Fehleranzeige ist standardmäßig aus. Sie wird pro Feld mit dem Attribut fehler (:fehler="false" schaltet aus) oder für alle Felder über die Config laravelkit.fehleranzeige (Env LARAVELKIT_FEHLERANZEIGE=true) aktiviert; das Attribut geht der Config vor, ein leeres fehler="" folgt der Config, ein Attribut error="Text" aktiviert das Feld ebenfalls. Das Attribut fehler erscheint nicht im HTML, old() bleibt immer aktiv.
Ist die Fehleranzeige aktiv und enthält der geteilte $errors-Bag Fehler zum Feldnamen, zeigen input-text, input-email, input-password, input-date, input-number, input-euro, input-file, input-file-img, text-area, combobox und select die erste Meldung unter dem Feld:
- Die Meldung steht in einem Element mit der id
<id>-error. Tailwind: Klassefield-error, Bootstrap 5:invalid-feedback d-block. - Das Feld bekommt
aria-invalid="true"undaria-describedby="<id>-error". Ein übergebenesaria-describedbybleibt erhalten, die Fehler-id wird angehängt. - Im Theme
bootstrap5bekommt das Feld zusätzlich die Klasseis-invalid. - Die Meldung wird escaped. Ein Attribut
error="Text"überschreibt die Meldung aus dem Bag. - Ohne
$errorsim View (z. B. Rendern ohne Middleware) erscheint nichts.
Upgrade-Hinweis: Wer Fehler selbst anzeigt, ändert nichts (das Kit zeigt standardmäßig keine). Wer die Kit-Anzeige will, setzt fehler am Feld oder LARAVELKIT_FEHLERANZEIGE=true.
Die id ist das Attribut id, sonst der Feldname ohne [ und ]: adresse[ort] ergibt adresse_ort, tags[] ergibt tags.
Dateien hochladen
input-file und input-file-img funktionieren nur in einem Formular mit enctype="multipart/form-data". Das Kit setzt das Attribut nicht selbst:
<form method="post" enctype="multipart/form-data"> @csrf <x-kit::input-file name="bild" label="Bild" accept="image/png" /> <x-kit::button-save /> </form>
HForm und Blade-Formulare
Für Blade-Formulare ist HForm durch die Formular-Components oben ersetzbar. HForm bleibt für Bestandsprojekte erhalten.
CSS-Klassen
Das Kit-CSS liefert field-error für die Fehlermeldung (vue/tailwind/forms/field-error.css, über forms.css eingebunden) sowie btn-primary und btn-secondary für <x-kit::button> (vue/tailwind/buttons/). Im Theme bootstrap5 gelten die Bootstrap-Klassen invalid-feedback, is-invalid, btn-primary und btn-secondary. Die CSS-Dateien müssen im Projekt eingebunden sein (siehe „Integrations-Voraussetzungen“).
Vue-Checkbox (checkbox, tailwind und bootstrap5)
checked entscheidet über das Häkchen: checked="1", checked="checked", checked="true", :checked="true" und :checked="1" haken an (Groß-/Kleinschreibung egal), checked="0", checked="false", :checked="false" nicht – auch nicht bei value="1". Ohne checked gilt wie bisher value 1 als angehakt. checked ohne Wert (<checkbox checked>) ist checked="" und hakt nicht an; zum Anhaken checked="1" oder :checked="true" schreiben. value bleibt der gesendete Wert.
Checkbox im Theme bootstrap5
Im Theme bootstrap5 bestimmt das Attribut checked den Zustand. value ist nur der gesendete Wert (Default 1). Ohne checked ist die Checkbox nicht angehakt. Die Vue-Version aus vue/bootstrap5 nimmt nur ohne checked den value als Zustand (siehe Abschnitt „Vue-Checkbox“); die Kit-Component ist ohne checked nie angehakt und weicht darin bewusst ab.
<x-kit::checkbox name="aktiv" value="1" :checked="$kunde->aktiv" />
Im Theme tailwind folgt die Kit-Component der Vue-Version: angehakt ist sie, wenn value gleich 1 oder true ist.
Tabs
Eine Tab-Gruppe bindet ihre Reiter und Inhalte über data-kit-tabs (am tabs-header) und data-kit-tabs-body (am tabs-body). Der Name (name) eines Reiters und seines Inhalts muss zusammenpassen. Die Reiter-Namen gelten seitenweit: Sie erzeugen die IDs <name>-tab und <name>. Zwei Gruppen auf einer Seite schalten unabhängig voneinander, solange ihre Namen eindeutig sind.
Ohne Gruppennamen (kein data-kit-tabs, die Components setzen dann einen leeren Wert) gehört ein tabs-header zum nächsten folgenden tabs-body in Dokumentreihenfolge. Header und Body müssen dafür nicht im selben Elternelement stehen. Der Header darf zum Beispiel in card-main-header liegen und der Body in card-body:
<x-kit::card-main> <x-kit::card-main-header> <x-kit::tabs-header> <x-kit::tab-header name="tab-daten" active>Daten</x-kit::tab-header> <x-kit::tab-header name="tab-adresse">Adresse</x-kit::tab-header> </x-kit::tabs-header> </x-kit::card-main-header> <x-kit::card-body> <x-kit::tabs-body> <x-kit::tab-body name="tab-daten" active>…</x-kit::tab-body> <x-kit::tab-body name="tab-adresse">…</x-kit::tab-body> </x-kit::tabs-body> </x-kit::card-body> </x-kit::card-main>
Mit Gruppennamen gehören alle tabs-body mit demselben Wert in data-kit-tabs-body zur Gruppe, egal wo sie stehen. Gleiche Namen in zwei Gruppen erzeugen doppelte IDs. Bootstrap-JS kann dann falsch reagieren, das ist nicht unterstützt.
active (Boolean, Default false) markiert den Reiter und seinen Inhalt, der beim Laden sichtbar sein soll. Ohne active ist beim Laden kein Reiter sichtbar.
<x-kit::tabs-header data-kit-tabs="stammdaten"> <x-kit::tab-header name="tab-daten" active>Daten</x-kit::tab-header> <x-kit::tab-header name="tab-adresse">Adresse</x-kit::tab-header> </x-kit::tabs-header> <x-kit::tabs-body data-kit-tabs-body="stammdaten"> <x-kit::tab-body name="tab-daten" active>…</x-kit::tab-body> <x-kit::tab-body name="tab-adresse">…</x-kit::tab-body> </x-kit::tabs-body>
Das Umschalten übernimmt das Kit-Skript js/tabs.js ohne Vue. Es wird einmal pro Seite eingebunden:
import { initTabs } from '../../vendor/ithilbert/laravel-kit/js/tabs.js'; initTabs();
Das Tailwind-Theme braucht zusätzlich tabs.css (siehe Integrations-Voraussetzungen), damit .tab-body.active greift.
Lösch-Button und Lösch-Dialog
button-delete nimmt value entgegen, die ID des Datensatzes. Der Button gibt sie als data-kit-delete aus und hat type="button". Ohne value fehlt data-kit-delete. Ein Klick meldet die ID über das Ereignis kit:delete. initLoeschen() aus js/loeschen.js nimmt die Meldung entgegen und muss einmal pro Seite laufen:
<x-kit::button-delete value="{{ $kunde->id }}" />
import { initLoeschen } from '../../vendor/ithilbert/laravel-kit/js/loeschen.js'; initLoeschen();
Den Dialog bindet die Insel dialog-delete (Theme tailwind) über data-vue und data-props ein. Die Props sind titel, body und route. Die Route endet auf ein Pfadsegment, das der Dialog durch die ID des Datensatzes ersetzt. Ein Dialog pro Seite genügt für alle button-delete-Buttons der Seite:
<div data-vue="dialog-delete" data-props="{{ json_encode([ 'titel' => 'Kunde löschen', 'body' => 'Den Kunden wirklich löschen?', 'route' => route('kunden.destroy', 0), ]) }}"></div>
Der Dialog sendet nicht selbst. Er setzt die action des Formulars #formDelete der Seite auf die Lösch-Route und sendet es ab. Das Formular mit id="formDelete" legt das Projekt an. Methode (@method('DELETE')) und CSRF-Feld (@csrf) gehören in dieses Formular.
Bisheriger Öffnungsweg: Projekte, die den Dialog selbst öffnen, funktionieren weiter. Sie setzen eine globale deleteID und rufen document.getElementById('myModalDelete').classList.remove('hidden') auf. Das Overlay behält dafür id="myModalDelete" und trägt das Attribut route mit dem Wert des Props. „Löschen“ bildet die Route dann aus deleteID. Öffnet ein button-delete den Dialog, gilt dessen ID, auch wenn deleteID gesetzt ist. Diese ID gilt nur für diesen einen Öffnungsvorgang. Nach Schließen (Abbruch, Escape, Klick neben den Dialog) oder Absenden ist sie vergessen, ein danach über den alten Weg geöffneter Dialog nutzt wieder deleteID. Ist keine Route bestimmbar (kein Ereignis, deleteID nicht gesetzt oder leer) oder fehlt #formDelete, schließt „Löschen“ den Dialog, ohne zu senden.
Die Zustandslogik des Dialogs steht in erzeugeLoeschDialog() aus js/loeschen.js. Die Vue-Komponente verdrahtet sie nur.
Die Insel wird mit dem Mount-Helfer gemountet (siehe unten).
Mount-Helfer mountInseln
mountInseln(verzeichnis, root = document) aus js/mount-inseln.js mountet Vue-Inseln (Vue 3). Für jedes Element mit data-vue unter root lädt er die Komponente aus dem Insel-Verzeichnis und mountet sie als eigene App. Die Props kommen aus data-props (JSON-Objekt). Fehlt data-props, hat die Insel keine Props.
Das Insel-Verzeichnis ist ein Objekt. Der Schlüssel entspricht dem Wert von data-vue, der Wert ist ein Lazy-Loader:
import { mountInseln } from '../../vendor/ithilbert/laravel-kit/js/mount-inseln.js'; mountInseln({ 'dialog-delete': () => import('../../vendor/ithilbert/laravel-kit/vue/tailwind/dialog/delete.vue'), 'kunden-liste': () => import('./components/KundenListe.vue'), });
Ein Element wird nur einmal gemountet. Ein zweiter Aufruf auf demselben root überspringt bereits gemountete Inseln. Der Helfer setzt Vue 3 voraus. Vue 2.7 wird nicht unterstützt.
Fehler isolieren: Ein unbekannter Name, ein ungültiges data-props (kein JSON oder kein JSON-Objekt) oder ein Ladefehler überspringt nur diese Insel. Dabei erscheint eine Warnung in der Konsole (console.warn, mit Name und Grund). Die übrigen Inseln werden gemountet.
Whole-DOM-Mount (veraltet)
Die Dateien vue/vueapp_TW.js, vue/vueapp_B5.js und vue/vueapp_B4.js registrieren alle Vue-Komponenten des Kits als Komponenten-Plugin für die ganze Seite. Dieser Whole-DOM-Mount ist veraltet. Neue Seiten mounten Inseln mit mountInseln.
Integrations-Voraussetzungen
Das Laravel-Kit bringt Vue-Komponenten (<data-table>, <tabs>, <button-*>) mit, die Abhängigkeiten vom Konsumprojekt haben. Diese müssen explizit geladen werden.
DataTable + Buttons + Tabs: Globale Abhängigkeiten einrichten
1. jQuery + DataTables.net global setzen
Erstelle resources/js/datatable.js im Konsumprojekt:
import $ from 'jquery'; import DataTable from 'datatables.net-dt'; window.$ = window.jQuery = $; window.DataTable = DataTable;
Wichtig: Diese Datei MUSS im Blade-Layout vor der Vue-App geladen sein (damit jQuery-Init abläuft, bevor Komponenten jQuery brauchen).
In resources/views/layouts/app.blade.php oder Template:
<script src="{{ asset('js/datatable.js') }}"></script>
2. CSS aus dem Kit importieren
In resources/css/app.css folgende Imports hinzufügen (NACH @import 'tailwindcss', weil Buttons/Tabs @apply nutzen):
@import 'tailwindcss'; @import '../../vendor/ithilbert/laravel-kit/vue/tailwind/buttons/buttons.css'; @import '../../vendor/ithilbert/laravel-kit/vue/tailwind/tabs/tabs.css';
Auswirkung wenn fehlend:
- Ohne
buttons.css:<button-edit>,<button-delete>etc. sind unsichtbar - Ohne
tabs.css: Alle Tab-Inhalte sichtbar untereinander (CSS-Regeln.tab-body.activefehlen)
3. Vue globalProperty für window
Veraltet: Dieser Mount der ganzen Seite (Whole-DOM) wird durch mountInseln abgelöst (siehe „Kit-Components (Blade)“).
In resources/js/vueapp.js (wo die Vue-App initialisiert wird):
const app = createApp({}); // KRITISCH: window als globalProperty BEVOR Komponenten registriert werden app.config.globalProperties.window = window; // Dann Komponenten registrieren (oder mit @edit/@delete Event-Handlern arbeiten, die window nutzen) app.component('data-table', defineAsyncComponent(() => import('../../vendor/ithilbert/laravel-kit/vue/tailwind/datatable/DataTable.vue') )); app.mount('#vue-app');
Auswirkung wenn fehlend: Event-Handler wie @edit="row => window.location.href = ..." crashen mit "Cannot read properties of undefined (reading 'location')".
HForm: Escaping (Verhaltensänderung)
HForm escapt alle übergebenen Werte (Name, Wert, Klasse, Attributwerte, Label-, Options-, Textarea- und Kommentartexte, Pfade) wie Laravels e(). Attribute in $attributes mit ungültigem Schlüssel (Leerzeichen, ", ', >, /, = oder leer) werden nicht ausgegeben. Früher wurden Werte ungeprüft eingesetzt.
Gewolltes HTML (z. B. ein Label mit <span>) übergibst du als Htmlable; es bleibt unverändert:
use Illuminate\Support\HtmlString; HForm::label(new HtmlString('Name <span class="text-danger">*</span>'), 'name');
HForm: Label und Eingabefeld (Verhaltensänderung)
HForm::checkBox() gibt dem <input> eine id (aus $attributes['id'], sonst name) und setzt for des Labels auf dieselbe id; ein Klick auf das Label hakt die Box an. Mehrere Boxen einer Gruppe (rechte[]) bekommen ihre eigene id über $attributes — ohne eigene id hätten sie alle dieselbe id rechte[], und jedes Label hakte die erste Box an. HForm::label() gibt übergebene $attributes jetzt im <label> aus.
HButton: Escaping und Attribute (Verhaltensänderung)
HButton (project, create, show, edit, delete, submit, save, back) escapt jetzt wie HForm alle übergebenen Werte – Route, Text, Tooltip, Klasse, ID und die Werte in $attributes – wie Laravels e(). Früher wurden sie ungeprüft eingesetzt: Ein Text wie <b>Neu</b> erschien als Fettschrift, jetzt erscheint er als Text. Gewolltes HTML im Text oder Tooltip übergibst du als Htmlable, z. B. new HtmlString(…); es bleibt unverändert. Die Vorgabetexte („Löschen“, „Zurück“, …) zeigen dieselben Texte wie bisher. Wer einen Text mit HTML-Entity als normalen String übergibt ('Löschen'), sieht jetzt ö – solche Texte als UTF-8 ('Löschen') oder als HtmlString übergeben.
Schlüssel in $attributes mit ungültigem Namen entfallen wie bei HForm. Ein Schlüssel, der ein von der Methode fest gesetztes Attribut doppelt (href, class, title, data-toggle, type, onclick, data-kit-delete), wird nicht ausgegeben – auch in anderer Schreibweise (Class, TITLE). Dasselbe gilt für alle Methoden von HForm (z. B. ID neben der fest gesetzten id, for und class bei label()); kommt ein Schlüssel in $attributes mehrfach in verschiedener Schreibweise vor, gilt der erste. So enthält keine Ausgabe ein Attribut doppelt. Ausnahme: HForm::checkBox() übernimmt die id aus $attributes in jeder Schreibweise (id, ID).
HButton::delete() ruft eine globale Funktion OpenDeleteForm(id) nur noch auf, wenn es sie gibt; ohne sie wirft der Klick keinen ReferenceError mehr. Der Lösch-Dialog öffnet über data-kit-delete (siehe „Lösch-Button und Lösch-Dialog“).
Icons: Inline-SVG (kein Font Awesome)
Die Kit-Komponenten (<button-edit>, <button-show>, <button-delete>) rendert native Inline-SVGs als Icons, nicht Font Awesome.
- Kein CDN-Import nötig: Buttons sind out-of-the-box funktional
- DSGVO-konform: Keine externen Fonts/Icons
- Custom-Icons: Falls eigene Icons nötig, neue Vue-Komponente bauen (z.B.
resources/js/components/button-custom.vue)
MyDateTime: Zeitzone der App
MyDateTime nutzt die Zeitzone der App (config('app.timezone')) und setzt keine eigene mehr. Projekte, die Berlin-Zeit brauchen, stellen timezone in config/app.php auf Europe/Berlin (oder lesen dort APP_TIMEZONE und setzen die Variable) — ein fest eingetragenes 'UTC' ignoriert APP_TIMEZONE.
AI Developer CLI Tools (Voraussetzung für KI Agenten)
Damit die KI-Tools und die asynchrone AI-Pipeline (Hintergrund-Worker) korrekt funktionieren, müssen die entsprechenden CLI-Tools auf dem System installiert sein:
# OpenAI Codex CLI für das CodexReviewTool installieren: sudo npm i -g @openai/codex # Gemini CLI für die Haupt-Agent-Pipeline installieren: npm install -g gemini-chat-cli # (Oder das entsprechende von dir genutzte NPM-Package für Gemini)
(Stelle sicher, dass im jeweiligen Laravel-Projekt in der .env Datei die entsprechenden Variablen wie z.B. OPENAI_API_KEY oder GEMINI_API_KEY gesetzt sind.)
Namespace
ITHilbert\LaravelKit
Remote & MCP Integration
Das Laravel-Kit bringt gebündelte Tools mit, um das Cloud-Deployment und Remote-Debugging des verbundenen Live-Servers (insbesondere für Laravel Boost MCP) zu vereinfachen.
Trage zuerst in dem Projekt, welches dieses Kit nutzt, folgende Ziel-Parameter in die .env ein (Voraussetzung: Dein lokaler SSH-Key ist auf dem Zielserver hinterlegt):
# MCP Live Server Dev Sync LIVE_SERVER_HOST="123.123.123.12" LIVE_SERVER_USER="root" LIVE_SERVER_PATH="/var/www/meineapp" LIVE_SERVER_PORT=22
Damit werden in deiner lokalen Umgebung automatisch folgende Features aktiviert:
Interaktive Developer Commands
php artisan ssh:open- Öffnet dir ein natives, interaktives SSH-Terminal das direkt in den konfigurierten Projektordner auf deinem Ziel-Linux einspringt.php artisan ftp:open- Öffnet dir blitzschnell eine interaktive SFTP-Sitzung am exakt richtigen Ablageort des Servers.
AI-Agent Tools (MCP Server)
RemoteExecuteTool: Verleiht deinem KI-Agenten die Macht, asynchrone Shell-Befehle (z.B. Optimierungen, Migrations) per sichererProcess-Facade auf dem Host auszuführen.RemoteSyncTool: Verleiht der KI einen gezielten Datei-Transfer Push (via nativesrsync), um Modifikationen sofort remote live zu nehmen, ohne dass du den vollen Cloud-Deploy Button im Dashboard drücken musst!
MyDateTime: LC_TIME und unvollständige Datumsangaben
laravel-kit setzt LC_TIME nicht mehr. Hosts, die eine deutsche Locale brauchen, setzen sie selbst, z. B. im AppServiceProvider.
Angaben, die MyDateTime nicht als vollständiges Datum oder Uhrzeit erkennt, erzeugen keine Warnung und keine Exception. Das Objekt ist dann leer (Typ Nothing, Zeitstempel 0). Dazu gehören:
- unvollständige Datumsangaben:
15.03,2026-03,15.03.,2026-03-,15.03 10:00 - führendes Minus mit weiterem Trenner:
-03-15,-2026-03(negative Zeitstempel wie-86400bleiben Zeitstempel) - nicht numerische Teile:
aa.bb.cccc,2018-05-25T10:00,15:,aa:bb - Teile mit Nachkommastellen:
2018-05-25 15:25.5 bool:trueundfalseergeben kein Datum (bisher ergabtrueden aktuellen Zeitpunkt)
HForm::date() zeigt bei leerem Ergebnis den übergebenen Wert escaped unverändert an, damit die Eingabe sichtbar bleibt. Eine leere Eingabe ('', null) ergibt ein leeres Feld.
Unverändert bleiben vollständige Formate (2018-05-25, 25.05.2018, mit Uhrzeit, Uhrzeit allein, now, NULL, 0000-00-00) und Angaben mit Leerraum am Rand. Sekundenbruchteile einer Uhrzeit werden abgeschnitten. Ein Zeitstempel behält seinen Typ: int bleibt int, float bleibt float. Teile mit Leerraum oder Vorzeichen zählen als Zahl (25. 05. 2018, +25.05.2018).
Browser-Helper: IP über request()->ip()
Browser::getIP() nutzt request()->ip() und beachtet damit die Trusted Proxies des Hosts. Ist keine IP ermittelbar (z. B. CLI oder Test ohne REMOTE_ADDR), liefert sie 'N/A' ohne Warnung. getBrowser() und getPlatform() liefern ohne HTTP_USER_AGENT ebenfalls 'N/A'.
Upgrade-Hinweis: Bisher wurden Client-IP und X-Forwarded-For ungeprüft übernommen. Hosts hinter einem Proxy oder Load-Balancer müssen jetzt die Trusted Proxies konfigurieren (Laravel: trustProxies in bootstrap/app.php), sonst liefert getIP() die Adresse des Proxys statt die des Besuchers.
db:backup-seeders
Exportiert alle Tabellen per iseed (je Tabelle, --orderby nach Primärschlüssel bzw. erster Spalte, --skip-fk-checks, --force).
laravelkit.backup_seeders.ignore_tables nimmt u. a. migrations und sessions aus. Fehlt eine Tabelle im Export wegen eines iseed-Fehlers, läuft der Rest weiter und der Befehl endet mit Exit-Code 1.
Der Befehl fügt in database/seeders/DatabaseSeeder.php (falls vorhanden) am Anfang von run() eine Sperre (// laravelkit:seed-sperre) ein: db:seed bricht außerhalb von local und testing ab, da iseed-Seeder Tabellen leeren.
install:iSeed installiert orangehill/iseed als Dev-Abhängigkeit (composer require --dev).