Code Snippets

A collection of code snippets that I've used in projects

PHP QueryBuilder

PHP

A lightweight PHP class for building and executing basic SQL queries using MySQLi.

<?php

class QueryBuilder {
    private mysqli $conn;
    private string $table = '';
    private array $columns = ['*'];
    private array $where = [];
    private array $bindings = [];

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

    // Set the table and reset previous query state
    public function table(string $table): self {
        $this->reset();
        $this->table = $table;
        return $this;
    }

    // Insert a new row into the table
    public function insert(array $data): int|false|string {
        if (empty($data)) {
            return "Insert failed: no data provided.";
        }

        $columns = implode(', ', array_keys($data));
        $placeholders = implode(', ', array_fill(0, count($data), '?'));
        $sql = "INSERT INTO {$this->table} ($columns) VALUES ($placeholders)";

        $stmt = $this->conn->prepare($sql);
        if (!$stmt) {
            return "Prepare failed: " . $this->conn->error;
        }

        $types = $this->getParamTypes(array_values($data));
        if (!$stmt->bind_param($types, ...array_values($data))) {
            return "Bind failed: " . $stmt->error;
        }

        if ($stmt->execute()) {
            return $this->conn->insert_id;
        }

        if ($stmt->errno === 1062) {
            return "Duplicate entry: " . $stmt->error;
        }

        return "Execute failed: " . $stmt->error;
    }

    // Set the columns to select
    public function select(array|string $columns = '*'): self {
        $this->columns = is_array($columns) ? $columns : [$columns];
        return $this;
    }

    // Add a WHERE clause
    public function where(string $column, string $operator, $value): self {
        $this->where[] = [$column, $operator, $value];
        return $this;
    }

    // Execute SELECT query and return results
    public function get(): array {
        $sql = "SELECT " . implode(', ', $this->columns) . " FROM {$this->table}";

        $params = [];
        if (!empty($this->where)) {
            $whereClauses = array_map(fn($w) => "$w[0] $w[1] ?", $this->where);
            $sql .= " WHERE " . implode(' AND ', $whereClauses);
            $params = array_map(fn($w) => $w[2], $this->where);
        }

        $stmt = $this->prepareAndBind($sql, $params);
        $stmt->execute();

        $res = $stmt->get_result();
        return $res->fetch_all(MYSQLI_ASSOC);
    }

    // Execute UPDATE query
    public function update(array $data): bool {
        $set = implode(', ', array_map(fn($k) => "$k = ?", array_keys($data)));
        $sql = "UPDATE {$this->table} SET $set";

        $params = array_values($data);

        if (!empty($this->where)) {
            $whereClauses = array_map(fn($w) => "$w[0] $w[1] ?", $this->where);
            $sql .= " WHERE " . implode(' AND ', $whereClauses);
            $params = array_merge($params, array_map(fn($w) => $w[2], $this->where));
        }

        $stmt = $this->prepareAndBind($sql, $params);
        return $stmt->execute();
    }

    // Execute DELETE query
    public function delete(): bool {
        $sql = "DELETE FROM {$this->table}";
        $params = [];

        if (!empty($this->where)) {
            $whereClauses = array_map(fn($w) => "$w[0] $w[1] ?", $this->where);
            $sql .= " WHERE " . implode(' AND ', $whereClauses);
            $params = array_map(fn($w) => $w[2], $this->where);
        }

        $stmt = $this->prepareAndBind($sql, $params);
        return $stmt->execute();
    }

    // Prepare a statement and bind parameters
    private function prepareAndBind(string $sql, array $params): mysqli_stmt {
        $stmt = $this->conn->prepare($sql);
        if (!$stmt) {
            throw new Exception("Failed to prepare SQL: {$this->conn->error}");
        }

        if (!empty($params)) {
            $types = $this->getParamTypes($params);
            $stmt->bind_param($types, ...$params);
        }

        return $stmt;
    }

    // Generate parameter types string for binding
    private function getParamTypes(array $params): string {
        return implode('', array_map(function ($value) {
            if (is_int($value)) return 'i';
            if (is_float($value)) return 'd';
            if (is_string($value)) return 's';
            return 'b'; // fallback for blob or unknown
        }, $params));
    }

    // Reset query state between calls
    private function reset(): void {
        $this->columns = ['*'];
        $this->where = [];
        $this->bindings = [];
    }
}


?>

Usage Example

//setup 
$mysqli = new mysqli('localhost', 'username', 'password', 'database');
$db = new QueryBuilder($mysqli);

//insert
$userId = $db->table('users')->insert([
'name' => 'Alice',
'email' => 'alice@example.com',
'age' => 28
]);

//select all
$users = $db->table('users')->get();

//select with condition
$users = $db->table('users')
        ->select(['id', 'name', 'email'])
        ->where('age', '>', 25)
        ->get();

//update
$updated = $db->table('users')
          ->where('id', '=', 1)
          ->update(['name' => 'Alice Smith']);
//delete
$deleted = $db->table('users')
          ->where('id', '=', 1)
          ->delete();

How it works

This `QueryBuilder` class provides a fluent interface for constructing and executing SQL queries in PHP with MySQLi. It supports basic operations like `select`, `insert`, `update`, and `delete`, and includes safe binding of parameters to avoid SQL injection. Methods can be chained such as `table()`, `where()`, and `select()` to build queries dynamically. Insert operations handle errors gracefully, including duplicate key detection. The class also supports automatic type inference for parameter binding based on data types.

Category:PHP

PHP Validation Class

PHP

A lightweight PHP validation class for handling form or input data. Supports common validation rules such as required, email, min, max, match, numeric, and custom regex patterns.

<?php

class Validator {
    // Input data to validate
    private array $data = [];

    // Collected validation errors
    private array $errors = [];

    // Validation rules per field
    private array $rules = [];

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

    // Set validation rules
    public function setRules(array $rules): void {
        $this->rules = $rules;
    }

    // Run validation against all rules
    public function validate(): bool {
        foreach ($this->rules as $field => $fieldRules) {
            $value = $this->data[$field] ?? null;

            foreach ($fieldRules as $rule) {
                // Rule without parameters (e.g., 'required', 'email')
                if (is_string($rule)) {
                    $method = "validate_" . $rule;
                    if (method_exists($this, $method)) {
                        $this->$method($field, $value);
                    }
                }

                // Rule with parameters (e.g., ['min' => 5])
                if (is_array($rule)) {
                    foreach ($rule as $ruleName => $param) {
                        $method = "validate_" . $ruleName;
                        if (method_exists($this, $method)) {
                            $this->$method($field, $value, $param);
                        }
                    }
                }
            }
        }

        return empty($this->errors);
    }

    // Retrieve validation errors
    public function getErrors(): array {
        return $this->errors;
    }

    // Add an error message to a specific field
    private function addError(string $field, string $message): void {
        $this->errors[$field][] = $message;
    }

    // --- Validation methods ---

    private function validate_required(string $field, $value): void {
        if (empty($value) && $value !== '0') {
            $this->addError($field, 'This field is required.');
        }
    }

    private function validate_email(string $field, $value): void {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            $this->addError($field, 'Invalid email address.');
        }
    }

    private function validate_min(string $field, $value, int $min): void {
        if (strlen((string)$value) < $min) {
            $this->addError($field, "Must be at least $min characters.");
        }
    }

    private function validate_max(string $field, $value, int $max): void {
        if (strlen((string)$value) > $max) {
            $this->addError($field, "Must be no more than $max characters.");
        }
    }

    private function validate_match(string $field, $value, string $otherField): void {
        if (!isset($this->data[$otherField]) || $value !== $this->data[$otherField]) {
            $this->addError($field, "Must match $otherField.");
        }
    }

    private function validate_numeric(string $field, $value): void {
        if (!is_numeric($value)) {
            $this->addError($field, "Must be a number.");
        }
    }

    private function validate_regex(string $field, $value, string $pattern): void {
        if (!preg_match($pattern, $value)) {
            $this->addError($field, "Invalid format.");
        }
    }
}

Usage Example

$rules = [
    'username' => ['required', ['min' => 3], ['max' => 20]],
    'email' => ['required', 'email'],
    'password' => ['required', ['min' => 6]],
    'confirm_password' => ['required', ['match' => 'password']],
    'age' => ['required', 'numeric'],
    'postal_code' => ['required', ['regex' => '/^[0-9]{5}$/']],
];

$validator = new Validator($data);
$validator->setRules($rules);

if ($validator->validate()) {
    echo "Validation passed";
} else {
    print_r($validator->getErrors());
}

How it works

This class validates form data based on a set of rules. It supports checks such as required for non-empty fields, email for valid email addresses, min and max for character length limits, match to ensure a field matches another, and both numeric and regex for number validation and pattern matching. All validation errors are collected and can be retrieved using the getErrors() method.

Category:PHP

Load and Parse Code Snippets with Frontmatter

TypeScript

Reads code snippet files with metadata and extracts their contents.

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

export type Snippet = {
    id: string;
    title: string;
    description: string;
    category: string;
    language: string;
    code: string;
    usage: string;
    explanation: string;
    demoUrl: string;
};

export function getSnippets(): Snippet[] {
    const snippetsDir = path.join(process.cwd(), 'src/app/snippets/codesnips');
    const filenames = fs.readdirSync(snippetsDir); // Read all files in the snippets folder

    return filenames.map((filename) => {
        const fullPath = path.join(snippetsDir, filename);
        const fileContents = fs.readFileSync(fullPath, 'utf8');

        // Parse frontmatter and content using gray-matter
        const { data, content } = matter(fileContents);

        // Extract language identifier from the first code block (e.g. ```js)
        const langMatch = content.match(/^```(\w+)/m);
        const language = langMatch ? langMatch[1] : 'plaintext';

        return {
            id: filename,
            title: data.title || filename.replace(/\..+$/, ''),
            description: data.description || '',
            category: language, // Use code language as category
            language: language[0].toUpperCase() + language.slice(1), // Capitalize first letter
            // Strip opening and closing backticks from code block
            code: content.replace(/^```(\w+)\n/, '').replace(/```$/, ''),
            usage: data.usage,
            explanation: data.explanation || '',
            demoUrl: data.demoUrl || '#',
        };
    });
}

Usage Example

Example .md file
---
title: Modal Manager
description: Handles opening and closing of modals.
usage: |
const modal = new ModalManager();
modal.bindTriggers('.open-modal');
modal.open('myModalId');
explanation: |
This class manages modals by binding click triggers and handling closing via Escape or clicking outside.
demoUrl: https://example.com/modal-demo
---
```JavaScript
export class ModalManager {
// modal logic...
}

How it works

This utility function reads markdown (.md) files from a snippets directory, parses the frontmatter metadata (title, description, explanation, etc.), and extracts the code block and its language. It maps each file into a consistent Snippet object used to render code cards or previews in the app. The language is auto-detected from the fenced code block (e.g. ```js), and the frontmatter provides extra data like title and links.

Category:TypeScript

Form Handler

JavaScript

A class for handling form submission and validation in Javascript. Includes smooth scrolling to the first error and re-labeling fields dynamically.

import { wordsUpper } from './utils.js';

export class FormHandler {
    constructor(form) {
        this.form = form;
        this.validationResponse = {};
    }

    // Collect form data into requestData object
    getFormData() {
        const formElements = document.querySelectorAll(`.${this.form.formClass} input, .${this.form.formClass} textarea, .${this.form.formClass} select`);
        const requestData = {};

        formElements.forEach((el) => {
            if (el.name) {
                requestData[el.name] = el.value;
            }
        });

        this.form.requestData = requestData;
    }

    // Submit form data via POST and handle response
    async submit() {
        if (this.dataClass.form === true) {
            this.getFormData();
        }

        try {
            const response = await fetch(this.form.dataUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ requestData: this.form.requestData }),
            });
            const data = await response.json();
            this.checkValidation(data);
            return data;
        } catch (error) {
            console.error('Request failed:', error);
            throw error;
        }
    }

    // Handle server validation result
    checkValidation(data) {
        this.validationResponse = data;
        if (data.success === 1) {
            console.log("Validation successful");
        } else if (data.success === 2) {
            location.reload();
        } else {
            this.readValidation();
        }
    }

    // Display validation errors in the UI
    readValidation() {
        for (const field in this.validationResponse) {
            if (field === "success") continue;

            const label = document.querySelector(`#input-label-${field}`);
            const border = document.querySelector(`#input-border-${field}`);
            const input = document.querySelector(`#input-${field}`);

            label.style.color = 'red';
            label.textContent = this.validationResponse[field];

            border.classList.remove('focus-border');
            border.classList.add('focus-border2');

            input.classList.remove('has-content');
            input.classList.add('has-content2');
        }

        this.scrollToError();
        this.resetInputs();
    }

    // Scroll to the first input with an error
    scrollToError() {
        const fields = Object.keys(this.validationResponse).filter(k => k !== "success");
        if (fields.length) {
            document.querySelector(`#input-${fields[0]}`).scrollIntoView({ behavior: 'smooth', block: 'end' });
        }
    }

    // Reset inputs when user focuses them after an error
    resetInputs() {
        const erroredInputs = document.querySelectorAll('.has-content2');
        erroredInputs.forEach((input) => {
            input.addEventListener('focus', (e) => {
                const field = e.target.id.split('-')[1];
                const label = document.querySelector(`#input-label-${field}`);
                const border = document.querySelector(`#input-border-${field}`);

                label.style.color = '#741404';
                label.textContent = wordsUpper(field.replace(/_/g, ' '));

                border.classList.add('focus-border');
                border.classList.remove('focus-border2');

                e.target.classList.add('has-content');
                e.target.classList.remove('has-content2');
            }, { once: true });
        });
    }
}

  

Usage Example

import {FormHandler} from './FormHandler.js'

document.getElementById('submitBtn').addEventListener('click', () => {
    const formHandler = new FormHandler({
        formClass: 'myForm',
        dataUrl: 'api'
    });

    formHandler.submit()
        .then(response => {
            console.log('Form submitted', response);
        })
        .catch(error => {
            console.error('Error:', error);
        });
});

How it works

This class streamlines front-end form handling by collecting input data from the DOM, sending it to the server via POST, handling success and validation error responses, and managing user feedback by highlighting invalid fields and resetting them when focused.

Category:JavaScript

JavaScript SPA Router

JavaScript

A class for handling navigation, routing, and UI updates in a single-page app.

import { wordsUpper, formatTitle } from './utils.js';

export class Router {
    constructor(config) {
        // Element selectors and app state
        this.container = document.querySelector(config.containerSelector || '#main');
        this.locationDisplay = document.querySelector(config.locationSelector || '.location');
        this.navSelector = config.navSelector || '.navigation-menu';
        this.toggleSelector = config.toggleSelector || '.mobile-toggle-nav';
        this.basePath = config.basePath || '/app/';
        this.defaultPage = config.defaultPage || 'overview';
        this.menuOpen = false;
        this.title = '';
        this.member = config.member || false;
        this.activityActive = false;

        this.bindListeners();

        // Handle browser navigation (back/forward)
        window.addEventListener('popstate', (event) => this.handlePopState(event));
    }

    // Attach event listeners to nav links and toggle button
    bindListeners() {
        document.querySelectorAll(this.navSelector).forEach(nav => {
            nav.removeEventListener('click', this.onNavClick);
            nav.addEventListener('click', (e) => this.onNavClick(e));
        });

        const toggleBtn = document.querySelector(this.toggleSelector);
        if (toggleBtn) {
            toggleBtn.removeEventListener('click', this.onToggleClick);
            toggleBtn.addEventListener('click', () => this.onToggleClick());
        }
    }

    // Handle nav link clicks and route to new page
    onNavClick(event) {
        event.preventDefault();
        const href = event.currentTarget.getAttribute('href');
        if (!href) return;

        this.navigateToUrl(href);
    }

    // Handle mobile nav toggle
    onToggleClick() {
        const appContainer = document.querySelector('.app-container');
        const toggleBtn = document.querySelector(this.toggleSelector);

        toggleBtn.classList.toggle('is-active');
        appContainer.classList.toggle('sidebar-mobile-open');

        // Update location display depending on menu state
        if (!this.menuOpen) {
            this.updateLocationDisplay('Menu');
        } else {
            this.updateLocationDisplay(this.title);
        }

        this.menuOpen = !this.menuOpen;
    }

    // Update internal state and browser URL... then render new page
    navigateToUrl(location) {
        this.location = location;
        this.currentLocation = location.split('/');

        this.title = formatTitle(this.currentLocation.at(-1));
        history.pushState({ page: this.basePath + location }, '', this.basePath + location);

        this.updateLocationDisplay(this.title);
        this.renderPage(this.currentLocation[0]);
    }

    // Handle back/forward navigation via browser controls
    handlePopState(event) {
        if (this.activityActive) {
            this.closeActivity();
        }

        this.location = event.state?.page || this.defaultPage;
        this.currentLocation = this.location.split('/').slice(3);

        this.title = formatTitle(this.currentLocation.at(-1));
        this.updateLocationDisplay(this.title);

        this.renderPage(this.currentLocation[0]);
    }

    // Update the UI element that shows current location/page title
    updateLocationDisplay(text) {
        if (this.locationDisplay) {
            this.locationDisplay.textContent = wordsUpper(text);
        }
    }

    // Render the current page module (if available)
    renderPage(moduleName) {
        if (this[moduleName] && typeof this[moduleName].display === 'function') {
            this[moduleName].display();
        } else {
            console.warn(`Module "${moduleName}" not found`);
            this.container.innerHTML = '<p>Page not found</p>';
        }
    }

    // Close any active activity state (if applicable)
    closeActivity() {
        console.log('Closing activity...');
        this.activityActive = false;
    }
}

How it works

This `Router` class provides basic single-page application (SPA) routing in plain JavaScript. It updates the URL without reloading the page, handles back/forward browser navigation, manages sidebar/menu state, updates the visible location label, and dynamically renders page modules. It supports configuration options like base path, default page, and selectors for containers and buttons. Navigation links are intercepted and routed internally using `history.pushState`, and `popstate` is used for native browser navigation.

Category:JavaScript

Modal Manager

JavaScript

Lightweight utility class to handle modal open/close behavior with ESC key and click outside.

export class ModalManager {
    constructor() {
        this.activeModal = null;

        // Close modal on Escape key press
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape') this.close();
        });
    }

    open(modalId) {
        const modal = document.querySelector(`#${modalId}`);
        if (modal) {
            modal.classList.add('open');
            this.activeModal = modal;

            // Close modal if clicking outside the modal content
            const onClickOutside = (e) => {
                if (e.target === modal) {
                    this.close();
                    modal.removeEventListener('click', onClickOutside);
                }
            };

            modal.addEventListener('click', onClickOutside);
        }
    }

    close() {
        if (this.activeModal) {
            this.activeModal.classList.remove('open');
            this.activeModal = null;
        }
    }

    // Binds click triggers to open modals based on data-target attribute
    bindTriggers(triggerSelector) {
        document.querySelectorAll(triggerSelector).forEach(trigger => {
            trigger.addEventListener('click', (e) => {
                const targetId = trigger.dataset.target;
                this.open(targetId);
            });
        });
    }
}

Usage Example

import { ModalManager } from './modalManager.js';

const modal = new ModalManager();
modal.bindTriggers('.open-modal');

document.querySelector('.close-modal').addEventListener('click', () => {
    modal.close();
});

How it works

This `ModalManager` class helps manage modal dialogs in the browser. It allows opening a modal by ID, closing it via the Escape key or clicking outside the modal content, and binding trigger buttons via a selector. It keeps track of the currently active modal and uses event delegation for flexibility. Useful for simple modal handling in any JavaScript-driven UI without dependencies.

Category:JavaScript