PHPackages                             cycle/transaction - 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. [Database &amp; ORM](/categories/database)
4. /
5. cycle/transaction

ActiveLibrary[Database &amp; ORM](/categories/database)

cycle/transaction
=================

Transaction abstraction for Cycle ORM: run DBAL operations and a scoped Entity Manager within a single database transaction.

1.1.0(1mo ago)03491BSD-3-ClausePHPPHP &gt;=8.2CI passing

Since Jun 24Pushed 1mo agoCompare

[ Source](https://github.com/cycle/transaction)[ Packagist](https://packagist.org/packages/cycle/transaction)[ RSS](/packages/cycle-transaction/feed)WikiDiscussions 1.x Synced 2w ago

READMEChangelog (2)Dependencies (20)Versions (3)Used By (1)

 [   ![CycleORM Logo](https://github.com/cycle/.github/raw/main/logo/words-vector-light.svg?raw=true)  ](https://cycle-orm.dev)

[![Build Status](https://camo.githubusercontent.com/344e2cfbfb833227c70df6b5708e24cf0fcfdcf996f2d8d93ac9140b613755ae/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6379636c652f7472616e73616374696f6e2f74657374696e672e796d6c3f6272616e63683d312e78267374796c653d666c61742d737175617265266c6162656c3d7465737473)](https://github.com/cycle/transaction/actions)[![Codecov Coverage](https://camo.githubusercontent.com/aa656b4b81ccc26696b1f6bd8399a180d0c498504f6a425689844c206d89934a/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6379636c652f7472616e73616374696f6e2f312e783f7374796c653d666c61742d737175617265266c6f676f3d636f6465636f76)](https://app.codecov.io/gh/cycle/transaction/tree/1.x)[![Mutation testing badge](https://camo.githubusercontent.com/9129f12ca0d4290709d64c624915d2937e72ec1fb7b10bd946dbf718ea4e63bc/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742d737175617265266c6162656c3d6d75746174696f6e25323073636f72652675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d2532466379636c652532467472616e73616374696f6e253246312e78)](https://dashboard.stryker-mutator.io/reports/github.com/cycle/transaction/1.x)

[![Discord](https://camo.githubusercontent.com/82e12441f19f24f02114101c123dc4aae710b4e80f4ec464a85195f8d56cdd71/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3533383131343837353537303931333239303f7374796c653d666c61742d737175617265266c6f676f3d646973636f7264266c6162656c436f6c6f723d373238396439266c6f676f436f6c6f723d776869746526636f6c6f723d333934353664)](https://discord.gg/spiralphp)[![Follow on Twitter (X)](https://camo.githubusercontent.com/91c1c3b545d03e0c79f91364259b2814308d2b3786c67c8578740879528ff37c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d466f6c6c6f772d626c61636b3f7374796c653d666c61742d737175617265266c6f676f3d58)](https://x.com/intent/follow?screen_name=SpiralPHP)

Transaction Abstraction for Cycle ORM
=====================================

[](#transaction-abstraction-for-cycle-orm)

This library provides a small transaction abstraction for Cycle ORM. It opens a single database transaction and lets you run raw DBAL operations together with a scoped [Entity Manager](https://cycle-orm.dev/docs/advanced-entity-manager) inside it.

Everything executed within the callback shares one transaction: if the callback throws, the transaction is rolled back; otherwise it is committed. The Entity Manager is scoped to a single database connection for the duration of the callback, so accidental cross-connection writes are rejected instead of silently splitting your work across transactions.

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

[](#installation)

The preferred way to install this package is through [Composer](https://getcomposer.org/).

```
composer require cycle/transaction
```

[![PHP Version Require](https://camo.githubusercontent.com/72e93d823a455b20f6c62a95c2f9bfa49d2e5d7d35d30ce35712325640ab06e3/68747470733a2f2f706f7365722e707567782e6f72672f6379636c652f7472616e73616374696f6e2f726571756972652f7068703f7374796c653d666c61742d737175617265)](https://packagist.org/packages/cycle/transaction)[![Latest Stable Version](https://camo.githubusercontent.com/8afc4effdeb1ad12e1d887dccbf1ce4965b8250397878aa7db379b194bf04116/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6379636c652f7472616e73616374696f6e3f267374796c653d666c61742d737175617265)](https://packagist.org/packages/cycle/transaction)[![License](https://camo.githubusercontent.com/50721652d801159d00b963c6098674916a310342e4aedd32bc4187914ff0a20b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6379636c652f7472616e73616374696f6e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Total Downloads](https://camo.githubusercontent.com/7c195ff62b7964561dbcfa0ba30fe225264646264445b9cb5fe309b7e318b257/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6379636c652f7472616e73616374696f6e3f267374796c653d666c61742d737175617265)](https://packagist.org/packages/cycle/transaction)

Usage
-----

[](#usage)

### Obtaining a Transaction

[](#obtaining-a-transaction)

The package ships a single implementation of the `Cycle\Transaction\Transaction` interface. Build it from your configured ORM and DBAL, or resolve `Cycle\Transaction\Transaction` from your framework's container if it is registered there.

```
use Cycle\Transaction\Internal\TransactionImpl;
use Cycle\Transaction\Transaction;

/**
 * @var \Cycle\ORM\ORMInterface $orm
 * @var \Cycle\Database\DatabaseProviderInterface $dbal
 */
$transaction = new TransactionImpl($orm, $dbal);
```

### Basic Example

[](#basic-example)

The callback receives the scoped `EntityManagerInterface` and the `DatabaseInterface` of the resolved connection. Persisted entities are flushed and committed automatically when the callback returns.

```
use Cycle\Database\DatabaseInterface;
use Cycle\ORM\EntityManagerInterface;

$transaction->transact(function (EntityManagerInterface $em, DatabaseInterface $db): void {
    $em->persist(new User('john@example.com'));

    // The same transaction is visible to raw DBAL operations.
    $db->table('audit')->insertOne(['event' => 'user.created']);
});
```

If the callback throws, the whole transaction — both the Entity Manager changes and the raw DBAL operations — is rolled back.

```
$transaction->transact(function (EntityManagerInterface $em): void {
    $em->persist(new User('john@example.com'));

    throw new \DomainException('Something went wrong');
    // Nothing is committed: the new user is rolled back.
});
```

### Returning a Value

[](#returning-a-value)

`transact()` returns whatever the callback returns.

```
$user = $transaction->transact(function (EntityManagerInterface $em): User {
    $user = new User('john@example.com');
    $em->persist($user);

    return $user;
});
```

### Flush Modes

[](#flush-modes)

The `FlushMode` enum controls when and how the scoped Entity Manager flushes its pending changes. Pass it via the `$flush` argument (defaults to `FlushMode::BeforeCommit`).

ModeBehaviour`FlushMode::OnWrite`Flush every `persist`/`persistState`/`delete` to the database immediately.`FlushMode::BeforeCommit`Collect all changes and flush them once, right before the transaction is committed. **(default)**`FlushMode::FailOnPending`Do not flush automatically; throw a `TransactionException` if any changes are still pending.`FlushMode::SkipPending`Do not flush automatically; silently discard any pending changes (only DBAL operations are committed).```
use Cycle\Transaction\FlushMode;

// Require the callback to flush explicitly; otherwise the transaction fails.
$transaction->transact(
    callback: function (EntityManagerInterface $em): void {
        $em->persist(new User('john@example.com'));
        $em->run(); // explicit flush — without it a TransactionException is thrown
    },
    flush: FlushMode::FailOnPending,
);
```

### Transaction Modes

[](#transaction-modes)

The `TransactionMode` enum controls how the Entity Manager's Unit of Work interacts with the open transaction. Pass it via the `$emMode` argument (defaults to `TransactionMode::Current`).

ModeBehaviour`TransactionMode::Current`Reuse the currently opened transaction. Throws if none is open. **(default)**`TransactionMode::OpenNew`Open a new inner transaction per driver connection and close it on finish.`TransactionMode::Ignore`Do not manage transactions for the Unit of Work.`TransactionMode::Exclusive`Like `OpenNew`, but require the transaction to be top-level. Throws if wrapped by another.```
use Cycle\Transaction\TransactionMode;

$transaction->transact(
    callback: function (EntityManagerInterface $em): void {
        $em->persist(new User('john@example.com'));
    },
    emMode: TransactionMode::OpenNew,
);
```

### Selecting the Database

[](#selecting-the-database)

By default the transaction runs against the default database connection. Use the `$source` argument to pick another connection — either by its name or by an entity class mapped to it. The scoped Entity Manager then rejects entities that belong to a different connection.

```
// By connection name.
$transaction->transact(
    callback: fn(EntityManagerInterface $em, DatabaseInterface $db) => $db->getName(),
    source: 'reporting',
);

// By entity class — resolves the connection the entity is mapped to.
$transaction->transact(
    callback: function (EntityManagerInterface $em): void {
        $em->persist(new User('john@example.com'));
    },
    source: User::class,
);
```

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance92

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 93.3% 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 ~0 days

Total

3

Last Release

39d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/796136?v=4)[Anton Tsitou](/maintainers/wolfy-j)[@wolfy-j](https://github.com/wolfy-j)

---

Top Contributors

[![roxblnfk](https://avatars.githubusercontent.com/u/4152481?v=4)](https://github.com/roxblnfk "roxblnfk (14 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

###  Code Quality

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/cycle-transaction/health.svg)

```
[![Health](https://phpackages.com/badges/cycle-transaction/health.svg)](https://phpackages.com/packages/cycle-transaction)
```

###  Alternatives

[cycle/orm

PHP DataMapper ORM and Data Modelling Engine

1.3k922.8k86](/packages/cycle-orm)[cycle/annotated

Cycle ORM Annotated Entities generator

29817.4k57](/packages/cycle-annotated)[cycle/schema-builder

Cycle ORM Schema Builder

15857.4k30](/packages/cycle-schema-builder)[wayofdev/laravel-cycle-orm-adapter

🔥 A Laravel adapter for CycleORM, providing seamless integration of the Cycle DataMapper ORM for advanced database handling and object mapping in PHP applications.

3642.5k3](/packages/wayofdev-laravel-cycle-orm-adapter)[cycle/active-record

Provides a simple way to work with your database using Active Record pattern and Cycle ORM

672.0k5](/packages/cycle-active-record)[cycle/migrations

Database migrations, migration scaffolding

21621.7k42](/packages/cycle-migrations)

PHPackages © 2026

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