PHPackages                             aternos/rados-ffi - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. aternos/rados-ffi

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

aternos/rados-ffi
=================

An object oriented PHP library for using librados with FFI

v1.1.2(2y ago)1124LGPL-2.1-onlyPHP

Since Mar 22Pushed 2y ago1 watchersCompare

[ Source](https://github.com/aternosorg/php-rados-ffi)[ Packagist](https://packagist.org/packages/aternos/rados-ffi)[ RSS](/packages/aternos-rados-ffi/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (1)Versions (5)Used By (0)

php-rados-ffi
=============

[](#php-rados-ffi)

An object oriented PHP library for using librados with FFI.

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

[](#requirements)

- Linux
- PHP 8.1 or later
- php-ffi
- librados

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

[](#installation)

```
composer require aternos/rados-ffi
```

Why not phprados?
-----------------

[](#why-not-phprados)

The [phprados](https://github.com/ceph/phprados) extension is a native PHP extension that provides bindings to librados. Unfortunately, it has been largely unmaintained for the past few years. While it does compile for the latest version of PHP, many of the included rados functions [do not work as intended and can cause crashes](https://github.com/ceph/phprados/pull/35). Additionally, phprados only adds bindings for a small subset of the librados API.

php-rados-ffi provides a modern, object-oriented, and complete interface to librados using PHP's FFI system. Through FFI, PHP can load shared libraries like librados and call their functions directly. This allows using librados without a native PHP extension, making it easier to install and safer to update.

Usage
-----

[](#usage)

Before the library can be used, the librados shared library must be loaded. This can be done using the `initialize()` method of the [`Rados`](src/Rados.php) class.

```
$rados = \Aternos\Rados\Rados::getInstance()->initialize();
```

### Preloading

[](#preloading)

To preload librados, ensure that FFI preloading is enabled and add the following line to your `opcache.preload` file:

```
\Aternos\Rados\Rados::getInstance()->preload();
```

Rados can then be initialized by calling `initializePreloaded()` instead of `initialize()`.

```
$rados = \Aternos\Rados\Rados::getInstance()->initializePreloaded();
```

### Cluster

[](#cluster)

The [`Rados`](src/Rados.php) instance can then be used to create a [`Cluster`](src/Cluster/Cluster.php) instance, which is used to connect to a Ceph cluster.

```
$cluster = $rados->createCluster();
$cluster->configReadFile('/etc/ceph/ceph.conf');
$cluster->connect();
```

Once connected, a [`Cluster`](src/Cluster/Cluster.php) object can be used to perform operations and request information about the cluster. It is, for example, possible to ping monitors, request the cluster's ID, or list pools.

```
var_dump($cluster->pingMonitor("mon1"));
var_dump($cluster->getClusterFsid());

foreach ($cluster->getPools() as $pool) {
    echo $pool->getName() . PHP_EOL;
}
```

### Pool

[](#pool)

[`Pool`](src/Cluster/Pool/Pool.php) objects contain general information about a pool, and can be used to obtain an [`IOContext`](src/Cluster/Pool/IOContext.php).

```
$ioContext = $pool->createIOContext();
```

### IOContext

[](#iocontext)

[`IOContext`](src/Cluster/Pool/IOContext.php) objects are used to perform operations on a pool. It can, for example, be used to iterate over objects in the pool, or to get a specific object.

```
foreach ($ioContext->createObjectIterator() as $entry) {
    echo $entry->getObject()->getId() . PHP_EOL;
}

$object = $ioContext->getObject("object1");
```

### RadosObject

[](#radosobject)

A `RadosObject` represents an object in a Ceph pool, and can be used to read and write data or modify attributes.

```
// Write full object
$object->writeFull("Hello, World");

// Write at offset
$object->write("World", 7);

//Append to object
$object->append("!");

// Read from object
echo $object->read(13, 0) . PHP_EOL;
```

### Async operations and completions

[](#async-operations-and-completions)

Many IO operations can be performed asynchronously. Asynchronous operations return a [`ResultCompletion`](src/Completion/ResultCompletion.php) object, which can be used to track the status of the operation and to wait for its completion.

```
$completion = $object->writeFullAsync("Hello, World");
```

To check the status of a completion, the `isComplete()` method can be used.

```
if ($completion->isComplete()) {
    echo "Operation is complete" . PHP_EOL;
}
```

It is also possible to block until the operation is complete using the `waitForComplete()` method.

```
$completion->waitForComplete();
$completion->isComplete(); // true
```

Completions can be canceled by calling the `cancel()` method.

```
$completion->cancel();
```

The result of the operation can be obtained using the `getResult()` method. The type of the result depends on the operation that was performed.

```
$result = $completion->getResult();
```

If the operation failed, the `getResult()` method will throw an exception.

Likewise, an exception will be thrown if the operation was not completed yet. To avoid this, `waitAndGetResult()` can be used to block until the operation is complete and to get the result.

```
$result = $completion->waitAndGetResult();
```

### Object operations

[](#object-operations)

[Object operations](https://docs.ceph.com/en/latest/rados/api/librados/#breathe-section-title-object-operations) allow performing multiple tasks on an object atomically. Write and read operations can be created by calling `$rados->createWriteOperation()` and `$rados->createReadOperation()` respectively.

```
$object = $ioContext->getObject("object1");

$operation = $rados->createWriteOperation();
$operation->addTask(new \Aternos\Rados\Operation\Common\Task\AssertExistsTask());
$operation->addTask(new \Aternos\Rados\Operation\Write\Task\AppendTask("Hello, World"));
$operation->operate($object);
```

Some tasks, especially in read operations, will return data. This data can be accessed by calling `getResult()` on the task object after the operation has been completed.

If the task failed, `getResult()` may throw an exception.

```
$object = $ioContext->getObject("object1");
$object->writeFull("Hello, World");

$operation = $rados->createReadOperation();
$task = new \Aternos\Rados\Operation\Read\Task\ReadTask(0, 12);
$operation->addTask($task);
$operation->operate($object);

echo $task->getResult() . PHP_EOL;
```

If a single task in an operation fails, the entire operation will fail. This can be avoided by adding the `OperationTaskFlag::FailOK` flag to tasks that are allowed to fail.

```
$task = new \Aternos\Rados\Operation\Common\Task\CompareExtTask("Hello_", 0);
$task->setFlags([\Aternos\Rados\Constants\OperationTaskFlag::FailOK]);
```

Operations can also be executed asynchronously, using the `operateAsync()` method.

#### Available tasks

[](#available-tasks)

##### Common

[](#common)

- [`AssertExistsTask`](src/Operation/Common/Task/AssertExistsTask.php)
- [`AssertVersionTask`](src/Operation/Common/Task/AssertVersionTask.php)
- [`CompareExtTask`](src/Operation/Common/Task/CompareExtTask.php)
- [`CompareXAttributeTask`](src/Operation/Common/Task/CompareXAttributeTask.php)
- [`OMapCompareTask`](src/Operation/Common/Task/OMapCompareTask.php)

##### Read

[](#read)

- [`ChecksumTask`](src/Operation/Read/Task/ChecksumTask.php)
- [`ExecuteTask`](src/Operation/Read/Task/ExecuteTask.php) (with output data)
- [`GetXAttributesTask`](src/Operation/Read/Task/GetXAttributesTask.php)
- [`OMapGetByKeysTask`](src/Operation/Read/Task/OMapGetByKeysTask.php)
- [`OMapGetKeysTask`](src/Operation/Read/Task/OMapGetKeysTask.php)
- [`OMapGetTask`](src/Operation/Read/Task/OMapGetTask.php)
- [`ReadTask`](src/Operation/Read/Task/ReadTask.php)
- [`StatTask`](src/Operation/Read/Task/StatTask.php)

##### Write

[](#write)

- [`AppendTask`](src/Operation/Write/Task/AppendTask.php)
- [`CreateObjectTask`](src/Operation/Write/Task/CreateObjectTask.php)
- [`ExecuteTask`](src/Operation/Write/Task/ExecuteTask.php) (without output data)
- [`OMapClearTask`](src/Operation/Write/Task/OMapClearTask.php)
- [`OMapRemoveKeyRangeTask`](src/Operation/Write/Task/OMapRemoveKeyRangeTask.php)
- [`OMapRemoveKeysTask`](src/Operation/Write/Task/OMapRemoveKeysTask.php)
- [`OMapSetTask`](src/Operation/Write/Task/OMapSetTask.php)
- [`RemoveTask`](src/Operation/Write/Task/RemoveTask.php)
- [`RemoveXAttributeTask`](src/Operation/Write/Task/RemoveXAttributeTask.php)
- [`SetAllocHintTask`](src/Operation/Write/Task/SetAllocHintTask.php)
- [`SetXAttributeTask`](src/Operation/Write/Task/SetXAttributeTask.php)
- [`TruncateTask`](src/Operation/Write/Task/TruncateTask.php)
- [`WriteFullTask`](src/Operation/Write/Task/WriteFullTask.php)
- [`WriteSameTask`](src/Operation/Write/Task/WriteSameTask.php)
- [`WriteTask`](src/Operation/Write/Task/WriteTask.php)
- [`ZeroTask`](src/Operation/Write/Task/ZeroTask.php)

### Exceptions and error handling

[](#exceptions-and-error-handling)

If a Rados operation fails, it will throw a [`RadosException`](src/Exception/RadosException.php).
The error code returned from librados can be obtained using the `getCode()` method.

To check whether an error has a specific error code, the `is()` method can be used.

```
try {
    $cluster->getPool("nonexistent")->createIOContext();
} catch (\Aternos\Rados\Exception\RadosException $e) {
    if ($e->is(\Aternos\Rados\Generated\Errno::ENOENT)) {
        echo "Pool does not exist" . PHP_EOL;
    }
}
```

Available Rados features
------------------------

[](#available-rados-features)

This library aims to implement the full librados API. There are, however, some features can't be implemented due to limitations in PHP's FFI system.

### Not planned

[](#not-planned)

- Callback functions for completions
- Watch/Notify
- Log callbacks

PHP callback functions can be passed to C functions using FFI, but they can only be called (more or less) safely from the main thread. Since both completions and watches can be called from any thread, using PHP callback functions is not feasible.

### Implemented, but not really supported

[](#implemented-but-not-really-supported)

Some librados features are poorly documented to a point where I do not understand what they are supposed to do. These features have bindings in this library, but I can't guarantee that they work as intended. Currently, this includes:

- Self-managed snapshots
- rados\_(un)set\_pool\_full\_try

How to not segfault
-------------------

[](#how-to-not-segfault)

The library uses FFI to call into the librados shared library. To avoid crashes from incorrect usage of librados, only call methods and constructors that are `public` and not marked as `@internal` in the source code.

Methods marked as `@internal` are not part of the public API and should not be called directly.

License
-------

[](#license)

php-rados-ffi - PHP library for Ceph RADOS using FFI
Copyright (C) 2024 Aternos GmbH

This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1, as published by the Free Software Foundation. See file LICENSE.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Documentation comments in this library are derived from documentation comments from librados. The file includes/librados.h is generated from librados.h, which is part of Ceph. Source code for Ceph is available at

Ceph - scalable distributed file system
Copyright (C) 2004-2012 Sage Weil

This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1, as published by the Free Software Foundation. See file LICENSE.

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity44

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 ~5 days

Total

4

Last Release

771d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/182e603c02f308d1036a1ecaba0b994665e87d13a86ff4550a96c9189a92c544?d=identicon)[aternos](/maintainers/aternos)

---

Top Contributors

[![KurtThiemann](https://avatars.githubusercontent.com/u/26512466?v=4)](https://github.com/KurtThiemann "KurtThiemann (45 commits)")

---

Tags

cephffilibradosphprados

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/aternos-rados-ffi/health.svg)

```
[![Health](https://phpackages.com/badges/aternos-rados-ffi/health.svg)](https://phpackages.com/packages/aternos-rados-ffi)
```

###  Alternatives

[hybridinteractive/craft-position-fieldtype

Brings back the Position fieldtype from Craft 2

16177.5k3](/packages/hybridinteractive-craft-position-fieldtype)

PHPackages © 2026

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