• Startseite
  • Produkte
  • Jetzt
  • Buchnotizen
  • Lebenslauf
  • Unternehmensberatung
  • Spiele
  • Click to open the search input field Click to open the search input field Suche
  • Menü Menü
Denis Reis
  • Link zu X
  • Link zu Facebook
  • Link zu Xing
  • Link zu LinkedIn
  • Link zu Rss dieser Seite
  • Link zu Mail
Allgemein

PHP Spickzettel

PHP Spickzettel

Wenn Sie alle paar Jahre PHP schreiben, vergessen Sie leicht die Syntax. In diesem Fall können Sie diesen Spickzettel nutzen. Dabei nutze ich Vergleiche mit JavaScript, um den Übergang zu erleichtern.

PHP Basics:

  • Windows Setup
  • php.ini
  • phpMyAdmin in Windows ausführen
  • Datenbank Verbindung
  • Tabelle auslesen
  • Tabelleneinträge
  • Ausgabe mit echo
  • Variablen
  • Kommentare
  • Style Guide
  • Script Platzierung
  • var_dump() – Wert und Datentyp ausgeben
  • Arithmetische Operatoren
  • String concatenation
  • Standardfunktionen
  • Nesting
  • Integer
  • Variablen und Konstanten
  • Mathematische Zuweisungsoperatoren
  • PHP-Variablen an JavaScript übergeben
  • Conditional Statements: if
  • If … Else
  • if … elseif … else
  • Switch
  • Vergleichsoperatoren
  • Logische Operatoren
  • „Truthy“ & „falsy“ assignment
  • Ternary Operator
  • Zufallszahlen
  • Funktionen
  • Klassen
  • Array
  • Foreach
  • For Schleife
  • GET
  • POST
  • SSL Proxy

Laravel:

  • Hilfreiche Links
  • Laravel Installation
  • Laravel Projekt anlegen
  • Projekt bearbeiten
  • Glossar
  • Ordner und Dateien Übersicht
  • Routes
  • Views
  • Layout Page
  • Test Commands
  • Erstes Deployment
  • Updates deployen

Windows Setup

Start → IIS eintippen → Internetinformationsdienste (IIS)-Manager

Wenn Sie den Webserver installiert haben, können Sie normalerweise lokal über http://localhost/ oder über http://127.0.0.1/ darauf zugreifen. Die URL lautet dann wie folgt:

http://localhost/php_test/index.php

php geht nicht, muss php_test heissen, php ist reserviert

%SystemDrive%\inetpub\wwwroot

D:\Users\denis\php_projekte\inetpub\wwwroot

To change the physical path of your IIS Web Code Module from C:\inetpub\wwwroot\php\ to D:\inetpub\wwwroot\php\, you can follow these steps:

  1. Open Internet Information Services (IIS) Manager:
    • Press Win + R, type inetmgr and press Enter, or
    • Go to Control Panel > Administrative Tools > Internet Information Services (IIS) Manager
  2. In the left panel (Connections pane), navigate to your website:
    • Expand the server name
    • Expand „Sites“
    • Select your website (likely „Default Web Site“)
  3. Find your PHP application:
    • Look for the virtual directory or application with the path /php/
    • Select it
  4. Change the physical path:
    • In the right-hand Actions pane, click „Basic Settings“ or double-click on „Basic Settings“ in the central Features View
    • In the dialog that appears, change the physical path from C:\inetpub\wwwroot\ to D:\inetpub\wwwroot\
    • Click „OK“ to save changes
  5. Make sure the new directory exists:
    • Ensure D:\inetpub\wwwroot\ exists and contains all your PHP files
    • If not, create it and copy your files from the C drive location
  6. Verify permissions:
    • Ensure the IIS application pool identity has read and execute permissions on the new folder
    • Right-click on the folder, select Properties > Security tab, and check permissions
  7. Test your site by navigating to http://localhost:80/php_test/ to make sure it works with the new path.

ACHTUNG: der Unterordner sollte php_test sein, nicht php (reserved word).

Modulzuordnung hinzufügen:

MIME Typ hinzufügen

http://localhost/php_test/index.php

php.ini

Enthält die Konfiguration. Ist unter C:\php zu finden.

phpMyAdmin in Windows ausführen

D:\Program Files (x86)\phpMyAdmin-5.2.2

config.sample.inc.php kopieren und in config.inc.php umbennen

Rechtsklick auf den Ordner und in „Terminal öffnen“ auswählen.

Oder direkt im Terminal eingeben:

cd /d "D:\Program Files (x86)\phpMyAdmin-5.2.2"

Webserver starten:

php -S 127.0.0.1:8001
PHP Development Server started

Beide Befehle verkettet:

cd /d "D:\Program Files (x86)\phpMyAdmin-5.2.2" && php -S 127.0.0.1:8001

Dann diese URL ausführen:

http://127.0.0.1:8001

Mit dem in MySQL definierten User und Password einloggen:

Datenbank Verbindung

<?php
if ($db = mysqli_connect("localhost", "dbuser", "h0inUP8Pi4uzLy9B2UWZk!", "myapp_testdb")) {
echo "Connection successful.";
mysqli_close($db);
} else {
echo "Error!";
}
?>

Mit config.php Datei. Die Datei wird mit Berechtigungen 640 abgelegt.

<?php
// ** MySQL-Einstellungen ** //
/**
* Ersetze datenbankname_hier_einfuegen mit dem Namen der Datenbank, die du verwenden möchtest.
*/
define( 'DB_NAME', 'myapp_testdb' );

/**
* Ersetze benutzername_hier_einfuegen mit deinem MySQL-Datenbank-Benutzernamen.
*/
define( 'DB_USER', 'ma_read' );

/**
* Ersetze passwort_hier_einfuegen mit deinem MySQL-Passwort.
*/
define( 'DB_PASSWORD', 'TVho7MVWB...' );

/**
* Ersetze localhost mit der MySQL-Serveradresse.
*/
define( 'DB_HOST', 'localhost' );
// es bleibt localhost auf der webseite

/**
* Der Datenbankzeichensatz, der beim Erstellen der Datenbanktabellen verwendet werden soll
*/
define( 'DB_CHARSET', 'utf8' );

Für Dateien, die ausschließlich PHP-Code enthalten (z.B. config.php), ist es tatsächlich eine empfohlene Praxis, das schließende ?>-Tag wegzulassen.

In der Verbindung aufrufen:

<?php
require_once __DIR__ . '/config.php';
// oder require_once __DIR__ . '/../config.php';  - wenn die config Datei im Verzeichnis darüber liegt

if ($db = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)) {
    echo "Connection successful.";
    mysqli_close($db);
} else {
    echo "Error!";
}
?>

file_exists() prüft zuerst das aktuelle Verzeichnis — wird die Datei dort nicht gefunden, wird die eine Ebene darüber geladen.

<?php
$config = file_exists(__DIR__ . '/config.php')
    ? __DIR__ . '/config.php'
    : __DIR__ . '/../config.php';
require_once $config;

if ($db = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)) {
    echo "Connection successful.";
    mysqli_close($db);
} else {
    echo "Error!";
}
?>

Tabelle auslesen

  1. HTTP_ACCEPT_LANGUAGE wird ausgelesen (z.B. de-DE,de;q=0.9,en;q=0.8)
  2. Die ersten 2 Zeichen werden als lang_code verwendet (de)
  3. Prepared Statement sucht greeting + erkannter Sprache in der Tabelle messages
  4. Kein Treffer → Fallback auf en

Inhalt von db_connect.php:

<?php
require_once __DIR__ . '/config.php';

$db = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (!$db) {
    die("Verbindungsfehler: " . mysqli_connect_error());
}

Ausgabelogik:

<?php
require_once __DIR__ . '/db_connect.php';

// Browser-Sprache auslesen und auf 2 Zeichen kürzen
$raw  = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en';
$lang = substr($raw, 0, 2);

// Greeting für erkannte Sprache laden
$stmt = mysqli_prepare($db, "SELECT content FROM messages WHERE text_key = 'greeting' AND lang_code = ?");
mysqli_stmt_bind_param($stmt, 's', $lang);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $content);

if (!mysqli_stmt_fetch($stmt)) {
    // Fallback auf Englisch
    mysqli_stmt_close($stmt);
    $stmt = mysqli_prepare($db, "SELECT content FROM messages WHERE text_key = 'greeting' AND lang_code = 'en'");
    mysqli_stmt_execute($stmt);
    mysqli_stmt_bind_result($stmt, $content);
    mysqli_stmt_fetch($stmt);
    $lang = 'en (fallback)';
}

mysqli_stmt_close($stmt);
mysqli_close($db);
?>
<!DOCTYPE html>
<html lang="<?= htmlspecialchars(substr($lang, 0, 2)) ?>">
<head>
    <meta charset="UTF-8">
    <title>Greeting</title>
</head>
<body>
    <p><strong>Browser-Sprache:</strong> <?= htmlspecialchars($raw) ?></p>
    <p><strong>Erkannter lang_code:</strong> <?= htmlspecialchars($lang) ?></p>
    <p><strong>Greeting:</strong> <?= htmlspecialchars($content ?? 'Welcome!') ?></p>
</body>
</html>

Texte pro Sprache und Page (z.B. Home) laden, im Array verarbeiten. PDO wird für FETCH_KEY_PAIR verwendet

db_connect_pdo.php

<?php
require_once __DIR__ . '/config.php';

$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8';
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];

try {
    $pdo = new PDO($dsn, DB_USER, DB_PASSWORD, $options);
} catch (\PDOException $e) {
    die("Verbindungsfehler: " . $e->getMessage());
}

home.php

<?php
require_once __DIR__ . '/db_connect_pdo.php';

$page = 'home';
$raw  = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en';
$lang = substr($raw, 0, 2);

// Eine Abfrage holt ALLE Texte für Sprache + Seite
$stmt = $pdo->prepare("SELECT text_key, content FROM messages WHERE lang_code = :lang AND page = :page");
$stmt->execute(['lang' => $lang, 'page' => $page]);
// FETCH_KEY_PAIR → ['greeting' => 'Hallo', 'login_btn' => 'Anmelden', ...]
$texts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

// Fallback auf Englisch, falls Sprache nicht vorhanden
if (empty($texts)) {
    $stmt->execute(['lang' => 'en', 'page' => $page]);
    $texts = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
    $lang = 'en (fallback)';
}
?>
<!DOCTYPE html>
<html lang="<?= htmlspecialchars(substr($lang, 0, 2)) ?>">
<head>
    <meta charset="UTF-8">
    <title>Greeting (optimiert)</title>
</head>
<body>
    <p><strong>Browser-Sprache:</strong> <?= htmlspecialchars($raw) ?></p>
    <p><strong>Erkannter lang_code:</strong> <?= htmlspecialchars($lang) ?></p>
    <p><strong>Greeting:</strong> <?= htmlspecialchars($texts['greeting'] ?? 'Welcome!') ?></p>
    <button><?= htmlspecialchars($texts['login_btn'] ?? 'Login') ?></button>
</body>
</html>

Tabelleneinträge

Gästebuch Beispiel. Separater Benutzer zum Schreiben, table-specific, hat SELECT und INSERT Berechtigungen nur für die gaestebuch Tabelle.

  • Prepared Statement mit ?-Platzhaltern und bind_param('ss', ...) verhindert SQL-Injection.
  • htmlspecialchars() beim Ausgeben verhindert, dass eingegebenes HTML/JS im Browser ausgeführt wird (XSS-Schutz).
  • POST statt GET für schreibende Aktionen — Daten landen nicht in der URL.
<?php
require_once __DIR__ . '/config.php';

$db = mysqli_connect(DB_HOST, DB_GUESTBOOK_USER, DB_GUESTBOOK_PASSWORD, DB_NAME);
if (!$db) {
    die("Verbindungsfehler: " . mysqli_connect_error());
}

$gespeichert = isset($_GET['gespeichert']);

// Schreiben: nur wenn das Formular per POST abgeschickt wurde
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name      = trim($_POST['name'] ?? '');
    $nachricht = trim($_POST['nachricht'] ?? '');

    if ($name !== '' && $nachricht !== '') {
        // Prepared Statement schützt vor SQL-Injection
        $stmt = mysqli_prepare($db, "INSERT INTO gaestebuch (name, nachricht) VALUES (?, ?)");
        mysqli_stmt_bind_param($stmt, 'ss', $name, $nachricht);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_close($stmt);
        mysqli_close($db);

        // Post/Redirect/Get: Weiterleitung verhindert doppeltes Absenden beim Aktualisieren
        header('Location: ' . $_SERVER['PHP_SELF'] . '?gespeichert=1');
        exit;
    }
}

// Lesen: alle Einträge, neueste zuerst (nur im GET-Pfad erreicht)
$result    = mysqli_query($db, "SELECT name, nachricht, erstellt_am FROM gaestebuch ORDER BY erstellt_am DESC");
$eintraege = mysqli_fetch_all($result, MYSQLI_ASSOC);

mysqli_close($db);
?>
<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gästebuch: Daten in die Datenbank schreiben</title>
</head>

<body>

    <h1>Gästebuch: Daten in die Datenbank schreiben</h1>
    <h2>Formular</h2>

    <form method="post">
        <p>
            <label>Name:<br>
                <input type="text" name="name" maxlength="50" required>
            </label>
        </p>
        <p>
            <label>Nachricht:<br>
                <textarea name="nachricht" rows="4" cols="40" required></textarea>
            </label>
        </p>
        <p>
            <button type="submit">Eintragen</button>
        </p>
    </form>

    <?php if ($gespeichert): ?>
        <p><strong>Eintrag gespeichert.</strong></p>
    <?php endif; ?>

    <hr>

    <h2>Bisherige Einträge</h2>

    <?php if (empty($eintraege)): ?>
        <p>Noch keine Einträge vorhanden.</p>
    <?php else: ?>
        <?php foreach ($eintraege as $eintrag): ?>
            <p>
                <strong><?= htmlspecialchars($eintrag['name']) ?></strong>
                <em>(<?= htmlspecialchars($eintrag['erstellt_am']) ?>)</em><br>
                <?= nl2br(htmlspecialchars($eintrag['nachricht'])) ?>
            </p>
        <?php endforeach; ?>
    <?php endif; ?>

    <hr>


</body>

</html>

Ausgabe mit echo

Die Anweisung echo kann mit oder ohne Klammern verwendet werden: echo oder echo().

<html>
  <head>
    <title>PHP Test</title>
  </head>
  <body>
    <?php 
      echo "<p>Hello World</p>"; 
    ?> 
  </body>
</html>
<html>
  <head>
    <title>PHP Test</title>
  </head>
  <body>
    <?php 
      echo("<p>Hello World</p>"); 
    ?> 
  </body>
</html>
<?php
    // Basic PHP Hello World script
    $greeting = "Hello, World!";
?>

<h1><?php echo $greeting; ?></h1>

Variablen

Variablen werdem mit $ definiert.

<html>
  <head>
    <title>PHP Test</title>
  </head>
  <body>
    <?php 
      $name = "Denis"; // Variable
    /* 
    Block comment - Multiple lines
    */
      echo "<h1>Heading</h1>";
      echo "<p>Hello $name !</p>"; 
    ?> 
  </body>
</html>

Kommentare

Wie in JavaScript

// Comment line
/* 
Block comment - Multiple lines
*/

Style Guide

Variablen werden immer klein geschrieben, mit Unterstrichen zwischen mehreren Wörtern (snake_case). Variablen fangen immer mit einem $ an.

$student_name = "Alice";

Konstanten verwenden nur Großbuchstaben.Wörter werden mit Unterstrichen getrennt.

define('MAX_RETRIES', 5);

Funktionen verwenden camelCase. Das erste Wort klein, danach jedes neue Wort groß.

function calculateTotalPrice() {
    return 99;
}

Bei Klassen wird jedes Wort großschreiben, keine Unterstriche (PascalCase).

class StudentProfile {
    // ...
}

Script Platzierung

<?php
// Bindet Header als PHP-Include ein
require_once 'includes/header.php';
?>

Für Dateien, die ausschließlich PHP-Code enthalten (z.B. config.php), ist es tatsächlich eine empfohlene Praxis, das schließende ?>-Tag wegzulassen.

Mit Variablen:

<?php
// Basic PHP Hello World script
$greeting = "Hello, World!";
$currentTime = date("Y-m-d H:i:s");
?>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP Hello World</title>
</head>

<body>

    <h1><?php echo $greeting; ?></h1>
    <p>This is a simple PHP test page.</p>
    <p class="time">Current server time: <?php echo $currentTime; ?></p>

    <h3>PHP Environment Information:</h3>
    <p>PHP Version: <?php echo phpversion(); ?></p>
    <p>Server Software: <?php echo $_SERVER['SERVER_SOFTWARE']; ?></p>
    <p>Server Name: <?php echo $_SERVER['SERVER_NAME']; ?></p>

</body>
</html>

var_dump() – Wert und Datentyp ausgeben

Für Debugging-Zwecke gibt es in PHP var_dump(). Es gibt den Wert zusammen mit dem Datentyp aus – ähnlich wie console.log() in den DevTools, das ebenfalls Typinformationen anzeigt.

    <?php
        $greeting = "Hello, World!";
        $currentTime = date("Y-m-d H:i:s");
    ?>
    <p>var_dump($greeting): <code><?php var_dump($greeting); ?></code></p>
    <p>var_dump($currentTime): <code><?php var_dump($currentTime); ?></code></p>

Arithmetische Operatoren

    <h3>Addition</h3>
    <p><?php echo 3+4; ?></p> //=7

    <h3>Subtraktion</h3>
    <p><?php echo 5-1; ?></p> //=4

    <h3>Multiplikation</h3>
    <p><?php echo 4*2; ?></p> //=8

    <h3>Division</h3>
    <p><?php echo 9/3; ?></p> //=3

    <h3>Modulo</h3>
    <p>Modulo gibt den <strong>Rest einer Division zurück.</p>

    <p><?php echo 11%3; ?></p> //=2
    <p><?php echo 12%3; ?></p> //=0

String concatenation

In JavaScript werden Strings mit + verkettet.
In PHP verwendet man stattdessen den Punkt . denn + ist in PHP ausschließlich für Zahlen reserviert.

    <h3>String Concatenation</h3>
    <p><code>// JS: console.log("I love to " + "code");</code></p>
    <p>PHP: <?php echo "I love to " . "code"; ?></p>

Standardfunktionen

In JavaScript werden Methoden direkt auf Werte angewendet: "Hello".toUpperCase().
In PHP gibt es keine Methoden auf primitiven Typen. Stattdessen werden Funktionen verwendet, denen der Wert als Argument übergeben wird.

String-Methoden
toUpperCase()
// JS: console.log("Hello".toUpperCase()); // HELLO
<?php echo strtoupper("Hello"); ?>

startsWith()
// JS: console.log("Hey".startsWith("He")); // true
<?php var_dump(str_starts_with("Hey", "He")); ?>

// JS: console.log("Hey".startsWith("Hello")); // false
<?php var_dump(str_starts_with("Hey", "Hello")); ?>

trim() / trimStart() / trimEnd()
// JS: " Hello ".trim()
PHP trim() — entfernt Whitespace von beiden Seiten:
<?php var_dump(trim("  Hello  ")); ?>

// JS: " Hello ".trimStart()
PHP ltrim() — entfernt Whitespace nur links:
<?php var_dump(ltrim("  Hello  ")); ?>

// JS: " Hello ".trimEnd()
PHP rtrim() — entfernt Whitespace nur rechts:
<?php var_dump(rtrim("  Hello  ")); ?>

// Ersten Buchstaben groß schreiben:
  $str = "hello world";                                                                                                                       
  echo ucfirst($str); // "Hello world"

// Alle Buchstaben groß:
$str = "hello world"; 
echo ucwords("$str"); // "Hello World"

Math-Methoden
Math.random()
// JS: console.log(Math.random()); // z.B. 0.4721...
In PHP gibt es keine direkte Entsprechung für eine zufällige Zahl zwischen 0 und 1.
Stattdessen verwendet man rand($min, $max) mit einem konkreten Bereich:
<?php echo rand(0, 100); ?>

Math.floor() - abrunden
// JS: Math.floor(4.7) // =4
<?php echo floor(4.7); ?>

Math.ceil() - aufrunden
// JS: Math.ceil(4.2) // =5
<?php echo ceil(4.2); ?>

Nesting

Funktionen können ineinander verschachtelt werden. PHP und JavaScript funktionieren hier identisch — die innerste Funktion wird zuerst ausgeführt.

// JS: console.log( Math.floor( Math.random() * 100 ) );

Da PHP kein Math.random() (Float 0–1) kennt, wird es wie folge aufgebaut:
mt_rand() / mt_getrandmax() ergibt eine zufällige Zahl zwischen 0 und 1.

<?php echo floor( mt_rand() / mt_getrandmax() * 100 ); ?>

Integer

// JS: console.log(Number.isInteger(2024)); // true
<?php var_dump(is_int(2024)); ?>

// JS: console.log(Number.isInteger(2024.5)); // false
<?php var_dump(is_int(2024.5)); ?>

Variablen und Konstanten

In JavaScript werden Variablen mit var, let oder const deklariert.
In PHP gibt es diese Schlüsselwörter nicht. Variablen beginnen immer mit $ und werden direkt durch Zuweisung erstellt.

var / let → einfache Zuweisung mit $

// JS: var name = "Alice";
// JS: let name = "Alice";
    <?php $name = "Alice"; ?>
    <?php var_dump($name); ?>

PHP-Variablen können jederzeit neu zugewiesen werden:
    <?php $name = "Bob"; ?>
    <?php var_dump($name); ?>

const → define()

// JS: const PI = 3.14;

PHP verwendet define() für Konstanten. Konstanten haben kein $-Zeichen.

PHP: float(3.14)
Kein Wert = undefined?

// JS: let x; // x ist undefined
In PHP gibt es kein undefined. Eine nicht gesetzte Variable hat den Wert null und erzeugt eine Warnung, wenn man auf sie zugreift.
Mit isset() prüft man, ob eine Variable gesetzt ist.

PHP isset($y): bool(false)
const ohne Wert / const neu zuweisen

// JS: const x; → SyntaxError
// JS: const x = 1; x = 2; → TypeError

In PHP muss define() immer einen Wert erhalten — sonst fehlt ein Argument (Fatal Error).
Eine einmal definierte Konstante kann nicht überschrieben werden; ein erneuter define()-Aufruf wird ignoriert und erzeugt eine Warnung. 

Mathematische Zuweisungsoperatoren

Die mathematischen Zuweisungsoperatoren sind in PHP und JavaScript identisch. Statt let verwendet PHP $ für Variablen.

++ (um eins erhöhen)
// JS: let a = 1; a++; console.log(a); // 2
    <?php $a = 1; $a++; ?>
    <?php echo $a; ?>

+= (erhöhen um x)
// JS: let b = 2; b += 2; console.log(b); // 4

    <?php $b = 2; $b += 2; ?>
    <?php echo $b; ?>

-= (verringern um x)
// JS: let x = 20; x -= 5; console.log(x); // 15
    <?php $x = 20; $x -= 5; ?>
    <?php echo $x; ?>

*= (multiplizieren mit x)
// JS: let y = 50; y *= 2; console.log(y); // 100

    <?php $y = 50; $y *= 2; ?>
    <?php echo $y; ?>

/= (teilen durch x)
// JS: let z = 8; z /= 2; console.log(z); // 4
    <?php $z = 8; $z /= 2; ?>
    <?php echo $z; ?>

-- (um eins verringern)
// JS: let c = 5; c--; console.log(c); // 4
    <?php $c = 5; $c--; ?>
    <?php echo $c; ?>

PHP-Variablen an JavaScript übergeben

PHP wird serverseitig ausgeführt, bevor die Seite zum Browser gesendet wird. JavaScript sieht nur das fertige Ergebnis, die PHP-Tags sind bereits aufgelöst.

String

let name = "<?php echo $name; ?>";

Zahl

let zahl = <?php echo $zahl; ?>;

Array / Objekt → json_encode()

let daten = <?php echo json_encode($daten); ?>;

    <?php
        $name = "Alice";
        $zahl = 42;
        $daten = ["name" => "Alice", "alter" => 30];
    ?>

    <script>
        let name = "<?php echo $name; ?>";
        let zahl = <?php echo $zahl; ?>;
        let daten = <?php echo json_encode($daten); ?>;

        console.log(name); 
        console.log(zahl);
        console.log(daten);
//Öffne die Browser-Konsole (Strg + Umschalt + I), um die Ausgaben zu sehen.
    </script>

Conditional Statements: if

In den Klammern () steht die Bedingung — sie wird als wahr oder falsch ausgewertet.
Wenn die Bedingung wahr ist, wird der Code in den geschweiften Klammern {} ausgeführt.
Wenn die Bedingung falsch ist, wird der Block übersprungen.

<?php
if (true) {
    echo "<p>This message will print!</p>";
}
?>

<?php
$sale = true;
if ($sale) {
    echo "<p>Buy now!</p>";
}
?>

<?php
$sale = false;
if ($sale) {
    echo "<p>Buy now!</p>";
}
echo "<p>Ausgabe: (kein Output — Bedingung ist false)</p>";
?>

If … Else

// Der else-Block wird ausgeführt, wenn die Bedingung falsch ist.

<?php
if (false) {
    echo "<p>The code in this block won't run!</p>";
} else {
    echo "<p>But the code in this block will!</p>";
}
?>

<?php
$isMale = true;
if ($isMale) {
    echo "<p>You are male</p>";
} else {
    echo "<p>You are not male</p>";
}
?>

// if … else in einer Funktion

<?php
function handleModel($model) {
     // Convert model to lowercase for case-insensitive comparison
    $modelLower = strtolower($model);
    // Check if model is o1 or o1-mini
    if ($modelLower === 'o1' || $modelLower === 'o1-mini') {
        // Code block for o1 or o1-mini models
        // Add your specific code here
        return 'o1/o1-mini code executed';
    } else {
        // Code block for all other models
        // Add your specific code here
        return 'other model code executed';
    }
}

echo "<p>" . handleModel('o1') . "</p>"; // o1/o1-mini code executed
echo "<p>" . handleModel('o1-mini') . "</p>"; // o1/o1-mini code executed
echo "<p>" . handleModel('other') . "</p>"; // other model code executed
?>

if … elseif … else

Für mehr als zwei Fälle. In PHP wird elseif zusammen geschrieben.

<?php
$scores = [95, 72, 55, 34];

foreach ($scores as $score) {
    if ($score >= 90) {
        $label = "Sehr gut";
    } elseif ($score >= 70) {
        $label = "Gut";
    } elseif ($score >= 50) {
        $label = "Bestanden";
    } else {
        $label = "Durchgefallen";
    }
    echo "<p><code>score = $score</code> → <strong>$label</strong></p>";
}
?>

/* 
score = 95 → Sehr gut
score = 72 → Gut
score = 55 → Bestanden
score = 34 → Durchgefallen
*/

Switch

PHP-switch funktioniert identisch zu JavaScript — gleiche Syntax, gleiches Verhalten.

<?php
$groceryItem = "papaya";

switch ($groceryItem) {
    case "tomato":
        echo "Tomatoes are 0.49 CHF";
        break;
    case "lime":
        echo "Limes are 1.49 CHF";
        break;
    case "papaya":
        echo "Papayas are 1.29 CHF";
        break;
    default:
        echo "Invalid item";
        break;
}
?>

Ohne break läuft die Ausführung in den nächsten Case weiter — in JS und PHP gleich.

<?php
$day = "Saturday";

switch ($day) {
    case "Saturday":
    case "Sunday":
        echo "Wochenende";
        break;
    default:
        echo "Werktag";
        break;
}
?>

PHP-Besonderheit: === vs. ==

PHP switch vergleicht mit == (loose), nicht === (strict).

// JS: switch verwendet === Trifft zu! (0 == false in PHP switch)

In JavaScript würde switch (0) auf case false nicht zutreffen (weil ===).

match gibt einen Wert zurück und vergleicht strict — näher an JavaScript switch.

<?php
$status = 1;

$label = match($status) {
    0 => "Inaktiv",
    1 => "Aktiv",
    2 => "Gesperrt",
    default => "Unbekannt",
};

echo $label; // Aktiv
?>

Vergleichsoperatoren

Vergleichsoperatoren geben true oder false zurück.

< less than
<?php var_dump(10 < 12); ?> // bool(true)
<?php var_dump(12 < 10); ?> // bool(false)

> greater than
<?php var_dump(12 > 10); ?> // bool(true) 
<?php var_dump(10 > 12); ?> // bool(false)

<= less than or equal to
<?php var_dump(10 <= 10); ?> // bool(true)
<?php var_dump(11 <= 10); ?> // bool(false)

>= greater than or equal to
<?php var_dump(10 >= 10); ?> // bool(true)
<?php var_dump(9 >= 10); ?> // bool(false)

== is equal to (loose)
<?php var_dump("5" == 5); ?> // bool(true)
<?php var_dump(0 == false); ?> // bool(true) 

=== is equal to (strict — type & value)
<?php var_dump("5" === 5); ?> // bool(false)
<?php var_dump(5 === 5); ?> // bool(true)
<?php var_dump(0 === false); ?> // bool(false)
  
!== is not equal to (strict)
<?php var_dump("5" !== 5); ?> // bool(true)
<?php var_dump(5 !== 5); ?> // bool(false) 

Logische Operatoren

Logische Operatoren verknüpfen Bedingungen und geben true oder false zurück.

&& and
Beide Bedingungen müssen wahr / true sein.
<?php var_dump(true && true); ?> // bool(true)
<?php var_dump(true && false); ?> // bool(false)
<?php var_dump(false && false); ?> // bool(false)
 
<?php
$age = 23;
if ($age >= 18 && $age < 65) {
    echo "<p>Working age</p>";
} else {
    echo "<p>Not working age</p>";
}
?>
// Working age

|| or
Mindestens eine Bedingung muss wahr sein.
<?php var_dump(true || false); ?> // bool(true)
<?php var_dump(false || false); ?> // bool(false)
 

<?php
$day = "Saturday";
if ($day === "Saturday" || $day === "Sunday") {
    echo "<p>Weekend!</p>";
} else {
    echo "<p>Work</p>";
}
?>
// Weekend!

! not
Kehrt den Wahrheitswert um.
<?php var_dump(!true); ?> // bool(false)
<?php var_dump(!false); ?> //  bool(true)


<?php
$loggedIn = false;
if (!$loggedIn) {
    echo "<p>Please log in</p>";
}
?>
// Please log in

„Truthy“ & „falsy“ assignment

Manche Werte gelten in einer Bedingung als wahr (truthy) oder falsch (falsy), ohne direkt true oder false zu sein. Use Cases wie Existenz-Checks oder Fallback-Werte.

// Statt 
if ($username !== "" && $username !== null) { … } 
// zu schreiben, kann man einfach:
if ($username) { ... }
// schreiben.
// Leerer String und null sind falsy.

Falsy-Werte in PHP. Diese Werte werden in einer if-Bedingung als false behandelt:

<?php
$values = [false, 0, 0.0, "", "0", [], null];
$labels = ['false', '0', '0.0', '""', '"0"', '[]', 'null'];

foreach ($values as $i => $val) {
    $result = $val ? "truthy" : "falsy";
    echo "<p><code>{$labels[$i]}</code> → $result</p>";
}
?>

/* 
false → falsy
0 → falsy
0.0 → falsy
"" → falsy
"0" → falsy
[] → falsy
null → falsy
*/

Truthy-Werte in PHP. Alles andere gilt als true — zum Beispiel:

<?php
$values = [true, 1, -1, "hello", " ", [0]];
$labels = ['true', '1', '-1', '"hello"', '" " (Leerzeichen)', '[0]'];

foreach ($values as $i => $val) {
    $result = $val ? "truthy" : "falsy";
    echo "<p><code>{$labels[$i]}</code> → $result</p>";
}
?>

/* 
true → truthy
1 → truthy
-1 → truthy
"hello" → truthy
" " (Leerzeichen) → truthy
[0] → truthy
*/

Zwei wichtige Unterschiede zu JavaScript:

WertPHPJavaScript
"0"falsytruthy
[]falsytruthy
undefinedgibt es nichtfalsy
NaNgibt es nichtfalsy

Wenn username irgendetwas Brauchbares enthält, nimm es, sonst nimm den Fallback. Egal ob username leer ist, null ist oder gar nicht gesetzt wurde.

In JavaScript gibt || den ersten truthy Wert zurück — nicht nur true/false.
In PHP gibt || immer nur einen Boolean zurück. Für dasselbe Muster gibt es den Elvis-Operator ?::

// JS: let defaultName = username || "Fremder";
// PHP: $defaultName = $username ?: "Fremder";

<?php
$username = "";
$defaultName = $username ?: "Fremder";
echo "<p>username = \"\" → defaultName: <strong>$defaultName</strong></p>"; // Fremder

$username = "Anna";
$defaultName = $username ?: "Fremder";
echo "<p>username = \"Anna\" → defaultName: <strong>$defaultName</strong></p>"; // Anna
?>

Code wird lesbarer, weil man nicht jeden Randfall einzeln prüfen muss. if ($items) prüft gleichzeitig ob das Array nicht leer ist — [] ist falsy, [1, 2, 3] ist truthy.

Der Nachteil: Es kann subtile Bugs erzeugen. 0 ist falsy — wenn $score = 0 ein gültiger Wert ist, wird if ($score) unerwartet false. Dann braucht man doch einen expliziten Check: if ($score !== null).

Ternary Operator

Der ternary Operator ist eine kürzere Schreibweise für einfache if/else-Ausdrücke.

JS-Beispiel mit if/else:

let isNightTime = true;
if (isNightTime) {
    console.log("Turn on the lights!");
} else {
    console.log("Turn off the lights!");
}

Gleiche Logik als ternary:

// JS: isNightTime ? "Turn on the lights!" : "Turn off the lights!"

Syntax: Bedingung ? Wert-wenn-wahr : Wert-wenn-falsch

In PHP ist die Syntax ist identisch:

<?php
$isNightTime = true;
$message = $isNightTime ? "Turn on the lights!" : "Turn off the lights!";
echo "<p>$message</p>"; //Turn on the lights!

$isNightTime = false;
$message = $isNightTime ? "Turn on the lights!" : "Turn off the lights!";
echo "<p>$message</p>"; //Turn off the lights!
?>

Direkt in echo. Die Klammern um den ternary Ausdruck sind bei echo nötig, damit PHP die Verkettung mit . korrekt auswertet.

// JS: console.log(isLoggedIn ? "Willkommen!" : "Bitte einloggen.")
<?php
$isLoggedIn = false;
echo "<p>" . ($isLoggedIn ? "Willkommen!" : "Bitte einloggen.") . "</p>";

$isLoggedIn = true;
echo "<p>" . ($isLoggedIn ? "Willkommen!" : "Bitte einloggen.") . "</p>";
?>

Wert zuweisen.

// JS: const label = score >= 50 ? "bestanden" : "durchgefallen"
<?php
$score = 72;
$label = $score >= 50 ? "bestanden" : "durchgefallen";
echo "<p>$label</p>";

$score = 34;
$label = $score >= 50 ? "bestanden" : "durchgefallen";
echo "<p>$label</p>";
?>

Zufallszahlen

JavaScript nutzt Math.random(), das einen Float zwischen 0 und 1 zurückgibt. Mit Math.floor() wird daraus eine ganze Zahl. PHP hat mit mt_rand() eine direktere Methode: Min und Max werden als Argumente übergeben.

// Zufallszahl von 0 bis 999
<?php $randomNumber = mt_rand(0, 999); echo $randomNumber; ?>

// Zufallszahl von 1 bis 6 (Würfel)
<?php $dice = mt_rand(1, 6); echo $dice; ?>

Unterschied:

JS: Math.floor(Math.random() * max) — Float 0–1, dann skalieren und abrunden.
PHP: mt_rand($min, $max) — gibt direkt eine ganze Zahl im Bereich zurück.

Funktionen

Funktionen ermöglichen es, eine bestimmte Aufgabe mehrfach auszuführen.
Sie stellen einen wiederverwendbaren Codeblock dar, der eine Folge von Anweisungen zusammenfasst, um eine bestimmte Aufgabe zu erfüllen.
In PHP werden Funktionen mit function deklariert — genau wie in JavaScript.

Einfache Funktion ohne Parameter:

    <?php
    function greetWorld() {
        echo 'Hello World!';
    }
    ?>

<?php greetWorld(); ?> // Hello World!

Funktion mit Parameter:

    <?php
    function greetPerson($name) {
        echo 'Hello ' . $name;
    }
    ?>

    <?php greetPerson("Denis"); ?> // Hello Denis

Funktion mit Rückgabewert (return):

    <?php
    function begruessung($name) {
        return "Hallo, {$name}!";
    }
    ?>

    <?php echo begruessung('Denis'); ?>  // Hallo, Denis!

Zwei Zahlen addieren:

    <?php
    function addition($num1, $num2) {
        return $num1 + $num2;
    }
    ?>

    <?php echo addition(4, 5); ?> // 9

Ergebnis in Variable speichern:

    <?php
    $summe = addition(4, 5);
    ?>

    <?php echo $summe; ?> // 9

Zwei Zahlen multiplizieren:

    <?php
// Funktion zur Multiplikation von zwei Zahlen
    function multiplyNumbers($num1, $num2) {
        return $num1 * $num2;
    }
// Vom Benutzer bereitgestellte Eingaben
    $number1 = 2;
    $number2 = 3;
// Rufe die Funktion mit den Eingaben auf und speichere das Ergebnis in einer Variablen
    $number3 = multiplyNumbers($number1, $number2);
    ?>
// Gib das Ergebnis aus
   <?php echo "The result of multiplying {$number1} and {$number2} is {$number3}"; ?>

Klassen

Klassen fassen Daten und Methoden zu einer Einheit zusammen.
In PHP werden Klassen mit class definiert — genau wie in JavaScript.
Der Konstruktor heißt in PHP __construct() statt constructor().
Methoden greifen auf Eigenschaften der Klasse über $this zu.

Das vorherige Beispiel als Klasse:

    <?php
    class Multiplier {
        public function multiplyNumbers($num1, $num2) {
            return $num1 * $num2;
        }
    }

    $multiplier = new Multiplier();

    $number1 = 2;
    $number2 = 3;
    $number3 = $multiplier->multiplyNumbers($number1, $number2);
    ?>

    <?php echo "The result of multiplying {$number1} and {$number2} is {$number3}"; ?> 
//The result of multiplying 2 and 3 is 6

Klasse mit Konstruktor.

Der Konstruktor wird automatisch aufgerufen, wenn eine Instanz erstellt wird.
In JS: constructor() — in PHP: __construct()

    <?php
    class Greeter {
        public $name;

        public function __construct($name) {
            $this->name = $name;
        }

        public function greet() {
            return "Hallo, {$this->name}!";
        }
    }

    $g = new Greeter("Denis");
    ?>

    <?php echo $g->greet(); ?> // Hallo, Denis!

Array

Ein Array ist eine geordnete Sammlung von Elementen mit numerischem Index (beginnend bei 0).
In PHP wird ein Array mit [] oder array() erstellt — genau wie in JavaScript.
Der Zugriff auf Elemente erfolgt ebenfalls über den Index: $farben[0].

Array erstellen und auf Elemente zugreifen:

    <?php
    $farben = ['rot', 'grün', 'blau'];
    ?>

    <?php echo $farben[0]; ?> // rot
    <?php echo $farben[1]; ?> // grün
    <?php echo $farben[2]; ?> // blau

Element ändern:

    <?php
    $farben[1] = 'violett';
    ?>

    <?php var_dump($farben); ?>
// array(3) { [0]=> string(3) "rot" [1]=> string(7) "violett" [2]=> string(4) "blau" } 

Loop über ein Array — klassische for-Schleife

JS: for (let i = 0; i < farben.length; i++) { console.log(farben[i]); }

In PHP: count() statt .length

    <?php
    $farben = ['rot', 'grün', 'blau'];
    for ($i = 0; $i < count($farben); $i++) {
        echo "<p>PHP: " . $farben[$i] . "</p>";
    }
    ?>
// rot, grün, blau - jeweils in einer neuen Zeile

Foreach

Loop über ein Array — foreach

    <?php
    $farben = ['rot', 'grün', 'blau'];
    foreach ($farben as $farbe) {
        echo "<p>PHP: " . $farbe . "</p>";
    }
    ?>

In PHP: Strings sind nicht direkt iterierbar.
str_split($text) wandelt den String in ein Array von Zeichen um.

    <?php
    $text = "Hallo";
    foreach (str_split($text) as $buchstabe) {
        echo "<p>PHP: " . $buchstabe . "</p>";
    }
    ?>
// H, a, l, l, o - jeweils in einer neuen Zeile

In JavaScript iteriert for...in über die Eigenschaften (Schlüssel) eines Objekts.
In PHP gibt es kein Objekt-Literal — stattdessen verwendet man ein assoziatives Array.
Die Schleife dafür lautet foreach ($array as $schluessel => $wert).

// JS: for (let eintrag in person) { console.log(`${eintrag}: ${person[eintrag]}`); }
// In JS liefert for...in nur den Schlüssel — der Wert muss über person[eintrag] abgerufen werden.
// In PHP liefert foreach mit => direkt beides — kompakter und lesbarer. 

    <?php
    $person = ['name' => 'Denis', 'alter' => 42, 'beruf' => 'Berater'];
    ?>

    <?php var_dump($person); ?>
// array(3) { ["name"]=> string(5) "Denis" ["alter"]=> int(42) ["beruf"]=> string(7) "Berater" } 

    <?php
    foreach ($person as $eintrag => $wert) {
        echo "<p>PHP: $eintrag: $wert</p>";
    }
    ?>

For Schleife

For Schleife durchläuft einen Codeblock mehrmals in einer Schleife. Sie besteht aus drei Teilen: Initialisierung (Startwert setzen), Bedingung (Wiederholungsbedingung), Inkrement/Dekrement (Wertänderung pro Durchlauf).

PHP verwendet dieselbe Syntax wie JavaScript:

<?php
for ($i = 0; $i < 5; $i++) {
    echo "<p>Durchlauf Nummer: $i</p>";
}
?>
// 0, 1, 2, 3, 4 - jeweils in einer neuen Zeile

Array durchlaufen. In PHP: count($array) statt array.length (JavaScript)

<?php
$farben = ['rot', 'grün', 'blau'];
for ($i = 0; $i < count($farben); $i++) {
    echo "<p>$farben[$i]</p>";
}
?>
// rot, grün, blau - jeweils in einer neuen Zeile

GET

GET überträgt Daten über die URL — sichtbar in der Adresszeile als ?key=value&key2=value2.

    //URL-Beispiel: index.php?name=Denis&alter=44

<?php
$name = $_GET['name'] ?? 'unbekannt';
$alter = $_GET['alter'] ?? 'unbekannt';
?>

    <p>Name: <?php echo htmlspecialchars($name); ?></p> // Name: Denis
    <p>Alter: <?php echo htmlspecialchars($alter); ?></p> // Alter: 44

Nicht geeignet für Passwörter oder sensible Daten, da die Parameter in der URL, im Browserverlauf und in Server-Logs sichtbar sind. Dafür nimmt man POST.

POST

$_POST ist wie $_GET, aber die Daten kommen nicht aus der URL sondern aus dem Request-Body des Formulars.

$_SERVER['REQUEST_METHOD'] prüft, ob das Formular abgeschickt wurde — beim ersten Laden der Seite ist es GET, nach dem Absenden POST. Erst dann lohnt es sich, $_POST auszulesen. Die leeren Strings als Startwert verhindern, dass PHP eine Warnung wirft, wenn die Variablen vor dem ersten Submit im Template verwendet werden.

<?php
$name = '';
$alter = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'] ?? '';
    $alter = $_POST['alter'] ?? '';
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>POST-Parameter</title>
</head>
<body>
    <h1>POST-Parameter</h1>

    <form method="post">
        <label>Name: <input type="text" name="name" value="<?php echo htmlspecialchars($name); ?>"></label><br><br>
        <label>Alter: <input type="number" name="alter" value="<?php echo htmlspecialchars($alter); ?>"></label><br><br>
        <button type="submit">Absenden</button>
    </form>

    <?php if ($_SERVER['REQUEST_METHOD'] === 'POST'): ?>
        <hr>
        <p>Name: <?php echo htmlspecialchars($name); ?></p>
        <p>Alter: <?php echo htmlspecialchars($alter); ?></p>
    <?php endif; ?>
</body>
</html>

SSL Proxy

https://ssl.webpack.de/test.denisreis.de/

Laravel

Hilfreiche Links

  • Laravel 13.x Dokumentation
  • Laracast
  • Laravel From Scratch (2026 Edition)
  • VS Extension – Atom Material Theme
  • VS Extension – Atom Material Icons – anschließend Set File Icon Theme anklicken und auswählen

Laravel Installation

Offiziele doku hier. Sie können auch Herd für visuelle Installation nutzen.

Install Composer. Composer ist ein Paketmanager bzw. Abhängigkeitsmanager für PHP.

Der Installer fügt Composer automatisch zu deinem PATH hinzu. Installation prüfen:

composer -v

In C:\php\php.ini folgende extensions aktivieren. Sind standardmäßig auskommentiert. ; löschen

extension=zip
extension=fileinfo
extension=mysqli

Anschließend Laravel installieren. Im Terminal ausführen:

composer global require laravel/installer
Laravel installiert

Installation prüfen. Im Terminal:

laravel

Laravel Projekt anlegen

Zu dem Projekt Verzeichnis navigieren. Im Terminal:

laravel new <projekt_name>
laravel new mein_projekt

Sie können zunächst die Standardoptionen übernehmen. Kein Starter Kit (es sei denn Sie wollen explizit mit React oder Svelte für JS arbeiten), Pest als Testing Framework, usw.

Neues Projekt anlegen

Vor dem Schritt der Datenbankmigration müssen Sie eine Datenbank einrichten und einen Benutzer anlegen.

CREATE DATABASE IF NOT EXISTS mein_projekt
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'mp_user'@'localhost' IDENTIFIED WITH caching_sha2_password BY '***';GRANT USAGE ON *.* TO 'mp_user'@'localhost'; ALTER USER 'mp_user'@'localhost' ;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER ON `mein\_projekt`.* TO 'mp_user'@'localhost'; ALTER USER 'mp_user'@'localhost' ;

Anschließend müssen Sie die .env Datei im <projekt_name> z.B. mein-projekt anpassen.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mein_projekt
DB_USERNAME=root
DB_PASSWORD=cdKVdQ3W...

Sie können die Migration auch manuell nachholen:

cd mein_projekt
php artisan migrate
Tabellen werden angelegt.

Dabei werden alle relevanten Tabellen angelegt.

Sobald Sie den Entwicklungsserver gestartet haben, ist Ihre Anwendung in Ihrem Webbrowser unter http://localhost:8000 erreichbar.

http://localhost:8000

Laravel Glossar

Begriffsklärung für Laravel Einsteiger.

Route
Die Zuordnung URL → Aktion. In Dateien wie routes/web.php legst du fest, was passieren soll, wenn jemand eine
bestimmte URL aufruft (z. B. / oder /kontakt). Die Route entscheidet, ob eine View angezeigt oder ein Controller
ausgeführt wird.

Route kann einen Controller oder direkt eine View aufrufen.

Faustregel:

  • Closure in der Route → praktisch für ganz einfache Seiten oder Prototypen.
  • Controller → sobald Logik dazukommt (Datenbankabfragen, Validierung, mehrere Aktionen) — sauberer und besser
    testbar.

View
Die Darstellungsschicht — also das, was im Browser angezeigt wird (HTML). Views liegen in resources/views/ und
enden meist auf .blade.php. Sie enthalten das Markup der Seite, aber keine Logik.

Controller
Die Vermittlungsschicht zwischen Route und View. Ein Controller ist eine PHP-Klasse (in app/Http/Controllers/),
die eingehende Anfragen verarbeitet, Daten aus dem Model holt und am Ende eine View mit diesen Daten zurückgibt.
So bleibt die web.php schlank.

Blade
Die Template-Engine von Laravel. Mit Blade kannst du in .blade.php-Dateien dynamische Inhalte mit kurzen
Direktiven einbauen, z. B. {{ $name }} zur Ausgabe einer Variable oder @if, @foreach, @extends für Logik und
Layouts. Blade wird vor der Auslieferung in reines PHP/HTML kompiliert.

Zusammenspiel (MVC-Kette):
Route → ruft Controller auf → holt Daten (z. B. via Model) → übergibt sie an die View → Blade rendert HTML →
Browser zeigt die Seite.

Composer

Composer ist ein Paketmanager bzw. Abhängigkeitsmanager für PHP.

Laravel-Installation – Order und Dateien Übersicht

Top-Level-Ordner

OrdnerZweck
app/Herzstück deiner Anwendung – enthält Controller, Models, Service-Provider und sonstige Kern-Klassen
app/Http/HTTP-Schicht: Controller, Middleware, Form-Requests
app/Models/Eloquent-Models (z. B. User.php) – die Brücke zur Datenbank
app/Providers/Service-Provider, die beim Booten der App ausgeführt werden
bootstrap/App-Bootstrapping (app.php, providers.php) und Cache-Dateien des Frameworks
config/Alle Konfigurationsdateien (app.php, database.php, mail.php …)
database/Datenbank-Artefakte: Migrationen, Seeders, Factories
database/migrations/Schema-Versionierung (Tabellen anlegen / ändern)
database/seeders/Klassen zum Befüllen der DB mit Testdaten
database/factories/Model-Factories für Tests / Seeding (Faker-basiert)
public/Webroot – einziger öffentlich erreichbarer Ordner. Enthält index.php (Front-Controller), Assets, favicon.ico, robots.txt
public/build/Vite-Build-Output (compiled CSS/JS)
resources/Quell-Dateien für Frontend & Views
resources/views/Blade-Templates (*.blade.php)
resources/css/CSS-Quelldateien (werden von Vite verarbeitet)
resources/js/JS-Quelldateien (Vite-Entry-Points)
routes/Routen-Definitionen
routes/web.phpWeb-Routen (Sessions, CSRF)
routes/console.phpArtisan-Closure-Befehle
storage/Schreib-Bereich für die App – muss beschreibbar sein
storage/app/Anwendungs-Dateien (Uploads etc.)
storage/framework/Framework-interne Caches, Sessions, kompilierte Views
storage/logs/Log-Dateien (laravel.log)
tests/PHPUnit-/Pest-Tests
tests/Feature/High-Level-/HTTP-Tests
tests/Unit/Isolierte Unit-Tests
vendor/Composer-Abhängigkeiten (von Composer verwaltet, nicht manuell anfassen)
node_modules/NPM-Abhängigkeiten für das Frontend-Tooling (Vite etc.)

Top-Level-Dateien

DateiZweck
artisanCLI-Einstiegspunkt für Laravel (php artisan migrate, make:model …)
composer.jsonPHP-Abhängigkeiten + Autoload-Konfiguration
composer.lockExakte installierte PHP-Paket-Versionen (festgeschrieben)
package.jsonNPM-Abhängigkeiten + Build-Scripts (Vite)
package-lock.jsonExakte installierte NPM-Paket-Versionen
vite.config.jsBuild-Konfiguration des Asset-Bundlers Vite
phpunit.xmlPHPUnit-/Pest-Test-Konfiguration
.envUmgebungs-Variablen (DB-Credentials, App-Key, Mailer …) – nicht ins Git!
.env.exampleVorlage für .env, wird committet
.gitignoreWelche Dateien Git ignorieren soll (vendor/, node_modules/, .env …)
.gitattributesGit-Behandlung pro Datei (Line-Endings, Export-Ignore)
.editorconfigEditor-übergreifende Code-Style-Regeln (Tabs, Encoding …)
.npmrcNPM-Konfiguration (z. B. engine-strict)
README.mdStandard-Laravel-Readme (kannst du überschreiben)
CLAUDE.mdProjekt-Anweisungen für Claude Code
.mcp.jsonMCP-Server-Konfiguration für Claude Code
boost.jsonKonfig der Laravel-Boost-Erweiterung (AI-Tooling)
.claude/Projekt-spezifische Claude-Code-Einstellungen

Daumenregel

  • Was du anfasst: app/, config/, database/, resources/, routes/, tests/, .env
  • Was generiert/abhängig ist (nie manuell editieren): vendor/, node_modules/, bootstrap/cache/, storage/framework/, public/build/
  • Webserver zeigt nur auf: public/ 

Projekt bearbeiten

Sobald die Anwendung erstellt wurde, können Sie den lokalen Entwicklungsserver von Laravel, den Queue-Worker und den Vite-Entwicklungsserver mit dem dev Composer-Skript starten (node.js muss vorher installiert werden):

cd mein_projekt
npm install && npm run build
composer run dev

Wenn Sie zurück kommen und an Ihrem Projekt weiterabeiten, brauchen Sie npm install && npm run build nicht auszuführen. Führen Sie einfach die folgenden Befehle aus.

cd mein_projekt
composer run dev

Beziehungsweise:

cd mein_projekt && composer run dev

cd mein_projekt wechselt in den Projektordner. && bedeutet: führe den nächsten Befehl nur aus, wenn der erste
erfolgreich war. composer run dev startet dann den Laravel-Server, die Queue und Vite gleichzeitig.

Sie können auch zwei Projekte parallel laufen lassen:

cd mein_zweites_projekt 
npx concurrently -c "#93c5fd,#c4b5fd,#fdba74" "php artisan serve --port=8002" "php artisan queue:listen --tries=1" "npm run dev -- --port=5174" --names='server,queue,vite'

Routes

Die Datei routes/web.php ist die zentrale Routing-Datei für die Web-Oberfläche deiner Laravel-Anwendung. Hier definierst du, welche URL (z. B. /, /about, /users) welche Aktion auslöst — also entweder direkt eine View zurückgibt oder einen Controller aufruft. Routen in dieser Datei erhalten automatisch die web-Middleware-Gruppe, die u. a. Sessions, CSRF-Schutz und Cookies aktiviert (im Gegensatz zu routes/api.php, das zustandslos für APIs gedacht ist).

Betrachten wir das folgende Beispiel. Wenn jemand die Startseite (/) per GET aufruft, wird die Blade-View resources/views/welcome.blade.php zurückgegeben.

Laravel Routes
<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('landingpage'); // redirect auf eine andere view
});
<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/landing', function () {
    return view('landingpage');
});

Einfache View Routes können auch abgekürzt definiert werden:

<?php

use Illuminate\Support\Facades\Route;

Route::view('/', 'welcome');
Route::view('/about', 'about');
Route::view('/contact', 'contact');

Views

CSS sollte mit @vite hinzugefügt werden, damit Hot Reload funktioniert. @vite() aktiviert Hot Reload und sorgt im Production-Build dafür, dass die richtige gehashte CSS-Datei verlinkt wird.

@vite(['resources/css/landingpage.css'])

Voraussetzung ist, dass der Vite Server läuft. composer run dev startet dann den Laravel-Server, die Queue und Vite gleichzeitig.

cd mein_projekt && composer run dev

Layout page

Eine Layout-Page ist eine wiederverwendbare Hülle (Template), die das gemeinsame HTML-Gerüst aller Seiten einer
Anwendung enthält. Ohne Layout müsste jede View das , usw. wiederholen. Mit dem Layout schreibt man das einmal
zentral — Änderungen am Design (z.B. Navigation, CSS) gelten dann automatisch für alle Seiten.

Zum Beispiel in views/components/layout.blade.php

@props([
'title' => 'Default Title'
])

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{$title}}</title>
    @vite(['resources/css/landingpage.css'])
</head>

<body>
    <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/about">About Us</a></li>
            <li><a href="/contact">Contact</a></li>
        </ul>
    </nav>
    <main>
        {{ $slot }}
    </main>
</body>
</html>

In individuelen Blades, z.B. welcome.blade.php

<x-layout title="Home">  //wird an layout.blade.php übergeben
// das nachfolgende wird in {{ $slot }} ausgegeben
    <h1>Welcome to our Landing Page!</h1>
    <p>This is the main page of our website. Here you can find information about our services and products. Feel free to explore and learn more about what we have to offer.</p>
</x-layout>

Test Commands

Test commands (run from mein_projekt/)

Full suite:

composer test

This is the standard — runs artisan config:clear then artisan test. 142 tests today

Per testsuite (gemäss phpunit.xml im Projektverzeichnis):

php artisan test --testsuite=Feature 
php artisan test --testsuite=Browser 
php artisan test --testsuite=Arch 
php artisan test --testsuite=Unit 

Filter by name or file:

php artisan test --compact --filter=SitemapTest
php artisan test tests/Feature/ContactValidationTest.php

Compact output:

php artisan test --compact

With coverage:

Runs the test suite and prints a code-coverage report — per-file percentages showing which lines of production code under app/ (that’s the block in phpunit.xml) were executed by tests and which weren’t.

php artisan test --coverage

Browser tests need sockets extensions enabled in php.ini plus npx playwright install chromium run once.

Erstes Deployment

Build ausführen

Wenn Ihr Hoster kein node.js unterstützt, führen Sie den Build local aus. Der Ordner public muss aus .gitignore entfernt werden, damit dieser auch auf GitHub hochgeladen werden kann.

npm run build führt vite build aus (gemäß package.json) und macht folgendes:

  1. Bündelt alle JS- und CSS-Dateien in wenige optimierte Dateien
  2. Kompiliert Tailwind CSS — nur die tatsächlich genutzten Klassen landen im Output (kein ungenutztes CSS)
  3. Minifiziert alles (kleinere Dateigröße, schnellere Ladezeiten)
  4. Schreibt die Dateien mit Hash im Dateinamen nach public/build/ (z.B. app-a1b2c3d4.js)
  5. Erstellt ein manifest.json — damit weiß Laravels @vite()-Direktive im Blade-Template, welche Datei es einbinden
    soll.
cd mein_projekt  
npm run build

Das Ergebnis ist nun produktionsreif und kann auf GitHub commited werden.

SSH-Key auf dem Server generieren

Damit der Server mit GitHub kommunizieren kann, generieren wir einen SSH-Key.

mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "projekt-deploy"
# Bei allen Fragen einfach Enter drücken

Anschließend den generierten Key anzeigen und kopieren. Kopieren Sie die komplette Ausgabe, angefangen mit ssh-ed25519.

cat ~/.ssh/id_ed25519.pub

Key in GitHub hinterlegen

Wechseln Sie nun zu GitHub und wählen Sie Ihre Repository aus. Klicken Sie auf Settings und wählen Sie unter Security and quality den Eintrag Deploy keys aus. Fügen Sie über Add deploy key den generierten Schlüssel ein. Lassen Sie die Einstellung Allow write access nicht angehackt.

Add deploy key

Testen Sie die Verbindung mit diesem Befehl.

ssh -T git@github.com
# Erwartete Antwort: Hi! You've successfully authenticated...

Verzeichnis Struktur auf dem Server

Auf dem Server werden die folgende Verzeichnisse nutzen.

~/repos/projekt.de/              # Git-Klon (sparse, nur projekt/)
~/releases/20260611_1430/     # echte Release-Ordner (einer pro Deploy)
~/releases/20260615_0900/
~/shared/projekt/            # überlebt jeden Deploy:
~/shared/projekt/.env        #   die EINE echte .env
~/shared/projekt/storage/    #   der EINE echte storage-Ordner (Logs, Sessions, Uploads)
~/www/projekt.de  ->  ~/releases/20260615_0900    # nur noch ein SYMLINK auf das aktive Release

Diese Struktur trennt unveränderlichen Release-Code von persistenten Daten. Jeder Deploy landet als eigener, in
sich abgeschlossener Ordner unter ~/releases/, während .env und storage/ dauerhaft in
~/shared/projekt/ liegen und per Symlink in jedes Release eingehängt werden. So überleben Konfiguration, Logs,
Sessions und Uploads jeden Deploy unverändert.

Der eigentliche Umschaltpunkt ist der Symlink ~/www/projekt.de, der immer auf genau ein aktives Release zeigt;
ein Deploy bedeutet also nur, diesen Zeiger atomar auf den neuen Release-Ordner umzubiegen, und ein Rollback
heißt schlicht, ihn wieder auf ein älteres Release zeigen zu lassen.

Repo klonen

Die Repository wird separat von den eigentlichen Webseite Dateien auf dem Server abgelegt. Dazu legen wir einen Ordner repos an.

cd ~
mkdir -p repos
cd repos

Nun klonen wir die Repo. Allerdings enthält diese auch Tools, Doku, usw, die nicht für die Webseite relevant sind. Daher klonen wir nur den projekt Unterordner. Dieser enthält die Laravel Dateien.

git clone --filter=blob:none --no-checkout --sparse \
  git@github.com:DenisReis-hub/projekt.de.git projekt.de

cd projekt.de
git sparse-checkout set projekt
git checkout main

# Prüfen
ls projekt/

Neueste Änderungen von GitHub holen

cd ~/repos/projekt.de 
git pull

Shared-Ordner anlegen

Der Shared Ordner beinhaltet den storage Ordner sowie die .env Datei, die über alle Releases konstant bleiben.

mkdir -p ~/shared/projekt
# storage-Grundgerüst aus dem Repo übernehmen
cp -a ~/repos/spielhub.de/spielhub/storage ~/shared/spielhub/storage
chmod -R 775 ~/shared/spielhub/storage

.env anlegen

nano ~/shared/spielhub/.env

Inhalt einfügen (über Rechtsklick) und folgende Werte für Produktion anpassen:

APP_ENV=production
APP_DEBUG=false
APP_URL=https://www.projekt.de
LOG_LEVEL=error

DB_HOST=       # Produktions-DB Host von Host Europe
DB_DATABASE=   # Produktions-DB Name
DB_USERNAME=   # Produktions-DB User
DB_PASSWORD=   # Produktions-DB Passwort

GOOGLE_REDIRECT_URI=https://www.projekt.de/auth/google/callback

Speichern: Strg+O → Enter → Strg+X

Neuen Release-Ordner anlegen und befüllen

mkdir -p ~/releases/20260613_2042
cp -a ~/repos/projekt.de/projekt/. ~/releases/20260613_2042/

Symlinks auf den shared-Ordner setzen

Zuerst in den neuen Release-Ordner wechseln! ln -s ZIEL NAME legt den Link mit Namen NAME im aktuellen Verzeichnis an — steht man im falschen Ordner, landet der Link dort.

cd ~/releases/20260613_2042

# vom Repo mitkopierte Platzhalter entfernen
rm -rf storage

# Links anlegen (im neuen Release-Ordner!)
ln -s ~/shared/projekt/storage storage
ln -s ~/shared/projekt/.env .env
ln -s ~/shared/projekt/storage/app/public public/storage

Abhängigkeiten mit Composer installieren, Rechte setzen, Datenbank migrieren und Cachen

cd ~/releases/20260613_2042

composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist
chmod -R 775 bootstrap/cache
php8.3 artisan migrate --force   # nur bei neuen Migrationen
php8.3 artisan optimize

Der Release-Ordner wird nie umbenannt, seine absoluten Pfade bleiben für immer gültig. Deshalb darf optimize hier schon ausgeführt werden. Die neue Version geht mit fertigen Caches live.

Symlink auf die Domain setzen

projekt.de darf nicht als „echter“ Ordner in www vorhanden sein. Beim Hoster zeigt die Domain auf projekt.de/public .

ln -sfn ~/releases/20260613_2042 ~/www/projekt.de

Kontrollieren mit.

ls -la ~/www/projekt.de

Sollte den Link über einen Pfeil anzeigen

ls -la ~/www/projekt.de
lrwxrwxrwx 1 ftpuser 55 Jun 13 21:24 /is/htdocs/username/www/spielhub.de -> /is/htdocs/username/releases/20260613_2042

Testen, ob die Datei public/index.php über den Symlink erreichbar ist.

ls -la ~/www/projekt.de/public/index.php

~/www/projekt.de ist kein echter Ordner, sondern nur ein Symlink (eine Verknüpfung) auf den aktiven
Release-Ordner. Wenn du ls ~/www/projekt.de/public/index.php aufrufst, folgt das Dateisystem dieser Verknüpfung automatisch bis zum echten Ziel, also ~/releases/20260613_2042/public/index.php.

Updates deployen

Build lokal ausführen

Da unser Server node / npm nicht unterstützt, führen wir zuerst den Build lokal aus und commiten ihn auf GitHub.

cd mein_projekt  
npm run build

Build lokal testen

Wenn Sie php artisan serve nutzen, ohne composer run dev, wird der Vite Server nicht gestartet. Es werden die Objekte aus dem /build Ordner verwendet.

cd mein_projekt  
php artisan serve

Änderungen von GitHub holen

Loggen Sie sich nun auf dem Server ein und holen die neusten Änderungen von GitHub.

cd ~/repos/projekt.de 
git pull

bzw.

cd ~/repos/projekt.de && git pull

Neuen Release-Ordner anlegen und befüllen

Legen Sie nun den Ordner für den aktuellen Release an (siehe Ordner Struktur in der Anleitung für das erste Deployment) und kopieren Sie die aktualsierte Repo.

mkdir -p ~/releases/20260618_1959
cp -a ~/repos/projekt.de/projekt/. ~/releases/20260618_1959/

# vendor/ des aktiven Release übernehmen → composer muss nur das Delta installieren
cp -a ~/www/projekt.de/vendor ~/releases/20260618_1959/vendor

Symlinks auf den shared-Ordner setzen

Zuerst in den neuen Release-Ordner wechseln! ln -s ZIEL NAME legt den Link mit Namen NAME im aktuellen Verzeichnis an — steht man im falschen Ordner, landet der Link dort.

cd ~/releases/20260618_1959

# vom Repo mitkopierte Platzhalter entfernen
rm -rf storage


# Links anlegen (im neuen Release-Ordner!)
ln -s ~/shared/projekt/storage storage
ln -s ~/shared/projekt/.env .env
ln -s ~/shared/projekt/storage/app/public public/storage

Composer, Rechte und Caches

Vor dem Umschalten ausführen.

cd ~/releases/20260618_1959

composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist
chmod -R 775 bootstrap/cache
php8.3 artisan optimize

Der Release-Ordner wird nie umbenannt, seine absoluten Pfade bleiben für immer gültig. Deshalb darf optimize hier schon laufen. Die neue Version geht mit fertigen Caches live.

Migration und atomarer Tausch

# Wartungsmodus — nur bei neuen Migrationen nötig
cd ~/www/projekt.de && php8.3 artisan down --retry=15

# Migration aus dem NEUEN Release heraus
cd ~/releases/20260618_1959
php8.3 artisan migrate --force   # nur bei neuen Migrationen

# Atomarer Tausch: mv -T ersetzt den Symlink in einem einzigen rename()
ln -s ~/releases/20260618_1959 ~/www/projekt.de_tmp
mv -T ~/www/projekt.de_tmp ~/www/projekt.de

cd ~/www/projekt.de && php8.3 artisan up

Warum nicht einfach ln -sfn? Das macht intern unlink + neu anlegen (zwei Schritte) Der mv -T Trick ersetzt den Symlink in einem einzigen atomaren rename(). Es gibt keinen Augenblick, in dem `www/projekt.de` fehlt.

Testen mit:

readlink ~/www/projekt.de  
curl -s https://www.projekt.de /build/manifest.json | grep -o 'app-[^"]*\.css'
curl -sI https://www.projekt.de /build/assets/app-AUSGABE-AUS_DEM-VORHERIGEN-BEFEHL.css | head -1
# Sollte 200 ausgeben

Troubleshooting:

Wenn die Webseite nicht korrekt funktioniert, könnte es an dem Cache liegen. Checken Sie den festgelegten Zeitraum mit

php -r 'echo "ttl=", ini_get("realpath_cache_ttl"), " size=", ini_get("realpath_cache_size"), PHP_EOL;' 

PHP Version Reset im Hoster setzt den PHP Cache zurück.

Rollback

Falls die Seite nach dem Deploy nicht läuft, den Symlink wird einfach auf den vorherigen Release-Ordner setzen. Dabei nutzen wir denselben mv -T Trick wie beim Deploy.

# 1. Wohin zeigt der Symlink aktuell? Welche Releases gibt es?
readlink ~/www/projekt.de
ls -1 ~/releases/

# 2. Auf das vorherige Release zurückschalten (Zeitstempel einsetzen)
ln -s ~/releases/VORHERIGER_ZEITSTEMPEL ~/www/projekt.de_tmp
mv -T ~/www/projekt.de_tmp ~/www/projekt.de

Dabei ist kein artisan optimize nötig. Die Caches des alten Release sind noch da und seine Pfade unverändert gültig.

25. Oktober 2025/0 Kommentare/von Denis
Eintrag teilen
  • Teilen auf Facebook
  • Teilen auf X
  • Teilen auf WhatsApp
  • Teilen auf Pinterest
  • Teilen auf LinkedIn
  • Teilen auf Tumblr
  • Teilen auf Vk
  • Teilen auf Reddit
  • Per E-Mail teilen
https://www.denisreis.com/wp-content/uploads/2026/04/php-spickzettel.png 768 1376 Denis https://www.denisreis.com/wp-content/uploads/2016/09/logo.png Denis2025-10-25 13:26:002026-06-19 08:22:02PHP Spickzettel
0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.

Stay connected

  • RSS abonnieren
  • XING
  • LinkedIn
  • Twitter
  • Facebook
  • Newsletter

Ich lese gerade

12 Rules for Life: An Antidote to Chaos

Kategorien

  • Allgemein
  • BPC
  • Buchnotizen
  • CSS
  • Excel
  • How-To Tutorials SAP BI BA
  • Know-How SAP
  • Projektmanagement und Führung
  • VBA

Hörfutter

Hol dir ein kostenloses Hörbuch!

Anzeige

Beliebt
  • Bestimmte Zeilen in eine andere Tabelle kopieren
    Excel VBA – Bestimmte Zeilen in eine andere Tabelle...9. März 2014 - 22:14
  • Excel VBA - Wie Sie den Blattschutz ohne Kennwort aufheben
    Excel VBA – Wie Sie den Blattschutz ohne Kennwort...24. Oktober 2017 - 12:58
  • Excel VBA - Zeichen ersetzen mit Replace
    Excel VBA – Zeichen ersetzen mit Replace12. Oktober 2014 - 20:15
  • Wie sie das aktuelle Datum in einer Liste finden
    Excel VBA – Wie Sie das aktuelle Datum in einer Liste...30. Januar 2018 - 12:57
Kürzlich
  • SAP BDC Connect für Databricks
    SAP BDC Connect für Databricks leicht gemacht10. September 2026 - 08:28
  • Datasphere CLI einrichten
    Wie Sie Datasphere CLI einrichten20. Juni 2026 - 10:57
  • Linux Spickzettel
    Linux Spickzettel24. April 2026 - 20:38
  • SAP Datasphere als Remote Quelle für SAP HANA nutzen
    SAP Datasphere als Remote Quelle für SAP HANA nutzen23. März 2026 - 09:27
Kommentare
  • PaulSuper Artikel, leider gibt es diesen FuBa bei BW/4HANA 2023...3. März 2026 - 13:34 von Paul
  • MichaelHallo, ich habe diesen Beitrag gefunden, gerade der Tipp...1. August 2023 - 14:52 von Michael
  • CarportDanke für die tolle Arbeit die hier geleistet wurde, hier...14. Februar 2023 - 12:15 von Carport
  • Tobias IsenbergHi, kann nur davon abraten/warnen, das Sprachpaket zu...19. Oktober 2022 - 14:31 von Tobias Isenberg

Werbung

Schlagwörter

ABAP AI Analysis Aufwandsschätzung BAdI BDC berechtigungen BPC BTP Controlling CSS Datasphere Delegation Design Studio EPM EvDRE Excel HTML JavaScript Meeting PM Prozessketten Python SAC SAP Script Logic Scrum SQL SQLScript Tabellen Transformationsroutinen Tutorial VBA Workshop

Archiv

  • September 2026
  • Juni 2026
  • April 2026
  • März 2026
  • Februar 2026
  • Januar 2026
  • Dezember 2025
  • November 2025
  • Oktober 2025
  • September 2025
  • August 2025
  • Juli 2025
  • Juni 2025
  • Mai 2025
  • April 2025
  • März 2025
  • Februar 2025
  • Januar 2025
  • Dezember 2024
  • November 2024
  • Oktober 2024
  • September 2024
  • August 2024
  • Juli 2024
  • Juni 2024
  • Mai 2024
  • April 2024
  • März 2024
  • Februar 2024
  • Januar 2024
  • Dezember 2023
  • November 2023
  • Oktober 2023
  • September 2023
  • August 2023
  • Juli 2023
  • Juni 2023
  • Mai 2023
  • April 2023
  • März 2023
  • Februar 2023
  • Januar 2023
  • Dezember 2022
  • November 2022
  • Oktober 2022
  • September 2022
  • August 2022
  • Juli 2022
  • Juni 2022
  • Mai 2022
  • April 2022
  • März 2022
  • Februar 2022
  • Januar 2022
  • Dezember 2021
  • November 2021
  • Oktober 2021
  • September 2021
  • August 2021
  • Juli 2021
  • Juni 2021
  • Mai 2021
  • April 2021
  • März 2021
  • Februar 2021
  • Januar 2021
  • Dezember 2020
  • November 2020
  • Oktober 2020
  • September 2020
  • August 2020
  • Juli 2020
  • Juni 2020
  • Mai 2020
  • April 2020
  • März 2020
  • Februar 2020
  • Januar 2020
  • Dezember 2019
  • November 2019
  • Oktober 2019
  • September 2019
  • August 2019
  • Juli 2019
  • Juni 2019
  • Mai 2019
  • April 2019
  • März 2019
  • Februar 2019
  • Januar 2019
  • Dezember 2018
  • November 2018
  • Oktober 2018
  • Juli 2018
  • Juni 2018
  • Mai 2018
  • April 2018
  • März 2018
  • Februar 2018
  • Januar 2018
  • Dezember 2017
  • November 2017
  • Oktober 2017
  • September 2017
  • August 2017
  • Juli 2017
  • Juni 2017
  • Mai 2017
  • April 2017
  • März 2017
  • Februar 2017
  • Januar 2017
  • Dezember 2016
  • November 2016
  • Oktober 2016
  • September 2016
  • August 2016
  • Juli 2016
  • Juni 2016
  • Mai 2016
  • April 2016
  • März 2016
  • Februar 2016
  • Januar 2016
  • Dezember 2015
  • November 2015
  • Oktober 2015
  • September 2015
  • August 2015
  • Juli 2015
  • Juni 2015
  • Mai 2015
  • April 2015
  • März 2015
  • Februar 2015
  • Januar 2015
  • Dezember 2014
  • November 2014
  • Oktober 2014
  • September 2014
  • August 2014
  • Juli 2014
  • Juni 2014
  • Mai 2014
  • April 2014
  • März 2014
  • Februar 2014
  • Januar 2014
  • Dezember 2013
  • November 2013
  • Oktober 2013
  • September 2013
  • August 2013
  • Juli 2013
  • Juni 2013
  • Mai 2013
  • April 2013
  • März 2013
  • Februar 2013
  • Januar 2013
  • Dezember 2012
  • November 2012
  • Oktober 2012
  • September 2012
  • August 2012
  • Juli 2012
  • Juni 2012
  • Mai 2012
  • April 2012
  • März 2012
  • Februar 2012
  • Januar 2012
© Copyright - Denis Reis - Lumen accipe et imperti - Impressum - Datenschutz
  • Link zu X
  • Link zu Facebook
  • Link zu Xing
  • Link zu LinkedIn
  • Link zu Rss dieser Seite
  • Link zu Mail
Link to: Wie Sie einen eigenen MCP Server auf SAP BTP einrichten Link to: Wie Sie einen eigenen MCP Server auf SAP BTP einrichten Wie Sie einen eigenen MCP Server auf SAP BTP einrichtenWie Sie einen eigenen MCP Server auf SAP BTP einrichten Link to: Wie Sie einen SAP Datasphere Datenbankbenutzer anlegen Link to: Wie Sie einen SAP Datasphere Datenbankbenutzer anlegen Wie Sie einen SAP Datasphere Datenbankbenutzer anlegenWie Sie einen SAP Datasphere Datenbankbenutzer anlegen
Nach oben scrollen Nach oben scrollen Nach oben scrollen

Diese Website benutzt Cookies. Wenn du die Website weiter nutzt, erteilst du eine Einverständniserklärung zur Erhebung personenbezogener Daten nach der DSGVO. Weitere Informationen zu Cookies und insbesondere dazu, wie Sie deren Verwendung widersprechen können, finden Sie in unseren Datenschutzhinweisen.

Akzeptieren


Wie wir Cookies verwenden

Wir können Cookies anfordern, die auf Ihrem Gerät eingestellt werden. Wir verwenden Cookies, um uns mitzuteilen, wenn Sie unsere Websites besuchen, wie Sie mit uns interagieren, Ihre Nutzererfahrung verbessern und Ihre Beziehung zu unserer Website anpassen.

Klicken Sie auf die verschiedenen Kategorienüberschriften, um mehr zu erfahren. Sie können auch einige Ihrer Einstellungen ändern. Beachten Sie, dass das Blockieren einiger Arten von Cookies Auswirkungen auf Ihre Erfahrung auf unseren Websites und auf die Dienste haben kann, die wir anbieten können.

Notwendige Website Cookies

Diese Cookies sind unbedingt erforderlich, um Ihnen die auf unserer Webseite verfügbaren Dienste und Funktionen zur Verfügung zu stellen.

Da diese Cookies für die auf unserer Webseite verfügbaren Dienste und Funktionen unbedingt erforderlich sind, hat die Ablehnung Auswirkungen auf die Funktionsweise unserer Webseite. Sie können Cookies jederzeit blockieren oder löschen, indem Sie Ihre Browsereinstellungen ändern und das Blockieren aller Cookies auf dieser Webseite erzwingen. Sie werden jedoch immer aufgefordert, Cookies zu akzeptieren / abzulehnen, wenn Sie unsere Website erneut besuchen.

Wir respektieren es voll und ganz, wenn Sie Cookies ablehnen möchten. Um zu vermeiden, dass Sie immer wieder nach Cookies gefragt werden, erlauben Sie uns bitte, einen Cookie für Ihre Einstellungen zu speichern. Sie können sich jederzeit abmelden oder andere Cookies zulassen, um unsere Dienste vollumfänglich nutzen zu können. Wenn Sie Cookies ablehnen, werden alle gesetzten Cookies auf unserer Domain entfernt.

Wir stellen Ihnen eine Liste der von Ihrem Computer auf unserer Domain gespeicherten Cookies zur Verfügung. Aus Sicherheitsgründen können wie Ihnen keine Cookies anzeigen, die von anderen Domains gespeichert werden. Diese können Sie in den Sicherheitseinstellungen Ihres Browsers einsehen.

Andere externe Dienste

Wir nutzen auch verschiedene externe Dienste wie Google Webfonts, Google Maps und externe Videoanbieter. Da diese Anbieter möglicherweise personenbezogene Daten von Ihnen speichern, können Sie diese hier deaktivieren. Bitte beachten Sie, dass eine Deaktivierung dieser Cookies die Funktionalität und das Aussehen unserer Webseite erheblich beeinträchtigen kann. Die Änderungen werden nach einem Neuladen der Seite wirksam.

Google Webfont Einstellungen:

Google Maps Einstellungen:

Google reCaptcha Einstellungen:

Vimeo und YouTube Einstellungen:

Datenschutzrichtlinie

Sie können unsere Cookies und Datenschutzeinstellungen im Detail in unseren Datenschutzrichtlinie nachlesen.

Datenschutz
Einstellungen akzeptieren