PHPackages                             netglue/revs - 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. netglue/revs

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

netglue/revs
============

Simple utility for revving file name versions and deleting old revisions

1.6.1(4mo ago)0147.7k↑129.5%[1 issues](https://github.com/netglue/revs/issues)[1 PRs](https://github.com/netglue/revs/pulls)MITPHPPHP ~8.3 || ~8.4 || ~8.5CI passing

Since Sep 24Pushed 2w ago1 watchersCompare

[ Source](https://github.com/netglue/revs)[ Packagist](https://packagist.org/packages/netglue/revs)[ RSS](/packages/netglue-revs/feed)WikiDiscussions 1.7.x Synced 3d ago

READMEChangelog (9)Dependencies (7)Versions (23)Used By (0)

Filename Hashing Revisions &amp; Automatic Cleanup
==================================================

[](#filename-hashing-revisions--automatic-cleanup)

[![Continuous Integration](https://github.com/netglue/revs/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/netglue/revs/actions/workflows/continuous-integration.yml)

Probably re-inventing the wheel here, but I wanted to be able to rev front-end resource file names in a predictable way with options to automatically delete old revisions keeping either none of them or a specific number of the most recent ones. There are javascript tools that do this but at the time of writing, I couldn't find anything I liked in JS land that you could just fire off from an npm package script easily. There's plenty for Grunt and Gulp if you're using those.

The main use-case for this lib is to be triggered by a script in your `package.json` something like this:

```
{
    "scripts": {
        "css:rev": "vendor/bin/rev netglue:rev -s \"build/css/*.css\" -t \"public/assets/css\" -d -c 1 -r \"module/layouts/*.phtml\""
    }
}
```

Install with composer
---------------------

[](#install-with-composer)

```
composer require netglue/revs
```

In order to use the tools, make sure that you've `require`d composers `vendor/autoload.php`, or [use the shipped binary](#symfony-command) in `vendor/bin/rev`

Operation
---------

[](#operation)

Say you have a file in `/my/frontend/whatever.css`, and you want a hashed filename in `/my/public/assets/{hashed-file-name}.css`, you'd do something like this:

```
use Netglue\Revs\Revver;
use Netglue\Revs\RevverOptions;
use Netglue\Revs\RevvedFile;

$options = new RevverOptions();
$options->setDestinationDirectory('/my/public/assets');
$revver = new Revver($options);
/** @var RevvedFile $result */
$result = $rever->revFile('/my/frontend/whatever.css');
var_dump($result->destination()); // Yields the full path and filename of the copied file.
```

The options object can be fed an array like this:

```
use Netglue\Revs\RevverOptions;
$options = RevverOptions::fromArray([
    'destinationDirectory' => '/my/public/assets',
    'clean_up' => true,
    'revision_count' => 10,
]);
```

By default, no old revisions will be deleted, so the revision count parameter is irrelevant. You must explicitly enable it.

Resulting File Names
--------------------

[](#resulting-file-names)

Yeah, they’re pretty long because they are composed of `original-filename-{md5 hash}-{UUID1}.extension` - the file names include a time-based UUID so that an accurate time can be computed for the time the file was generated, hence being able to sort them and make sure we're deleting the oldest revisions when appropriate. It might make sense to get rid of the md5 hash, but that's what's used to determine whether the file has actually changed or not. If the hash hasn't changed between operations, the process is halted.

Removing old versions
---------------------

[](#removing-old-versions)

Specifying a 'revision count' in options and setting cleanup to true will keep that many old versions in the target directory. So with a revision count of 1, you'd have the current and next most recent versions.

The return value of `Revver::revFile()` can tell you the paths of any deleted files if you're interested.

Replacement in Files…
---------------------

[](#replacement-in-files)

Assuming you have some file that needs references to these 'revved' file names updating, you can use the return value of `\Netglue\Revs\Revver::revFile()` to perform replacement on a string, or in another file on disk, for example:

```
use Netglue\Revs\Revver;
use Netglue\Revs\RevvedFile;
use Netglue\Revs\Replacer;

/** @var RevvedFile $result */
$result = $rever->revFile('/my/frontend/whatever.css');
$replacementCount = Replacer::replaceInFile('/my/layout.html', $result);
// …or…
$resultingString = Replacer::replaceInString($someString, $result, $count);
// $count is an int with the number of replacements
```

Putting it together
-------------------

[](#putting-it-together)

Assuming you have somehow received notification that your JS is built to a file located in `/build/index.js` and you want that copied to `/public/assets` with a revved file name and all the html files in `/public` to be updated with the new file name:

```
$options = RevverOptions::fromArray([
    'destinationDirectory' => '/public/assets',
    'cleanUp' => true,
    'revisionCount' => 1,
]);
$revver = new Revver($options);
$info = $revver->revFile('/build/index.js');
printf(
    "New revision of %s copied to %s. %d old revisions deleted\n",
     basename($info->source()),
     dirname($info->destination()),
     count($info->deletedRevisions())
);
$count = 0;
$files = glob('/public/*.html');
foreach ($files as $html) {
    $count += Replacer::replaceInFile(sprintf('/public/%s', $html), $info);
}
printf('Replaced %d references over %d files', $count, count($files));
```

Symfony Command
---------------

[](#symfony-command)

Composer will create a binary in `vendor/bin/rev` after installation which you can call from build scripts. There’s straightforward help in the command itself so just issue `vendor/bin/rev netglue:rev --help` to get an overview of the options.

Test
----

[](#test)

`cd` to wherever the module is installed, issue a `composer install` followed by a `composer check`.

Contributions
-------------

[](#contributions)

PR's are welcomed. Please write tests for new features.

Support
-------

[](#support)

You're welcome to file issues, but please understand that finding the time to answer support requests is very limited so there might be a long wait for an answer.

About
-----

[](#about)

[Netglue makes websites and apps in Devon, England](https://netglue.uk). We hope this is useful to you and we’d appreciate feedback either way :)

###  Health Score

59

—

FairBetter than 98% of packages

Maintenance87

Actively maintained with recent releases

Popularity32

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity89

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 79.9% 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 ~157 days

Recently: every ~128 days

Total

19

Last Release

6d ago

PHP version history (6 changes)1.0.0PHP &gt;=7.1

1.1.0PHP &gt;=7.3

1.2.0PHP ~8.1 || ~8.2

1.3.0PHP ~8.1 || ~8.2 || ~8.3

1.5.0PHP ~8.2 || ~8.3 || ~8.4

1.6.0PHP ~8.3 || ~8.4 || ~8.5

### Community

Maintainers

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

---

Top Contributors

[![renovate[bot]](https://avatars.githubusercontent.com/in/2740?v=4)](https://github.com/renovate[bot] "renovate[bot] (318 commits)")[![gsteel](https://avatars.githubusercontent.com/u/2803720?v=4)](https://github.com/gsteel "gsteel (80 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/netglue-revs/health.svg)

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

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k95.4M306](/packages/laravel-horizon)[shlinkio/shlink

A self-hosted and PHP-based URL shortener application with CLI and REST interfaces

5.1k5.2k](/packages/shlinkio-shlink)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M572](/packages/shopware-core)

PHPackages © 2026

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