.mamluk Loading last commit info...
src
tests
.gitignore
LICENSE
README.md
composer.json
composer.lock
README.md

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require

Kipchak by Mamluk

Kipchak by Mamluk

Kipchak is a PHP 8.4+ API Development Kit (ADK) built on Slim Framework v4, designed for rapid API development and optimised for FrankenPHP in worker mode.

The core package provides the bootstrap layer, base classes, interfaces, and HTTP helpers. Drivers and middlewares are installed as separate packages alongside it.

Full documentation: https://kipchak.dev


Install

composer require kipchak/core

To get started with a complete working project, use the starter template:

composer create-project kipchak/starter [api-name] -s dev

What's in the Core

Class / InterfaceDescription
Kipchak\Core\ApiBootstrap entry point
Kipchak\Core\Components\Controllers\BaseBase controller with container and logger
Kipchak\Core\Components\Http\ResponseJSON, redirect, and raw response helpers
Kipchak\Core\Components\Http\RequestQuery param and attribute helpers
Kipchak\Core\Interfaces\DriverInterface all drivers must implement
Kipchak\Core\Interfaces\MiddlewareInterface all middlewares must implement
Kipchak\Core\FunctionsGlobal helper functions: env(), config(), dump()

Bootstrapping

Api::boot()

Bootstraps a full HTTP API. Loads drivers, middlewares, and routes from the project root — then returns a configured App instance ready to run.

// html/index.php (FrankenPHP worker mode)
$app = Kipchak\Core\Api::boot();
$app->addBodyParsingMiddleware();

frankenphp_handle_request(function () use ($app) {
    $app->run();
});

Api::bootCli()

Bootstraps a CLI application. Loads drivers only — no middlewares or routes — and returns the App instance.

$app = Kipchak\Core\Api::bootCli();

Boot sequence

Api::boot() performs these steps in order:

  1. Creates a php-di/php-di DI container
  2. Creates the Slim App instance and adds routing middleware
  3. Loads all .php files from drivers/ (your driver registrations)
  4. Loads all .php files from middlewares/ (your middleware registrations)
  5. Loads all .php files from routes/ (your route definitions)

HTTP Helpers

Http\Response

All response methods set Content-Type, X-Powered-By, and the HTTP status code.

JSON response — wraps data in the standard response envelope:

use Kipchak\Core\Components\Http;

return Http\Response::json($response, ['key' => 'value'], 200);

// With HTTP caching headers:
return Http\Response::json($response, $data, 200, cache: true, cacheTTL: 3600);

Redirect:

return Http\Response::redirect($response, 'https://example.com', 302);

Raw text response:

return Http\Response::raw($response, 'plain text', 200);

Http\Request

use Kipchak\Core\Components\Http;

// Read a query parameter (?name=value), returns null if absent
$value = Http\Request::getQueryParam($request, 'name');

// Read a request attribute (set by middleware)
$token = Http\Request::getAttribute($request, 'token');

Response Envelope

Http\Response::json() always wraps data in this envelope:

{
    "code": 200,
    "status": "OK",
    "data": { ... }
}

Controllers

Controllers extend Kipchak\Core\Components\Controllers\Base, which injects:

  • $this->container — the DI container (Psr\Container\ContainerInterface)
  • $this->logger — a Monolog\Logger instance
namespace Api\Controllers\v1;

use Kipchak\Core\Components\Controllers;
use Kipchak\Core\Components\Http;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class Example extends Controllers\Base
{
    public function get(ServerRequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
    {
        $this->logger->info('Handling request');

        return Http\Response::json($response, ['hello' => 'world'], 200);
    }
}

Helper Functions

Defined in Kipchak\Core\Functions and available globally once Api::boot() is called.

env(string $name, string $default): string

Reads an environment variable, returning $default if it is not set.

use function Kipchak\Core\env;

$host = env('DB_HOST', 'localhost');

config(string $file): array

Loads a PHP config file from the project's config/ directory by name (without the .php extension). Returns an empty array if the file does not exist.

use function Kipchak\Core\config;

$settings = config('kipchak.api'); // loads config/kipchak.api.php

dump(mixed $data): ResponseInterface

Renders a variable to the HTTP response. Use this instead of var_dump() or print_r(), which do not work in FrankenPHP worker mode. Can only be called from inside a controller or middleware.

use function Kipchak\Core\dump;

return dump($someVariable);

Driver Interface

All drivers implement Kipchak\Core\Interfaces\Driver:

interface Driver
{
    public static function initialise(ContainerInterface $container, ?string $configFileName = null);
    public static function set(?string $configFileName = null);
    public static function get(?string $configKey = null);
}
  • initialise() — stores the container reference and calls set()
  • set() — reads config and registers service(s) into the DI container
  • get() — retrieves a registered service from the container by key

Container keys follow the convention drivers.<category>.<name>.<connection>, for example drivers.cache.memcached.default.

Minimal driver example

namespace My\Driver;

use Kipchak\Core\Interfaces;
use Kipchak\Driver\Config\Config;
use Psr\Container\ContainerInterface;

class MyDriver implements Interfaces\Driver
{
    protected static ContainerInterface $container;

    public static function initialise(ContainerInterface $container, ?string $configFileName = null): void
    {
        self::$container = $container;
        self::set($configFileName);
    }

    public static function set(?string $configFileName = null): void
    {
        $config = Config::get($configFileName ?? 'kipchak.mydriver');
        self::$container->set('drivers.mydriver.default', fn() => new MyService($config));
    }

    public static function get(?string $configKey = null): MyService
    {
        return self::$container->get('drivers.mydriver.' . ($configKey ?? 'default'));
    }
}

Register it in drivers/drivers.php:

MyDriver::initialise($container);

Middleware Interface

All middlewares implement Kipchak\Core\Interfaces\Middleware:

interface Middleware
{
    public static function initialise(App $app);
}

initialise() receives the App instance and calls $app->add() to register the middleware globally, or conditionally based on config.

Minimal middleware example

namespace My\Middleware;

use Kipchak\Core\Interfaces;
use Kipchak\Core\Components\App;

class MyMiddleware implements Interfaces\Middleware
{
    public static function initialise(App $app): void
    {
        $app->add(new MyMiddlewareHandler());
    }
}

Register it in middlewares/middlewares.php:

MyMiddleware::initialise($app);

Available Drivers

The following driver packages are available. Install any of them with composer require:

Community (MIT)

PackageDescription
kipchak/driver-configLoads PHP config files from config/. Always required.
kipchak/driver-loggerPSR-3 logger (Monolog)
kipchak/driver-httpPSR-18 HTTP client (Laravel HTTP)
kipchak/driver-filecacheFile-based cache (Symfony Cache)
kipchak/driver-memcachedMemcached pools (Symfony Cache)
kipchak/driver-couchdbApache CouchDB 3.x document store
kipchak/driver-doctrineDoctrine DBAL and ORM for MySQL / MariaDB
kipchak/driver-rabbitmqRabbitMQ publisher and subscriber
kipchak/driver-s3S3-compatible object storage
kipchak/driver-gitGit repository operations over HTTPS
kipchak/driver-openaiOpenAI chat completions with default model injection
kipchak/driver-anthropicAnthropic Claude messages with default model injection
kipchak/driver-cloudflare-dnsCloudflare DNS zone and record management
kipchak/driver-cloudnsClouDNS zone and record management

Enterprise

PackageDescription
kipchak/driver-valkeyRedis / Valkey cache (standalone, sentinel, cluster, replica)
kipchak/driver-opensearchOpenSearch client (multi-connection, multiple auth types)
kipchak/driver-kafkaKafka producer and consumer (ext-rdkafka)
kipchak/driver-oauth2-tokenOAuth 2.0 client credentials token management

Available Middlewares

PackageDescription
kipchak/middleware-errorStandardised JSON error responses for unhandled exceptions
kipchak/middleware-auth-keyAPI key validation via header or query parameter
kipchak/middleware-auth-jwksBearer JWT validation against a remote JWKS URI
kipchak/middleware-auth-mtlsMutual TLS client certificate validation
kipchak/middleware-subashiWAF with OWASP rules, rate limiting, IP/header allow/blocklists
kipchak/middleware-subashi-proEnterprise WAF with RBAC, AuthN/AuthZ, and JWKS
kipchak/middleware-auth-jwtJWT validation with a local public key (Enterprise)

Enterprise Edition

Enterprise drivers and middlewares are available with a commercial licence. To enquire, contact us at https://mamluk.net/contact.


Technical Stack

ComponentProvider
FrameworkSlim Framework
DI ContainerPHP-DI
ORMDoctrine
HTTP ClientLaravel HTTP
LoggingMonolog
Object MappingCuyZ Valinor
OpenAPI DocsZircote Swagger PHP
CouchDB ClientMamluk CouchDB Client
RabbitMQ ClientTavshan by Mamluk
CacheSymfony Cache

Migrating from 1.x

  • Package name changed from mamluk/kipchak to kipchak/core
  • Namespace changed from Mamluk\Kipchak to Kipchak
  • The project is now modular: drivers and middlewares are separate packages
  • Interfaces (Driver, Middleware) have been added for writing extensions
  • The starter project has been updated to reflect the new structure

Migrating from 0.x

  • Session management has been removed (APIs should be stateless)
  • Zircote Swagger PHP added for generating OpenAPI documentation from PHP attributes
  • Doctrine upgraded to 3.5+, which may introduce breaking changes if you extended core Doctrine classes without explicit return types

About

  • Company: Mamluk
  • Name origin: Named after the Turkic Kipchak family which founded the Mamluk Sultanate of Cairo in 1250
  • Documentation: https://kipchak.dev
  • License: MIT
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover