PHPackages                             mallardduck/immutable-read-file - 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. mallardduck/immutable-read-file

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

mallardduck/immutable-read-file
===============================

An experiment in making an 'immutable' wrapper for PHP's file functions.

1.0.0(5y ago)112MITPHPPHP ^7.4 || ^8.0

Since Dec 15Pushed 5y ago1 watchersCompare

[ Source](https://github.com/mallardduck/immutable-read-file)[ Packagist](https://packagist.org/packages/mallardduck/immutable-read-file)[ RSS](/packages/mallardduck-immutable-read-file/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (5)Versions (15)Used By (0)

ImmutableReadFile - An immutable read-only file wrapper for PHP
===============================================================

[](#immutablereadfile---an-immutable-read-only-file-wrapper-for-php)

[![Latest Stable Version](https://camo.githubusercontent.com/a063fa9792146ccfe574526594c84fc7595182e2e739251925982fc7fa5def8a/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f76)](//packagist.org/packages/mallardduck/immutable-read-file)[![Total Downloads](https://camo.githubusercontent.com/8d59ade7141216c677f05fa62a373b23173e81181800954c2e82bcc09496a5e6/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f646f776e6c6f616473)](//packagist.org/packages/mallardduck/immutable-read-file)[![License](https://camo.githubusercontent.com/ee412e1269aeeb42003d4caf878edfeb3ac77cc68e3411125d0cfaa014ac5402/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f6c6963656e7365)](//packagist.org/packages/mallardduck/immutable-read-file)[![codecov](https://camo.githubusercontent.com/b0d56a64b8ee1908c24848c4a94d639e6404b35788ccdfa752eb51a2e23df4c9/68747470733a2f2f636f6465636f762e696f2f67682f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f6272616e63682f6d61737465722f67726170682f62616467652e7376673f746f6b656e3d493256444b384735424d)](https://codecov.io/gh/mallardduck/immutable-read-file)[![Coverage Status](https://camo.githubusercontent.com/1bdba642bb3186a32f4bee3e40982a843d018ff9b2dc0d7b1a82cfc0e7f2fd60/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/mallardduck/immutable-read-file?branch=master)[![Latest Unstable Version](https://camo.githubusercontent.com/9fa1ffc490481741119438762d0d1d946a2b9662511af2cff8f44044dfe3f42c/68747470733a2f2f706f7365722e707567782e6f72672f6d616c6c6172646475636b2f696d6d757461626c652d726561642d66696c652f762f756e737461626c65)](//packagist.org/packages/mallardduck/immutable-read-file)

If you've ever used `fopen`/`SplFileObject` and wanted the results to be idempotent1 this is de way.

With this library you get a read-only immutable wrapper for the basic SplFileObject - which is essentially the OOP fopen.

You probably would only rarely have a use case for this but if you do you'll know...and it may be hecking useful.

1 = Only technically because the wrapper tracks a "canonical" position to always work from.

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

[](#installation)

You can install the package via composer:

```
composer require mallardduck/immutable-read-file
```

Usage
-----

[](#usage)

```
use MallardDuck\ImmutableReadFile\ImmutableFile;

$fileName = __DIR__ . '/tests/stubs/json.txt'; // CONTENT: {"hello": "world"}

$step1 = ImmutableFile::fromFilePath($fileName);
echo $step1->fgetc(); // { - The first character of your file
echo $step1->fgetc(); // { - The first character of your file, again
$step2 = $step1->advanceBytePosition(); // A new r/o immutable entity advanced a single byte by default.
echo $step2->fgetc(); // " - The second character of your file
echo $step2->fgetc(); // " - The second character of your file, again
```

Why! I don't get it?
--------------------

[](#why-i-dont-get-it)

So, you were warned that this would only be useful rarely - but when it is useful it's hecking useful. You did read that right?

The main way to understand when this is useful is to understand how it's different from `fopen` or `SplFileObject`. Since this will be useful in cases when the default behavior of those is not desired.

So see for yourself! Examples...

### How `fopen` works by default

[](#how-fopen-works-by-default)

The use of a second `fopen`, and the `fseek`, are to emulate what `$step1->advanceBytePosition()` does in the usage example.

```
$fileName = __DIR__ . '/tests/stubs/json.txt'; // CONTENT: {"hello": "world"}

$step1 = fopen($fileName, 'r');
echo fgetc($step1) . PHP_EOL; // { - The first character of your file
echo fgetc($step1) . PHP_EOL; // " - The second character of your file
$step2 = fopen($fileName, 'r');
fseek($step2, 1);
echo fgetc($step2) . PHP_EOL; // " - The second character of your file
echo fgetc($step2) . PHP_EOL; // h - The third character of your file
```

### How `SplFileObject` works by default

[](#how-splfileobject-works-by-default)

The use of a second `new SplFileObject`, and the `$step2->fseek(1)`, are to emulate what `$step1->advanceBytePosition()` does in the usage example.

```
$fileName = __DIR__ . '/tests/stubs/json.txt'; // CONTENT: {"hello": "world"}

$step1 = new SplFileObject($fileName, 'r');
echo $step1->fgetc() . PHP_EOL; // { - The first character of your file
echo $step1->fgetc() . PHP_EOL; // " - The second character of your file
$step2 = new SplFileObject($fileName, 'r');
$step2->fseek(1);
echo $step2->fgetc() . PHP_EOL; // " - The second character of your file
echo $step2->fgetc() . PHP_EOL; // h - The third character of your file
```

### Summary

[](#summary)

Comparing the ways that `fopen` and `SplFileObject` work we can see they are functionally identical to each other. However, this also highlights how they are different from `ImmutableReadFile`.

When you use a method on either `fopen`/`SplFileObject` that returns content, then the current cursor position is incremented. That means when you run `fgetc` on these you'll always get either: the next character, or the EOF.

However for `ImmutableReadFile`, these methods do not affect the cursor position. This means that if you run `fgetc`, you'll always get the same exact character. Only until you explicitly advance the byte position will you get a novel character. When that happens you're actually getting a new instance of `ImmutableFile` too.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Dan Pock](https://github.com/mallardduck)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity65

Established project with proven stability

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

Recently: every ~32 days

Total

13

Last Release

1840d ago

Major Versions

0.5.3 → 1.0.02021-04-24

PHP version history (2 changes)0.0.1PHP ^7.4

0.5.3PHP ^7.4 || ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/801be8ba9bfb0cb2629f51f9753a0392683c2680fe3e941a188495840d920333?d=identicon)[MallardDuck](/maintainers/MallardDuck)

---

Top Contributors

[![mallardduck](https://avatars.githubusercontent.com/u/619938?v=4)](https://github.com/mallardduck "mallardduck (46 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mallardduck-immutable-read-file/health.svg)

```
[![Health](https://phpackages.com/badges/mallardduck-immutable-read-file/health.svg)](https://phpackages.com/packages/mallardduck-immutable-read-file)
```

PHPackages © 2026

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