# Use the PHP SDK

**Applies to:** current development source bundles. Obtain a matched client/server release through [early-access support](mailto:info@simplemagic.com); registry publication is not available yet. Paths below are relative to the supplied source checkout.

Synchronous PHP 8.2+ client using FFI and `libsmkv`. Requires 64-bit PHP, ext-ffi,
and ext-json. Initial source package; not published to Packagist.

## Install

Build/install the [C transport](c-client.html). Set `SMKV_LIBRARY` to the
absolute path of its shared library. Install OpenSSL/json-c runtime dependencies.
Load `src/Client.php` directly or use this directory as a Composer path repository
with package `simplemagic/smkv` (dev-main). Composer metadata includes a classmap.

FFI must be enabled for the process. For CLI examples use:

```sh
SMKV_LIBRARY=/absolute/path/libsmkv.so php -d ffi.enable=1 your-app.php
```

On macOS the suffix is `.dylib`. PHP-FPM/web deployments need administrator-enabled
FFI; shared hosts may disallow it. Do not enable FFI globally merely for a demo.
Native binaries must match the process's OS and architecture; Windows is unqualified.

## Usage

```php
require 'php-smkv/src/Client.php';
use SimpleMagic\Smkv\{Client, Bytes, WriteOptions};

$client = new Client('127.0.0.1:7379');
try {
    $client->put('greeting', "hello\0", new WriteOptions(ttlMs: 60000, sync: true));
    echo $client->get('greeting');
    $users = $client->table('users');
    $users->put('42', ['name'=>'Ada', 'visits'=>1, 'payload'=>new Bytes("\0\xff")]);
    $users->update('42', ['visits'=>2]);
    print_r($users->get('42', ['name', 'visits']));
} finally { $client->close(); }
```

Raw keys/values are binary PHP strings. Column strings are UTF-8 text; wrap binary
columns in `Bytes` (reads also return Bytes). Other values are int64, float64, and bool.
Numeric-looking column names follow PHP array-key conversion rules.

`WriteOptions` supports TTL, sync, replicaAck, durableReplicaAck. Omitted TTL means
no expiry on put, preserved expiry on update; zero expires immediately. Delete
rejects TTL. Updates atomically set/remove columns; get supports projection.

## Cluster, security, and errors

`Client::cluster(['host:7381'])` accepts **management** seeds. The first request
discovers owners. `get($key, replica: true)` explicitly permits stale reads.
Constructor arrays accept the [native config schema](c-client.html#configuration-routing-and-security):
`timeout_ms`, record limits, independent `security` and `management_security`.
A `ca` PEM path enables verified TLS; `name`/`token` enable auth. Both are optional.
Certificates and endpoint hostnames/IPs are always verified; no TLS downgrade.

`SmkvException::$status` identifies server/client errors; `outcomeUnknown` means a
mutation may have completed. Do not blindly retry. Only explicit WrongOwner is
retried automatically. Defaults are five-second total timeout, 1 KiB key limit,
and 1 MiB value limit. DNS may outlive the timeout; numeric endpoints avoid this.

One client retains one connection; create clients after worker fork and close them
explicitly. Native handles cannot be cloned or serialized. Calls block the PHP
thread; fibers do not make them asynchronous. No scans, batching, async API, or
load qualification yet. See [tests](sdk-clients.html#initial-release-limits).

Run `php -d ffi.enable=1 php-smkv/examples/basic.php 127.0.0.1:7379` after setting
`SMKV_LIBRARY`, against a disposable node. This writes expiring example records.

## Logical databases

Select the database when constructing the client (or cluster client):

```php
new Client(['endpoint' => '127.0.0.1:7379', 'database' => 'orders'])
```

Omitting the option uses `default` and preserves existing wire keys. Named
databases require database-aware development servers (cluster protocol 5, or 6
with experimental group sync). Names use 1–64 ASCII letters, digits, `_` or `-`.
The selection scopes raw keys and all table operations, including replica reads.
The complete database-prefixed key is hashed for routing and counts against the
key-size limit. Databases share cluster capacity and durability settings.

Use the matching database-aware native library and, for Java, JNI bridge. These
bindings require the ABI 2 constructor `smkv_create_v2`; an older library fails to
load or construct a client rather than silently selecting the default database.
