chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,147 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
/**
* Repräsentiert einen einzelnen Debug-Eintrag mit allen relevanten Informationen.
*/
final class DebugEntry
{
/** @var \DateTimeImmutable */
private \DateTimeImmutable $timestamp;
/** @var string */
private string $memory;
/** @var string */
private string $peakMemory;
/**
* Erstellt einen neuen Debug-Eintrag
*/
public function __construct(
private readonly mixed $data,
private readonly string $label,
private readonly string $file,
private readonly int $line,
private readonly EntryType $type = EntryType::STANDARD
) {
$this->timestamp = new \DateTimeImmutable(timezone: new \DateTimeZone('Europe/Berlin'));
$this->memory = self::formatBytes(memory_get_usage(true));
$this->peakMemory = self::formatBytes(memory_get_peak_usage(true));
}
/**
* Gibt die Debug-Daten zurück
*/
public function getData(): mixed
{
return $this->data;
}
/**
* Gibt das Label zurück
*/
public function getLabel(): string
{
return $this->label;
}
/**
* Gibt den Pfad der Datei zurück
*/
public function getFile(): string
{
return $this->file;
}
/**
* Gibt die Zeilennummer zurück
*/
public function getLine(): int
{
return $this->line;
}
/**
* Gibt den Dateinamen ohne Pfad zurück
*/
public function getFilename(): string
{
return basename($this->file);
}
/**
* Gibt den Zeitstempel zurück
*/
public function getTimestamp(): \DateTimeImmutable
{
return $this->timestamp;
}
/**
* Gibt den formatierten Zeitstempel zurück
*/
public function getFormattedTimestamp(string $format = 'Y-m-d H:i:s'): string
{
return $this->timestamp->format($format);
}
/**
* Gibt den aktuellen Speicherverbrauch zurück
*/
public function getMemory(): string
{
return $this->memory;
}
/**
* Gibt den höchsten Speicherverbrauch zurück
*/
public function getPeakMemory(): string
{
return $this->peakMemory;
}
/**
* Gibt den Typ des Eintrags zurück
*/
public function getType(): EntryType
{
return $this->type;
}
/**
* Erstellt ein Array mit allen Debug-Daten
*/
public function toArray(): array
{
return [
'data' => $this->data,
'label' => $this->label,
'file' => $this->file,
'line' => $this->line,
'timestamp' => $this->getFormattedTimestamp(),
'memory' => $this->memory,
'peak_memory' => $this->peakMemory,
'type' => $this->type->name,
];
}
/**
* Formatiert Bytes in lesbare Größen
*/
private static function formatBytes(int $bytes): string
{
$units = ['B', 'KB', 'MB', 'GB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, 2) . ' ' . $units[$pow];
}
}

View File

@@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
/**
* Registry-Klasse zum Speichern aller Debug-Einträge.
*/
final class DebugRegistry
{
/** @var DebugEntry[] */
private array $entries = [];
/** @var int */
private int $maxEntries = 100;
/**
* Fügt einen Debug-Eintrag hinzu
*/
public function addEntry(DebugEntry $entry): void
{
// Bei Überschreitung der maximalen Anzahl, ältesten Eintrag entfernen
if (count($this->entries) >= $this->maxEntries) {
array_shift($this->entries);
}
$this->entries[] = $entry;
}
/**
* Gibt alle gespeicherten Debug-Einträge zurück
*
* @return DebugEntry[]
*/
public function getEntries(): array
{
return $this->entries;
}
/**
* Gibt die Anzahl der gespeicherten Einträge zurück
*/
public function getCount(): int
{
return count($this->entries);
}
/**
* Löscht alle gespeicherten Einträge
*/
public function clear(): void
{
$this->entries = [];
}
/**
* Setzt die maximale Anzahl an Einträgen
*/
public function setMaxEntries(int $maxEntries): void
{
$this->maxEntries = max(1, $maxEntries);
// Überschüssige Einträge entfernen
if (count($this->entries) > $this->maxEntries) {
$this->entries = array_slice($this->entries, -$this->maxEntries);
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
use App\Framework\Debug\Formatters\ConsoleFormatter;
use App\Framework\Debug\Formatters\HtmlFormatter;
use App\Framework\Debug\Outputs\ConsoleOutput;
use App\Framework\Debug\Outputs\HtmlOutput;
/**
* Service Provider für die Einbindung des Debug-Moduls.
*/
final class DebugServiceProvider
{
/**
* Registriert das Debug-Modul in der Anwendung.
*/
public function register(bool $enabled = true): void
{
// Standardkonfiguration basierend auf Umgebung
$isConsole = PHP_SAPI === 'cli';
$output = $isConsole ? new ConsoleOutput() : new HtmlOutput();
$formatter = $isConsole ? new ConsoleFormatter() : new HtmlFormatter();
Debugger::configure($enabled, $output, $formatter);
}
/**
* Konfiguriert das Debug-Modul für die Produktionsumgebung.
*/
public function configureForProduction(): void
{
Debugger::disable();
}
/**
* Konfiguriert das Debug-Modul für die Entwicklungsumgebung.
*/
public function configureForDevelopment(): void
{
$isConsole = PHP_SAPI === 'cli';
$output = $isConsole ? new ConsoleOutput() : new HtmlOutput();
$formatter = $isConsole ? new ConsoleFormatter() : new HtmlFormatter();
Debugger::configure(true, $output, $formatter);
}
}

View File

@@ -0,0 +1,237 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
use App\Framework\Debug\Formatters\FormatterInterface;
/**
* Hauptklasse für das Framework-weite Debugging.
* Bietet eine übersichtlichere Alternative zu var_dump.
*/
final class Debugger
{
/** @var bool */
private static bool $enabled = true;
/** @var OutputInterface|null */
private static ?OutputInterface $output = null;
/** @var FormatterInterface|null */
private static ?FormatterInterface $formatter = null;
/** @var DebugRegistry */
private static ?DebugRegistry $registry = null;
/**
* Hauptfunktion für das Debugging - übersichtlichere Alternative zu var_dump
*/
public static function dump(mixed $data, string $label = '', bool $die = false): void
{
if (!self::isEnabled()) {
return;
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$caller = $backtrace[0] ?? [];
$debugInfo = new DebugEntry(
$data,
$label,
$caller['file'] ?? 'unknown',
$caller['line'] ?? 0
);
self::getRegistry()->addEntry($debugInfo);
self::getOutput()->output($debugInfo, self::getFormatter());
if ($die) {
die(1);
}
}
/**
* Spezielle Funktion für Arrays mit Formatierung
*/
public static function dumpArray(array $data, string $label = 'Array Debug'): void
{
if (!self::isEnabled()) {
return;
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$caller = $backtrace[0] ?? [];
$debugInfo = new DebugEntry(
$data,
$label ?: 'Array Debug',
$caller['file'] ?? 'unknown',
$caller['line'] ?? 0,
EntryType::ARRAY
);
self::getRegistry()->addEntry($debugInfo);
self::getOutput()->output($debugInfo, self::getFormatter());
}
/**
* Debug für Objekte mit Klasseninformationen
*/
public static function dumpObject(object $object, string $label = ''): void
{
if (!self::isEnabled()) {
return;
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$caller = $backtrace[0] ?? [];
$reflection = new \ReflectionClass($object);
$objectInfo = [
'class' => $reflection->getName(),
'methods' => array_map(fn($method) => $method->getName(), $reflection->getMethods()),
'properties' => array_map(fn($prop) => $prop->getName(), $reflection->getProperties()),
'data' => $object
];
$debugInfo = new DebugEntry(
$objectInfo,
$label ?: 'Object: ' . $reflection->getShortName(),
$caller['file'] ?? 'unknown',
$caller['line'] ?? 0,
EntryType::OBJECT
);
self::getRegistry()->addEntry($debugInfo);
self::getOutput()->output($debugInfo, self::getFormatter());
}
/**
* Einfaches Logging für Debugging-Zwecke
*/
public static function log(string $message, string $level = 'DEBUG'): void
{
if (!self::isEnabled()) {
return;
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$caller = $backtrace[0] ?? [];
$debugInfo = new DebugEntry(
$message,
$level,
$caller['file'] ?? 'unknown',
$caller['line'] ?? 0,
EntryType::LOG
);
self::getRegistry()->addEntry($debugInfo);
self::getOutput()->output($debugInfo, self::getFormatter());
}
/**
* Zeigt eine Übersicht aller Debug-Aufrufe
*/
public static function showHistory(): void
{
if (!self::isEnabled()) {
return;
}
$entries = self::getRegistry()->getEntries();
if (empty($entries)) {
self::getOutput()->outputRaw("Keine Debug-Historie vorhanden.\n");
return;
}
self::getOutput()->outputHistory($entries, self::getFormatter());
}
/**
* Konfiguration des Debuggers
*/
public static function configure(
bool $enabled = true,
?OutputInterface $output = null,
?FormatterInterface $formatter = null
): void {
self::$enabled = $enabled;
if ($output !== null) {
self::$output = $output;
}
if ($formatter !== null) {
self::$formatter = $formatter;
}
}
/**
* Prüft, ob der Debugger aktiviert ist
*/
public static function isEnabled(): bool
{
return self::$enabled;
}
/**
* Deaktiviert den Debugger
*/
public static function disable(): void
{
self::$enabled = false;
}
/**
* Aktiviert den Debugger
*/
public static function enable(): void
{
self::$enabled = true;
}
/**
* Gibt das Output-Objekt zurück
*/
private static function getOutput(): OutputInterface
{
if (self::$output === null) {
$isConsole = PHP_SAPI === 'cli';
self::$output = $isConsole
? new Outputs\ConsoleOutput()
: new Outputs\HtmlOutput();
}
return self::$output;
}
/**
* Gibt den Formatter zurück
*/
private static function getFormatter(): FormatterInterface
{
if (self::$formatter === null) {
$isConsole = PHP_SAPI === 'cli';
self::$formatter = $isConsole
? new Formatters\ConsoleFormatter()
: new Formatters\HtmlFormatter();
}
return self::$formatter;
}
/**
* Gibt die Registry zurück
*/
private static function getRegistry(): DebugRegistry
{
if (self::$registry === null) {
self::$registry = new DebugRegistry();
}
return self::$registry;
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
/**
* Enum für verschiedene Debug-Eintragstypen.
*/
enum EntryType
{
case STANDARD;
case ARRAY;
case OBJECT;
case LOG;
case TRACE;
}

View File

@@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug\Formatters;
use App\Framework\Console\ConsoleColor;
use App\Framework\Debug\DebugEntry;
use App\Framework\Debug\EntryType;
/**
* Formatiert Debug-Einträge für Konsolen-Ausgabe.
*/
final class ConsoleFormatter implements FormatterInterface
{
/** Farbdefinitionen für die Konsole */
private const RESET = ConsoleColor::YELLOW->value; # "\033[0m";
private const BOLD = "\033[1m";
private const GREEN = ConsoleColor::YELLOW->value; # "\033[32m";
private const string YELLOW = ConsoleColor::YELLOW->value; # "\033[33m";
private const string BLUE = ConsoleColor::BLUE->value; # "\033[34m";
private const string MAGENTA = ConsoleColor::MAGENTA->value; # "\033[35m";
private const string CYAN = ConsoleColor::CYAN->value; # "\033[36m";
private const string GRAY = ConsoleColor::GRAY->value; # = "\033[90m";
/**
* {@inheritdoc}
*/
public function format(DebugEntry $entry): string
{
$output = self::BOLD . str_repeat('=', 80) . self::RESET . "\n";
$output .= self::BOLD . self::GREEN . "DEBUG: " . self::RESET;
$output .= self::BOLD . ($entry->getLabel() ?: 'Debug Output') . self::RESET . "\n";
$output .= self::YELLOW . "File: " . self::RESET . $entry->getFile() . ":" . $entry->getLine() . "\n";
$output .= self::CYAN . "Time: " . self::RESET . $entry->getFormattedTimestamp() . "\n";
$output .= self::MAGENTA . "Memory: " . self::RESET . $entry->getMemory();
$output .= " | " . self::MAGENTA . "Peak: " . self::RESET . $entry->getPeakMemory() . "\n";
if ($entry->getType() === EntryType::ARRAY && is_array($entry->getData())) {
$data = $entry->getData();
$output .= self::BLUE . "Elements: " . self::RESET . count($data);
if (!empty($data)) {
$output .= " | " . self::BLUE . "Keys: " . self::RESET;
$output .= implode(', ', array_map('strval', array_keys($data)));
}
$output .= "\n";
}
$output .= str_repeat('-', 80) . "\n";
$output .= $this->formatValue($entry->getData()) . "\n";
$output .= str_repeat('=', 80) . "\n";
return $output;
}
/**
* {@inheritdoc}
*/
public function formatHistory(array $entries): string
{
$output = self::BOLD . "=== Debug Historie ===" . self::RESET . "\n";
$output .= "Anzahl Einträge: " . count($entries) . "\n";
$output .= str_repeat('-', 80) . "\n";
foreach ($entries as $index => $entry) {
$output .= self::BOLD . self::BLUE . "#" . ($index + 1) . self::RESET . " ";
$output .= self::GREEN . $entry->getLabel() . self::RESET . " - ";
$output .= self::YELLOW . $entry->getFilename() . ":" . $entry->getLine() . self::RESET . " - ";
$output .= self::CYAN . $entry->getFormattedTimestamp() . self::RESET . " - ";
$output .= self::MAGENTA . $entry->getMemory() . self::RESET . "\n";
}
$output .= str_repeat('-', 80) . "\n";
return $output;
}
/**
* {@inheritdoc}
*/
public function formatValue(mixed $value): string
{
$formatted = print_r($value, true);
// Hervorhebung von Schlüsseln in Arrays
$formatted = preg_replace(
'/\[(.*?)\]/',
'[' . self::CYAN . '$1' . self::RESET . ']',
$formatted
);
// Hervorhebung von NULL, true, false
$formatted = preg_replace(
'/(NULL|true|false)/',
self::YELLOW . '$1' . self::RESET,
$formatted
);
return $formatted;
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug\Formatters;
use App\Framework\Debug\DebugEntry;
/**
* Interface für alle Debug-Formatierungen.
*/
interface FormatterInterface
{
/**
* Formatiert einen Debug-Eintrag zur Ausgabe
*/
public function format(DebugEntry $entry): string;
/**
* Formatiert eine Liste von Debug-Einträgen
*
* @param DebugEntry[] $entries
*/
public function formatHistory(array $entries): string;
/**
* Formatiert einen beliebigen Wert zur Ausgabe
*/
public function formatValue(mixed $value): string;
}

View File

@@ -0,0 +1,204 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug\Formatters;
use App\Framework\Debug\DebugEntry;
use App\Framework\Debug\EntryType;
/**
* Formatiert Debug-Einträge für HTML-Ausgabe.
*/
final class HtmlFormatter implements FormatterInterface
{
/** @var bool */
private bool $stylesInjected = false;
/**
* {@inheritdoc}
*/
public function format(DebugEntry $entry): string
{
$styles = $this->stylesInjected ? '' : $this->getStyles();
$this->stylesInjected = true;
$html = $styles;
$html .= '<div class="debug-output">';
$html .= '<div class="debug-header">';
$html .= '<span class="debug-label">' . htmlspecialchars($entry->getLabel() ?: 'Debug') . '</span>';
$html .= '<span class="debug-location">' . $entry->getFilename() . ':' . $entry->getLine() . '</span>';
$html .= '<span class="debug-time">' . $entry->getFormattedTimestamp() . '</span>';
$html .= '</div>';
$html .= '<div class="debug-content">';
$html .= '<pre>' . htmlspecialchars($this->formatValue($entry->getData())) . '</pre>';
$html .= '</div>';
if ($entry->getType() === EntryType::ARRAY && is_array($entry->getData())) {
$data = $entry->getData();
$html .= '<div class="debug-array-info">';
$html .= '<small>Anzahl Elemente: ' . count($data) . '</small>';
if (!empty($data)) {
$html .= '<small> | Schlüssel: ' . htmlspecialchars(implode(', ', array_map('strval', array_keys($data)))) . '</small>';
}
$html .= '</div>';
}
$html .= '<div class="debug-footer">';
$html .= '<small>Memory: ' . $entry->getMemory() . ' | Peak: ' . $entry->getPeakMemory() . '</small>';
$html .= '</div>';
$html .= '</div>';
return $html;
}
/**
* {@inheritdoc}
*/
public function formatHistory(array $entries): string
{
$styles = $this->stylesInjected ? '' : $this->getStyles();
$this->stylesInjected = true;
$html = $styles;
$html .= '<div class="debug-history">';
$html .= '<h3>Debug Historie (' . count($entries) . ' Einträge)</h3>';
$html .= '<div class="debug-history-entries">';
foreach ($entries as $index => $entry) {
$html .= '<div class="debug-history-entry">';
$html .= '<div class="debug-history-header">';
$html .= '<span class="debug-history-index">#' . ($index + 1) . '</span> ';
$html .= '<span class="debug-history-label">' . htmlspecialchars($entry->getLabel()) . '</span> | ';
$html .= '<span class="debug-history-file">' . $entry->getFilename() . ':' . $entry->getLine() . '</span> | ';
$html .= '<span class="debug-history-time">' . $entry->getFormattedTimestamp() . '</span> | ';
$html .= '<span class="debug-history-memory">' . $entry->getMemory() . '</span>';
$html .= '</div>';
$html .= '</div>';
}
$html .= '</div>';
$html .= '</div>';
return $html;
}
/**
* {@inheritdoc}
*/
public function formatValue(mixed $value): string
{
return print_r($value, true);
}
/**
* Gibt die CSS-Styles zurück
*/
private function getStyles(): string
{
return '<style>
.debug-output {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
margin: 10px 0;
font-family: "Courier New", monospace;
font-size: 12px;
color: #212529;
}
.debug-header {
background: #343a40;
color: white;
padding: 8px 12px;
display: flex;
justify-content: space-between;
align-items: center;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.debug-label {
font-weight: bold;
color: #28a745;
}
.debug-location {
color: #ffc107;
}
.debug-time {
color: #17a2b8;
}
.debug-content {
padding: 12px;
max-height: 400px;
overflow-y: auto;
background: #fff;
}
.debug-content pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
font-size: 11px;
line-height: 1.5;
}
.debug-array-info {
background: #f1f3f5;
padding: 4px 12px;
border-top: 1px dashed #dee2e6;
color: #6c757d;
}
.debug-footer {
background: #e9ecef;
padding: 4px 12px;
border-top: 1px solid #dee2e6;
color: #6c757d;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.debug-history {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
margin: 10px 0;
padding: 10px;
font-family: "Courier New", monospace;
}
.debug-history h3 {
margin: 0 0 10px 0;
color: #343a40;
font-size: 14px;
}
.debug-history-entries {
max-height: 500px;
overflow-y: auto;
}
.debug-history-entry {
margin-bottom: 4px;
padding: 4px 8px;
background: #fff;
border-left: 3px solid #6c757d;
font-size: 11px;
}
.debug-history-header {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.debug-history-index {
font-weight: bold;
color: #007bff;
}
.debug-history-label {
color: #28a745;
}
.debug-history-file {
color: #fd7e14;
}
.debug-history-time {
color: #6c757d;
}
.debug-history-memory {
color: #6610f2;
}
</style>';
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug;
use App\Framework\Debug\Formatters\FormatterInterface;
/**
* Interface für alle Debug-Ausgabemethoden.
*/
interface OutputInterface
{
/**
* Gibt einen Debug-Eintrag aus
*/
public function output(DebugEntry $entry, FormatterInterface $formatter): void;
/**
* Gibt eine Historie von Debug-Einträgen aus
*
* @param DebugEntry[] $entries
*/
public function outputHistory(array $entries, FormatterInterface $formatter): void;
/**
* Gibt einen Rohtext aus
*/
public function outputRaw(string $text): void;
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug\Outputs;
use App\Framework\Debug\DebugEntry;
use App\Framework\Debug\Formatters\FormatterInterface;
use App\Framework\Debug\OutputInterface;
/**
* Ausgabeklasse für Konsolen-Umgebungen.
*/
final class ConsoleOutput implements OutputInterface
{
/**
* {@inheritdoc}
*/
public function output(DebugEntry $entry, FormatterInterface $formatter): void
{
fwrite(STDOUT, $formatter->format($entry));
}
/**
* {@inheritdoc}
*/
public function outputHistory(array $entries, FormatterInterface $formatter): void
{
fwrite(STDOUT, $formatter->formatHistory($entries));
}
/**
* {@inheritdoc}
*/
public function outputRaw(string $text): void
{
fwrite(STDOUT, $text);
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace App\Framework\Debug\Outputs;
use App\Framework\Debug\DebugEntry;
use App\Framework\Debug\Formatters\FormatterInterface;
use App\Framework\Debug\OutputInterface;
/**
* Ausgabeklasse für HTML-Umgebungen.
*/
final class HtmlOutput implements OutputInterface
{
/**
* {@inheritdoc}
*/
public function output(DebugEntry $entry, FormatterInterface $formatter): void
{
echo $formatter->format($entry);
}
/**
* {@inheritdoc}
*/
public function outputHistory(array $entries, FormatterInterface $formatter): void
{
echo $formatter->formatHistory($entries);
}
/**
* {@inheritdoc}
*/
public function outputRaw(string $text): void
{
echo "<div class='debug-raw'>", htmlspecialchars($text), "</div>";
}
}

View File

@@ -0,0 +1,23 @@
{
"name": "app/framework-debug",
"description": "Debug-Modul für das Framework",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Framework Team",
"email": "team@framework.example"
}
],
"require": {
"php": "^8.1"
},
"autoload": {
"psr-4": {
"App\\Framework\\Debug\\": ""
},
"files": [
"helpers.php"
]
}
}

View File

@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
use App\Framework\Debug\Debugger;
if (!function_exists('dd')) {
/**
* Debug und beende (dump and die)
*/
function dd(mixed $data, string $label = ''): void
{
Debugger::dump($data, $label, true);
}
}
if (!function_exists('debug')) {
/**
* Debug ohne beenden
*/
function debug(mixed $data, string $label = ''): void
{
Debugger::dump($data, $label);
}
}
if (!function_exists('debug_array')) {
/**
* Debug speziell für Arrays
*/
function debug_array(array $data, string $label = ''): void
{
Debugger::dumpArray($data, $label);
}
}
if (!function_exists('debug_object')) {
/**
* Debug speziell für Objekte
*/
function debug_object(object $object, string $label = ''): void
{
Debugger::dumpObject($object, $label);
}
}
if (!function_exists('debug_log')) {
/**
* Einfaches Debug-Logging
*/
function debug_log(string $message, string $level = 'DEBUG'): void
{
Debugger::log($message, $level);
}
}
if (!function_exists('debug_history')) {
/**
* Debug-Historie anzeigen
*/
function debug_history(): void
{
Debugger::showHistory();
}
}

View File

@@ -0,0 +1,104 @@
# Framework Debug-Modul
Dieses Modul bietet eine übersichtlichere Alternative zu `var_dump` und vereinfacht das Debugging in der Anwendung.
## Features
- **Übersichtliche Formatierung** - Besser lesbar als `var_dump`
- **Kontext-Informationen** - Zeigt Datei, Zeile, Zeit und Speicherverbrauch
- **Verschiedene Ausgabeformate** - HTML für Browser, Konsole für CLI
- **Spezialisierte Funktionen** - Für Arrays und Objekte optimiert
- **Debug-Historie** - Verfolgt alle Debug-Aufrufe
- **Einfache Konfiguration** - Kann für verschiedene Umgebungen aktiviert/deaktiviert werden
- **Erweiterbar** - Eigene Formatter und Outputs möglich
## Verwendung
### Einfaches Debugging
```php
// Variable debuggen
debug($variable, 'Meine Variable');
// Debuggen und Ausführung beenden
dd($variable, 'Fehleranalyse');
// Array-spezifisches Debugging
debug_array(['a' => 1, 'b' => 2], 'Mein Array');
// Objekt-Debugging mit Methoden- und Property-Liste
$user = new User();
debug_object($user, 'Benutzer');
// Einfache Log-Nachrichten
debug_log('Benutzer wurde erstellt', 'INFO');
// Historie aller Debug-Aufrufe anzeigen
debug_history();
```
### Konfiguration
```php
// In Bootstrap-Datei oder Service-Provider
use App\Framework\Debug\Debugger;
use App\Framework\Debug\Outputs\HtmlOutput;
use App\Framework\Debug\Formatters\HtmlFormatter;
// Für Entwicklungsumgebung aktivieren
Debugger::configure(
enabled: true,
output: new HtmlOutput(),
formatter: new HtmlFormatter()
);
// In Produktionsumgebung deaktivieren
if ($app->isProduction()) {
Debugger::disable();
}
```
## Eigene Formatierung und Ausgabe
Das Modul kann durch eigene Implementierungen von `FormatterInterface` und `OutputInterface` erweitert werden.
```php
namespace App\Debug;
use App\Framework\Debug\Formatters\FormatterInterface;
use App\Framework\Debug\DebugEntry;
class MyCustomFormatter implements FormatterInterface
{
public function format(DebugEntry $entry): string
{
// Eigene Formatierung implementieren
}
public function formatHistory(array $entries): string
{
// Eigene Formatierung für Historie
}
public function formatValue(mixed $value): string
{
// Eigene Formatierung für Werte
}
}
```
## Integration
Um die Helper-Funktionen global verfügbar zu machen, fügen Sie die folgende Zeile zu Ihrer Composer-Datei hinzu:
```json
{
"autoload": {
"files": [
"src/Framework/Debug/helpers.php"
]
}
}
```
Dann führen Sie `composer dump-autoload` aus.