Database triggers are special automated procedures in a database that are automatically executed when certain events occur on a table or view.
Imagine you have a table called Orders
, and you want to automatically log every time an order is deleted.
You can create a DELETE trigger on the Orders
table that inserts a message into a Log
table whenever a row is deleted.
Type | Description |
---|---|
BEFORE | Executes before the triggering action |
AFTER | Executes after the triggering action |
INSTEAD OF | (for views) replaces the triggering action |
CREATE TRIGGER log_delete
AFTER DELETE ON Orders
FOR EACH ROW
BEGIN
INSERT INTO Log (action, timestamp)
VALUES ('Order deleted', NOW());
END;
Data validation
Audit logging
Enforcing business rules
Extending referential integrity
Can be hard to debug
Might trigger other actions unexpectedly
Can impact performance if overly complex
GitHub Actions is a feature of GitHub that lets you create automated workflows for your software projects—right inside your GitHub repository.
You can build CI/CD pipelines (Continuous Integration / Continuous Deployment), such as:
🛠️ Build your app on every push or pull request
🚀 Automatically deploy (e.g. to a server, cloud platform, or DockerHub)
📦 Create releases (e.g. zip packages or version tags)
🔄 Run scheduled tasks (cronjobs)
GitHub Actions uses workflows, defined in a YAML file inside your repository:
Typically stored as .github/workflows/ci.yml
You define events (like push
, pull_request
) and jobs (like build
, test
)
Each job consists of steps, which are shell commands or prebuilt actions
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- run: npm install
- run: npm test
An Action is a single reusable step in a workflow. You can use:
Prebuilt actions (e.g. actions/checkout
, setup-node
, upload-artifact
)
Custom actions (e.g. shell scripts or Docker-based logic)
You can explore reusable actions in the GitHub Marketplace.
Saves time by automating repetitive tasks
Improves code quality through automated testing
Enables consistent, repeatable deployments
Integrated directly in GitHub—no need for external CI tools like Jenkins or Travis CI
Docker Compose is a tool that lets you define and run multi-container Docker applications using a single configuration file. Instead of starting each container manually via the Docker CLI, you can describe all your services (like a web app, database, cache, etc.) in a docker-compose.yml
file and run everything with a single command.
Docker Compose = Project config + Multiple containers + One command to run it all
docker-compose.yml
version: '3.9'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: "redis:alpine"
This file:
Builds and runs a local web app container
Starts a Redis container from the official image
Automatically networks the two containers
docker-compose up # Start all services in the foreground
docker-compose up -d # Start in detached (background) mode
docker-compose down # Stop and remove containers, networks, etc.
✅ Easy setup for multi-service applications
✅ Version-controlled config (great for Git)
✅ Reproducible development environments
✅ Simple startup/shutdown of entire stacks
Local development with multiple services (e.g., web app + DB)
Integration testing with full stack
Simple deployment workflows (e.g., via CI/CD)
Contentful is a headless content management system (headless CMS). It allows businesses to manage content centrally and deliver it flexibly to various channels—such as websites, apps, or digital displays—via APIs.
Traditional CMS platforms (like WordPress) handle both content management and content presentation (e.g., rendering on a website). A headless CMS separates the content backend from the presentation frontend—hence the term “headless,” as the “head” (the frontend) is removed.
Flexible content modeling: You can define your own content types (e.g., blog posts, products, testimonials) with customizable fields.
Multi-language support: Well-suited for managing multilingual content.
Cloud-based: No server maintenance needed.
Integration-friendly: Works well with tools like React, Vue, Next.js, Shopify, SAP, etc.
Companies with multiple delivery channels (websites, apps, smartwatches, etc.)
Large brands with global content needs
Developer teams seeking a scalable and flexible CMS
A Headless CMS (Content Management System) is a system where the backend (content management) is completely separated from the frontend (content presentation).
Backend and frontend are tightly coupled.
You create content in the system and it's rendered directly using built-in themes and templates with HTML.
Pros: All-in-one solution, quick to get started.
Cons: Limited flexibility, harder to deliver content across multiple platforms (e.g., website + mobile app).
Backend only.
Content is accessed via an API (usually REST or GraphQL).
The frontend (e.g., a React site, native app, or digital signage) fetches the content dynamically.
Pros: Very flexible, ideal for multi-channel content delivery.
Cons: Frontend must be built separately (requires more development effort).
Websites built with modern JavaScript frameworks (like React, Next.js, Vue)
Mobile apps that use the same content as the website
Omnichannel strategies: website, app, smart devices, etc.
Contentful
Strapi
Sanity
Directus
Prismic
Storyblok (a hybrid with visual editing capabilities)
Storyblok is a user-friendly, headless Content Management System (CMS) that helps developers and marketing teams create, manage, and publish content quickly and efficiently. It offers a visual editing interface for real-time content design and is flexible with various frameworks and platforms. Its API-first architecture allows content to be delivered to any digital platform, making it ideal for modern web and app development.
Shopware is a modular e-commerce system from Germany that allows you to create and manage online stores. It’s designed for both small retailers and large enterprises, known for its flexibility, scalability, and modern technology.
Developer: Shopware AG (founded in 2000 in Germany)
Technology: PHP, Symfony framework, API-first approach
Current Version: Shopware 6 (since 2019)
Open Source: Yes, with paid extensions available
Headless Ready: Yes, supports headless commerce via APIs
Product Management: Variants, tier pricing, media, SEO tools
Sales Channels: Web shop, POS, social media, marketplaces
Content Management: Built-in CMS ("Shopping Experiences")
Payments & Shipping: Many integrations (e.g. PayPal, Klarna)
Multilingual & Multi-Currency Support
B2B & B2C capabilities
App System & API for custom extensions
Startups (free Community Edition available)
SMEs and mid-sized businesses
Enterprise clients with complex needs
Very popular in the DACH region (Germany, Austria, Switzerland)
Made in Germany → GDPR-compliant
Highly customizable
Active ecosystem & community
Scalable for growing businesses
A Prepared Statement is a programming technique, especially used when working with databases, to make SQL queries more secure and efficient.
It consists of two steps:
Prepare the SQL query with placeholders
Example in SQL:
SELECT * FROM users WHERE username = ? AND password = ?
(Some languages use :username
or other types of placeholders.)
Bind parameters and execute
The real values are bound later, for example:
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
✅ Protection against SQL injection:
User input is treated separately and safely, not directly inserted into the SQL string.
✅ Faster with repeated use:
The SQL query is parsed once by the database server and can be executed multiple times efficiently (e.g., in loops).
$conn = new mysqli("localhost", "user", "pass", "database");
$stmt = $conn->prepare("SELECT * FROM users WHERE email = ?");
$stmt->bind_param("s", $email); // "s" stands for string
$email = "example@example.com";
$stmt->execute();
$result = $stmt->get_result();
A Prepared Statement separates SQL logic from user input, making it a secure (SQL Injection) and recommended practice when dealing with databases.
An Outer Join is a type of database join (commonly used in SQL) that returns records from one or both tables even if there’s no matching record in the other table.
LEFT OUTER JOIN (or simply: LEFT JOIN):
→ Returns all records from the left table, and the matching ones from the right table.
→ If there’s no match, the result is filled with NULL
values from the right table.
RIGHT OUTER JOIN (or: RIGHT JOIN):
→ Returns all records from the right table, and the matching ones from the left table.
→ If there’s no match, NULL
is used for the left side.
FULL OUTER JOIN:
→ Returns all records from both tables, with NULL
where no match exists on either side.
Suppose you have two tables:
Customers
CustomerID | Name |
1 | Anna |
2 | Bernd |
3 | Clara |
Orders
OrderID | CustomerID | Product |
101 | 2 | Book |
102 | 4 | Lamp |
CustomerID | Name | OrderID | Product |
---|---|---|---|
1 | Anna | NULL | NULL |
2 | Bernd | 101 | Book |
3 | Clara | NULL | NULL |
PDO stands for PHP Data Objects and it's a database abstraction layer in PHP. It provides an object-oriented interface to access different types of databases—such as MySQL, PostgreSQL, or SQLite—without needing to change much of your code.
✅ Consistent API
Same code style regardless of which database you use.
✅ Prepared Statements
Helps prevent SQL injection via bound parameters:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $userId]);
✅ Transactions Support
Great for use cases like banking systems or other operations that need rollback/commit.
✅ Exception-based Error Handling
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
✅ Easy Database Switching
Switching from MySQL to PostgreSQL? Usually only the DSN and driver need to be changed.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$user = 'root';
$pass = '';
try {
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully!";
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
PDO is the recommended way to work with databases in modern PHP applications—especially for its security, flexibility, and ease of use.