PHPackages                             fsans/fms-odata-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. fsans/fms-odata-php

ActiveLibrary[HTTP &amp; Networking](/categories/http)

fsans/fms-odata-php
===================

PHP client for the Claris FileMaker Server OData v4 API. Functional equivalent of fms-odata-js and fms-odata-py. Depends on fsans/fms-odata-spec-php for shared types, error hierarchy, auth helpers, and URL literal formatting.

v1.0.1(1mo ago)00MITPHPPHP ^8.2CI passing

Since Jul 12Pushed 1mo agoCompare

[ Source](https://github.com/fsans/fms-odata-php)[ Packagist](https://packagist.org/packages/fsans/fms-odata-php)[ RSS](/packages/fsans-fms-odata-php/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (3)Versions (4)Used By (0)

fms-odata-php
=============

[](#fms-odata-php)

[![PHP](https://camo.githubusercontent.com/9b504182096c7b89606aec97b1fa43f4f8dc233a5535ad43fdca6ce15f14e929/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344382e322d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://www.php.net/)[![OData](https://camo.githubusercontent.com/9e7d06ecb53cc29a161dc5efdd2ba36f7fc7f7f7b897fe844718f01f03dfbef8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f446174612d76342d3030373844343f6c6f676f3d64617461266c6f676f436f6c6f723d7768697465)](https://www.odata.org/)[![FileMaker](https://camo.githubusercontent.com/3fed200305a760f40144b6196ba8b9caed3fb39a30fea642e0e555caf9518dae/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c654d616b65722d32302e302d2d32362e302d4646364230303f6c6f676f3d66696c656d616b6572266c6f676f436f6c6f723d7768697465)](https://www.claris.com/filemaker/)[![Deps](https://camo.githubusercontent.com/d02b652bbba9caf16b0b97480e7e5ec5204831145956027a364f4b0f832bb799/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f72756e74696d65253230646570732d312d626c7565)](./composer.json)[![License](https://camo.githubusercontent.com/5e0abb27bc77af909f6e0c7cd00eee168f348ba6cbde1d3b1bcb5789c20477fd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c61636b)](./LICENSE)[![Spec](https://camo.githubusercontent.com/eafa90fb162306e024ec738d338a53564d32ae83f9407424ca0b286774e3873c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f737065632d666d732d2d6f646174612d2d737065632d4646364230303f6c6f676f3d66696c656d616b6572266c6f676f436f6c6f723d7768697465)](https://github.com/fsans/fms-odata-spec)[![Ask DeepWiki](https://camo.githubusercontent.com/0f5ae213ac378635adeb5d7f13cef055ad2f7d9a47b36de7b1c67dbe09f609ca/68747470733a2f2f6465657077696b692e636f6d2f62616467652e737667)](https://deepwiki.com/fsans/fms-odata-php)

PHP client for the Claris FileMaker Server OData v4 API.

Functional equivalent of [fms-odata-js](https://github.com/fsans/fms-odata-js)and [fms-odata-py](https://github.com/fsans/fms-odata-py).

Status
------

[](#status)

Core client functionality is implemented: configuration, cURL-backed HTTP transport with auth and 401 retry, fluent query builder, entity CRUD, script execution, container field I/O, metadata parsing, version detection, and feature gating.

> **Note:** `$batch`, schema DDL, and webhook management are not yet ported from the JS/Python clients. See the roadmap section below.

Spec alignment
--------------

[](#spec-alignment)

This library is aligned with the [fms-odata-spec](https://github.com/fsans/fms-odata-spec) reference specification and depends on [`fsans/fms-odata-spec-php`](https://packagist.org/packages/fsans/fms-odata-spec-php)for shared types, error hierarchy, auth helpers, and URL literal formatting.

Requirements
------------

[](#requirements)

- PHP 8.2 or later
- `ext-curl` (the cURL extension)

Installation
------------

[](#installation)

```
composer require fsans/fms-odata-php
```

Quick start
-----------

[](#quick-start)

```
use FmsOData\FMSOData;

$client = FMSOData::create(
    host: 'https://fms.example.com',
    database: 'Contacts',
    token: FmsOData\Spec\Auth\Auth::basicAuth('user', 'password'),
);

// Query records
$result = $client->from('Contacts')
    ->select('id', 'name', 'email')
    ->filter(fn (FilterFactory $f) => $f->eq('active', true))
    ->orderBy('name')
    ->top(10)
    ->get();

foreach ($result->value as $record) {
    echo $record['name'] . "\n";
}

// Get a single record by key
$record = $client->from('Contacts')->byKey(42)->get();

// Create a record
$created = $client->from('Contacts')->create(['name' => 'Jane', 'email' => 'jane@example.com']);

// Update a record (PATCH)
$client->from('Contacts')->byKey(42)->patch(['name' => 'Jane Doe']);

// Update with optimistic concurrency
$client->from('Contacts')->byKey(42)->patch(
    ['name' => 'Jane Doe'],
    new EntityWriteOptions(ifMatch: 'W/"abc123"'),
);

// Delete a record
$client->from('Contacts')->byKey(42)->delete();

// Run a FileMaker script at database scope
$result = $client->script('Greet', parameter: 'world');
echo $result->resultParameter;  // text result from Exit Script

// Run a script by FMSID (v26+; survives renames)
$client->scriptById(42, parameter: 'hello');

// Run a script at entity-set scope
$client->from('Contacts')->script('ValidateAll');

// Run a script at record scope (current record = this entity)
$client->from('Contacts')->byKey(42)->script('Notify', parameter: 'updated');

// Download a container field
$dl = $client->from('Contacts')->byKey(42)->container('Photo')->get();
echo $dl->size;           // byte length
echo $dl->contentType;    // e.g. image/png
echo $dl->filename;       // parsed from Content-Disposition
\file_put_contents('/tmp/photo.png', $dl->data);

// Upload to a container field (binary, MIME auto-sniffed from magic bytes)
$client->from('Contacts')->byKey(42)->container('Photo')->upload(
    data: \file_get_contents('/tmp/photo.png'),
    filename: 'photo.png',
);

// Upload via base64 JSON (for multi-field or mixed container+regular updates)
use FmsOData\Spec\Containers\ContainerEncoding;
$client->from('Contacts')->byKey(42)->container('Photo')->upload(
    data: \file_get_contents('/tmp/photo.png'),
    contentType: 'image/png',
    filename: 'photo.png',
    encoding: ContainerEncoding::BASE64,
);

// Update multiple container fields + regular fields in one request
$client->from('Contacts')->byKey(42)->patchContainers(
    [
        'Photo' => ['data' => $pngBytes, 'contentType' => 'image/png', 'filename' => 'p.png'],
        'Doc'   => ['data' => $pdfBytes, 'contentType' => 'application/pdf'],
    ],
    ['name' => 'Jane'],
);

// Clear a container field
$client->from('Contacts')->byKey(42)->container('Photo')->delete();

// Fetch metadata
$metadata = $client->metadata();
echo $metadata->namespace . "\n";
foreach ($metadata->entityTypes as $type) {
    echo "  Table: {$type->name}\n";
}

// Detect server version
$version = $client->version();       // FMVersionMajor::V21
$info = $client->versionInfo();      // FMVersionInfo
$client->hasFeature('webhooks');     // bool
```

Architecture
------------

[](#architecture)

The client is layered into pure request builders and an HTTP execution layer:

- **Query, Filter, EntityRef, Url** — build pure request data (URLs, filter expressions, key references). No direct cURL calls.
- **ScriptInvoker** — FileMaker script invocation at database, entity-set, and record scope (by name or FMSID). Reuses spec-php script helpers.
- **ContainerRef** — container field download (binary), upload (binary or base64), and clear. MIME sniffing and Content-Disposition via spec-php.
- **HttpClient** — handles auth, OData headers, 401 retry, JSON/XML decoding, and error conversion. Uses a `TransportInterface` for the actual HTTP call.
- **CurlTransport** — the production transport, using PHP's built-in cURL extension. The only transport shipped.
- **MockTransport** (test only) — deterministic in-memory transport for offline test execution.
- **MetadataParser / MetadataFetcher** — parse `$metadata` XML and cache the result.
- **Client / FMSOData** — the entry point, wiring everything together and providing version detection and feature gates.

Shared DTOs, enums, error classes, auth helpers, and URL literal formatting are sourced from `FmsOData\Spec` (the `fsans/fms-odata-spec-php` package).

FileMaker OData quirks handled
------------------------------

[](#filemaker-odata-quirks-handled)

- URL encoding: spaces are `%20` (not `+`), commas, `$`, `=`, `;`, `(`, `)`, and `'` are preserved as literal characters in query strings.
- Required headers: `OData-Version: 4.0` and `OData-MaxVersion: 4.0` are sent on every request.
- Error responses: both JSON (`{error: {code, message}}`) and XML (``) error bodies are parsed.
- Version detection: from `$metadata` XML `ProductVersion`/`ServerVersion`annotations.
- `Prefer` header: `return=minimal` (default) or `return=representation`.
- `ETag`/`If-Match`: for optimistic concurrency on PATCH and DELETE.

Roadmap
-------

[](#roadmap)

The following features are implemented in the JS and Python clients but not yet ported to PHP:

- `$batch` multipart request composer
- Schema DDL (create/delete tables, fields, indexes)
- Webhook management (create, remove, get, invoke)

Development
-----------

[](#development)

```
composer install
composer test        # PHPUnit (238 tests)
composer analyse     # PHPStan level max
composer check       # tests + static analysis
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

2

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e31bd27918523411356f90b32995c9e9287ded42815ab2cc2dc989e60e89bed0?d=identicon)[fsans](/maintainers/fsans)

---

Top Contributors

[![fsans](https://avatars.githubusercontent.com/u/90167?v=4)](https://github.com/fsans "fsans (12 commits)")

---

Tags

phpclientrestFileMakerodataclarisfms

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/fsans-fms-odata-php/health.svg)

```
[![Health](https://phpackages.com/badges/fsans-fms-odata-php/health.svg)](https://phpackages.com/packages/fsans-fms-odata-php)
```

###  Alternatives

[james.rus52/tinkoffinvest

PHP client Tinkoff Invest

683.0k](/packages/jamesrus52-tinkoffinvest)[openapi/openapi-sdk

Minimal and agnostic PHP SDK for Openapi® (https://openapi.com)

164.6k1](/packages/openapi-openapi-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
