Przejdź do głównej zawartości

Generator dokumentów HTML

Stworzysz Generator dokumentów HTML - aplikację umożliwiającą tworzenie różnego rodzaju dokumentów (zaświadczeń, podań, protokołów, umów) na podstawie danych wprowadzonych w formularzu. System wykorzystuje szablony HTML, pozwala na podgląd i zapis wygenerowanych dokumentów oraz prowadzi historię utworzonych plików.

Czego się nauczysz?

  • Pracy z szablonami dokumentów (placeholdery, podstawianie)
  • Generowania dynamicznego HTML w PHP
  • Sanityzacji danych wstawianych do dokumentów
  • Zarządzania plikami (zapis, odczyt, listowanie)
  • Implementacji prostego systemu ról
  • Tworzenia historii operacji

W prawdziwej pracy...

Generatory dokumentów są podstawą wielu systemów biznesowych - od generowania faktur i umów, przez tworzenie raportów, po automatyczne wysyłanie maili z szablonami. Umiejętność projektowania systemów z szablonami, podstawianiem danych i zarządzaniem plikami jest fundamentem dla każdego programisty tworzącego aplikacje biznesowe, CRM, ERP czy systemy dokumentacji.

  1. Formularz danych dokumentu Użytkownik wypełnia formularz z danymi potrzebnymi do dokumentu: dane osobowe, daty, treść, numer dokumentu itp.

  2. Walidacja danych System sprawdza poprawność wprowadzonych danych - czy wymagane pola są wypełnione, czy daty mają poprawny format, czy email jest prawidłowy.

  3. Generowanie dokumentu System podstawia dane do szablonu HTML i generuje gotowy dokument z odpowiednim formatowaniem.

  4. Podgląd dokumentu Użytkownik widzi wygenerowany dokument w czytelnej formie przed ostatecznym zapisem.

  5. Zapis i historia Dokument jest zapisywany jako plik HTML, a informacja o nim trafia do historii w JSON.

Przykładowa struktura pliku JSON (historia dokumentów):

{
"documents": [
{
"id": 1,
"type": "zaswiadczenie",
"template": "zaswiadczenie_zatrudnienia",
"filename": "DOC-2026-0001.html",
"data": {
"imie": "Jan",
"nazwisko": "Kowalski",
"pesel": "90010112345",
"stanowisko": "Programista",
"data_od": "2024-01-15",
"cel": "dla banku"
},
"created_by": "user1",
"created_at": "2026-02-10 14:30:00"
},
{
"id": 2,
"type": "podanie",
"template": "podanie_urlop",
"filename": "DOC-2026-0002.html",
"data": {
"imie": "Anna",
"nazwisko": "Nowak",
"dział": "Marketing",
"data_od": "2026-03-01",
"data_do": "2026-03-15",
"powod": "urlop wypoczynkowy"
},
"created_by": "user2",
"created_at": "2026-02-11 09:15:00"
}
]
}

Przykładowy szablon dokumentu (zaświadczenie):

<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Zaświadczenie - {{NUMER}}</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 40px auto; }
.header { text-align: center; margin-bottom: 40px; }
.content { line-height: 1.8; text-align: justify; }
.signature { margin-top: 60px; text-align: right; }
.date { margin-top: 40px; }
</style>
</head>
<body>
<div class="header">
<h1>ZAŚWIADCZENIE</h1>
<p>Nr {{NUMER}}</p>
</div>
<div class="content">
<p>Zaświadcza się, że Pan/Pani <strong>{{IMIE}} {{NAZWISKO}}</strong>,
PESEL: {{PESEL}}, jest zatrudniony/a w naszej firmie na stanowisku
<strong>{{STANOWISKO}}</strong> od dnia {{DATA_OD}}.</p>
<p>Zaświadczenie wydaje się {{CEL}}.</p>
</div>
<div class="date">
<p>{{MIEJSCOWOSC}}, dnia {{DATA_WYSTAWIENIA}}</p>
</div>
<div class="signature">
<p>____________________</p>
<p>podpis i pieczęć</p>
</div>
</body>
</html>
  • Foldergenerator-dokumentow/
    • index.php (strona główna z menu)
    • formularz.php (formularz wyboru typu i danych)
    • generuj.php (logika generowania)
    • podglad.php (podgląd dokumentu)
    • historia.php (lista wygenerowanych)
    • Folderincludes/
      • config.php
      • functions.php
      • templates.php
    • Foldertemplates/
      • zaswiadczenie_zatrudnienia.html
      • zaswiadczenie_ucznia.html
      • podanie_urlop.html
      • podanie_ogolne.html
      • protokół.html
    • Folderdocuments/ (wygenerowane dokumenty)
      • DOC-2026-0001.html
      • DOC-2026-0002.html
    • Folderdata/
      • history.json
      • users.json (wariant C)
    • Foldercss/
      • style.css
    • Folderjs/
      • validation.js

Wymagane funkcje:

  • Formularz danych dokumentu (min. 5 pól)
  • Walidacja PHP (wymagane pola, format danych)
  • Min. 1 walidacja JavaScript (np. PESEL, data)
  • 1 szablon dokumentu (np. zaświadczenie)
  • Generowanie dokumentu HTML z podglądem
  • Komunikaty błędów i sukcesu
  • Prosty interfejs CSS

Przykładowy scenariusz:

Użytkownik wypełnia formularz zaświadczenia: imię, nazwisko, PESEL, stanowisko, data zatrudnienia. Po kliknięciu “Generuj” widzi podgląd dokumentu z podstawionymi danymi. Może wydrukować lub skopiować treść.

Ocena: 3.0

Wczytywanie i podstawianie do szablonu:

function loadTemplate(string $templateName): string {
$path = __DIR__ . '/templates/' . $templateName . '.html';
if (!file_exists($path)) {
throw new Exception("Szablon nie istnieje: $templateName");
}
return file_get_contents($path);
}
function fillTemplate(string $template, array $data): string {
foreach ($data as $key => $value) {
$placeholder = '{{' . strtoupper($key) . '}}';
$safeValue = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
$template = str_replace($placeholder, $safeValue, $template);
}
return $template;
}
// Użycie
$template = loadTemplate('zaswiadczenie_zatrudnienia');
$document = fillTemplate($template, [
'imie' => 'Jan',
'nazwisko' => 'Kowalski',
'pesel' => '90010112345',
'stanowisko' => 'Programista',
'data_od' => '2024-01-15',
'cel' => 'dla banku',
'miejscowosc' => 'Kraków',
'data_wystawienia' => date('d.m.Y'),
]);

Generowanie numeru dokumentu:

function generateDocumentNumber(array $history): string {
$year = date('Y');
$count = 0;
// Policz dokumenty z bieżącego roku
foreach ($history as $doc) {
if (strpos($doc['filename'], "DOC-$year-") === 0) {
$count++;
}
}
$nextNumber = $count + 1;
return sprintf("DOC-%s-%04d", $year, $nextNumber);
}

Zapis dokumentu do pliku:

function saveDocument(string $content, string $filename): bool {
$path = __DIR__ . '/documents/' . $filename . '.html';
$dir = dirname($path);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
return file_put_contents($path, $content) !== false;
}
function addToHistory(array &$history, array $documentData): void {
$documentData['id'] = count($history) + 1;
$documentData['created_at'] = date('Y-m-d H:i:s');
$history[] = $documentData;
}

Walidacja PESEL:

function validatePesel(string $pesel): bool {
if (!preg_match('/^\d{11}$/', $pesel)) {
return false;
}
$weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
$sum = 0;
for ($i = 0; $i < 10; $i++) {
$sum += $weights[$i] * (int) $pesel[$i];
}
$checksum = (10 - ($sum % 10)) % 10;
return $checksum === (int) $pesel[10];
}

Walidacja NIP:

function validateNip(string $nip): bool {
$nip = preg_replace('/[^0-9]/', '', $nip);
if (strlen($nip) !== 10) {
return false;
}
$weights = [6, 5, 7, 2, 3, 4, 5, 6, 7];
$sum = 0;
for ($i = 0; $i < 9; $i++) {
$sum += $weights[$i] * (int) $nip[$i];
}
$checksum = $sum % 11;
return $checksum === (int) $nip[9];
}

JavaScript - walidacja formularza:

function validateForm() {
const pesel = document.getElementById('pesel').value;
const email = document.getElementById('email').value;
const errors = [];
if (pesel && !validatePesel(pesel)) {
errors.push('Nieprawidłowy numer PESEL');
}
if (email && !validateEmail(email)) {
errors.push('Nieprawidłowy format email');
}
if (errors.length > 0) {
alert(errors.join('\n'));
return false;
}
return true;
}
function validatePesel(pesel) {
if (!/^\d{11}$/.test(pesel)) return false;
const weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
let sum = 0;
for (let i = 0; i < 10; i++) {
sum += weights[i] * parseInt(pesel[i]);
}
const checksum = (10 - (sum % 10)) % 10;
return checksum === parseInt(pesel[10]);
}
function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

System ról (wariant C):

function getCurrentUserRole(): string {
return $_SESSION['user_role'] ?? 'guest';
}
function requireRole(string $requiredRole): void {
$currentRole = getCurrentUserRole();
$hierarchy = ['guest' => 0, 'user' => 1, 'admin' => 2];
if (($hierarchy[$currentRole] ?? 0) < ($hierarchy[$requiredRole] ?? 99)) {
header('Location: login.php?error=access_denied');
exit;
}
}
// Użycie na stronie admina
requireRole('admin');

Wykorzystaj lekcje!

Cotygodniowe spotkania podczas lekcji to idealny moment, by:

  • Pokazać postępy - nawet małe kroki się liczą
  • Wyjaśnić wątpliwości - pytaj, nie zgaduj
  • Skonsultować rozwiązania - feedback pomoże Ci się rozwijać

Pracuj iteracyjnie - lepiej mieć działający wariant A niż niedokończony C!