PHPackages                             weldist/laravel-pulse-md5-patch - 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. weldist/laravel-pulse-md5-patch

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

weldist/laravel-pulse-md5-patch
===============================

Laravel Pulse patch for MySQL servers without a usable MD5() function — uses a plain key\_hash column hashed in PHP.

v1.0.0(4w ago)229↓50%MITPHPPHP ^8.1CI passing

Since May 12Pushed 4w ago1 watchersCompare

[ Source](https://github.com/weldist/laravel-pulse-md5-patch)[ Packagist](https://packagist.org/packages/weldist/laravel-pulse-md5-patch)[ RSS](/packages/weldist-laravel-pulse-md5-patch/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (3)Versions (2)Used By (0)

weldist/laravel-pulse-md5-patch
===============================

[](#weldistlaravel-pulse-md5-patch)

[![Tests](https://github.com/weldist/laravel-pulse-md5-patch/actions/workflows/tests.yml/badge.svg)](https://github.com/weldist/laravel-pulse-md5-patch/actions/workflows/tests.yml)[![PHP](https://camo.githubusercontent.com/83dd395020c37276225039739320f6c8e7e99963ab21ee3d09282cb48dad2a60/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d626c7565)](https://www.php.net)[![Laravel Pulse](https://camo.githubusercontent.com/26d86f3d8fc07eb283e4e608e778db78a357edd8ffb576da7e08918dbf7e70a5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f50756c73652d312e782d707572706c65)](https://pulse.laravel.com)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE.md)

A compatibility layer that makes [Laravel Pulse](https://pulse.laravel.com) run on **MySQL servers where the built-in `MD5()` function is unavailable** — most notably MySQL 9.6+ (which removed it from the server core) on managed services where you cannot install the Legacy Hashing component.

> A [weld.ist](https://weld.ist) project.
>
> Unofficial. Not affiliated with Laravel.

The Problem
-----------

[](#the-problem)

Laravel Pulse's default migration defines the `key_hash` column on every `pulse_*` table as a **generated** column built from `md5()`:

```
$table->char('key_hash', 16)->storedAs('unhex(md5(`key`))');
```

As of **MySQL 9.6** (released January 2026), the `MD5()` and `SHA1()` SQL functions have been **removed from the server core** and relocated to a separate, optional **Legacy Hashing component** (`component_legacy_hashing`). On a server where that component is not installed, `md5()` simply does not exist — which breaks Pulse in two ways:

- **Migration fails — or the server won't start.** `php artisan migrate` dies on the first `pulse_*` table because the generated-column expression references a missing function. Worse, in our case the `pulse_*` tables already existed: after the server was upgraded to 9.6 without the component, MySQL itself refused to start until we dropped them.
- **Storage layer assumes a generated column.** Even if you hand-patch the schema, Pulse's `DatabaseStorage` only writes `key` and expects the database to derive `key_hash`. Drop the generated-column expression and the hash is silently `NULL` → unique constraints and upserts break.

The official remedy is to install the Legacy Hashing component:

```
INSTALL COMPONENT 'file://component_legacy_hashing';
```

**But on many managed/hosted MySQL offerings you can't.** They don't expose `INSTALL COMPONENT` or the filesystem path it reads from, so there's no way to restore `MD5()`. (Some of these services also reject `md5()` *inside* generated-column expressions outright — `ERROR 3758 (HY000): Expression of generated column 'key_hash' contains a disallowed function: md5.` — so the generated-column approach never worked there, even on older MySQL versions where `MD5()` itself was still present.)

- **Patching by hand is brittle:** every Pulse upgrade re-publishes the original migration and you re-fight the same error.

The Solution
------------

[](#the-solution)

This package swaps both halves of the assumption:

- **Migration** — ships a replacement for Pulse's default in which `key_hash` is a plain, non-generated column (`char(32)` on MySQL/MariaDB, `uuid` on PostgreSQL, `string` on SQLite).
- **Storage** — binds a `PulseDatabaseStorage` that extends Pulse's `DatabaseStorage` and only flips one switch: `requiresManualKeyHash()` returns `true`, so the `md5()` of `key` is computed in PHP and written alongside it.

```
Pulse default:   INSERT (key)            → DB derives key_hash via unhex(md5(key))   ✗ when MD5() is unavailable
This package:    INSERT (key, key_hash)  → key_hash = md5(key) computed in PHP       ✓

```

Nothing else in Pulse changes — dashboards, recorders, aggregation, trimming all behave exactly as before.

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

[](#requirements)

- PHP `^8.1`
- `laravel/pulse ^1.0`

No MySQL version constraint — it works on 8.x and on 9.6+ (with or without the Legacy Hashing component), since the hash never touches a server-side function.

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

[](#installation)

```
composer require weldist/laravel-pulse-md5-patch
```

The service provider is auto-discovered — no manual registration.

Setup
-----

[](#setup)

Publish this package's migration and run it **instead of** Pulse's own:

```
php artisan vendor:publish --tag=pulse-md5-patch-migrations
php artisan migrate
```

> **Do not** publish or run `php artisan vendor:publish --tag=pulse-migrations`. The two migrations create the same tables and cannot coexist. If you previously ran Pulse's migration, drop the `pulse_values`, `pulse_entries`, and `pulse_aggregates` tables before migrating this one.

That's it.

How It Works
------------

[](#how-it-works)

Default PulseThis package`key_hash` column (MySQL/MariaDB)`char(16) charset binary` — generated via `unhex(md5(key))``char(32)` — populated by PHP `md5()``key_hash` column (PostgreSQL)`uuid` — generated via `md5("key")::uuid``uuid` — `md5("key")::uuid` (unchanged)`key_hash` column (SQLite)`string``string`Storage class`DatabaseStorage``PulseDatabaseStorage` (extends `DatabaseStorage`)`key_hash` sourcedatabase expressionPHP `md5()` (`requiresManualKeyHash() === true`)Storage binding`PulseServiceProvider::register()`overridden in `boot()`, always wins### Why bind in `boot()` instead of `register()`?

[](#why-bind-in-boot-instead-of-register)

`PulseServiceProvider` binds `Storage::class → DatabaseStorage::class` inside its `register()` method. Re-binding in `boot()` — which always runs after every provider's `register()` — guarantees the override takes effect regardless of provider load order.

### Why a plain `char(32)` instead of a generated column?

[](#why-a-plain-char32-instead-of-a-generated-column)

When `MD5()` isn't available server-side (MySQL 9.6+ without the Legacy Hashing component) — and on managed services that additionally forbid `md5()` inside generated-column expressions — there is no generated-column variant that works. Storing the 32-char hex output of PHP's `md5()` directly side-steps database-level computation entirely. (`char(16) BINARY` would also work for raw bytes, but `char(32)` keeps the value human-readable and matches what `requiresManualKeyHash()` emits.)

### Minimal override

[](#minimal-override)

`PulseDatabaseStorage` overrides exactly one method — `requiresManualKeyHash()`. Every other line of Pulse's storage logic is inherited untouched, so upgrades to `laravel/pulse` carry over with no extra work.

Testing
-------

[](#testing)

The suite runs against a **real MySQL** server — the schema and storage behaviour this package changes only matter on MySQL, so SQLite would prove nothing. `docker compose` brings up a `mysql:8.4` container alongside the PHP container automatically; you don't need a local MySQL.

```
# Build first (once per PHP version)
DOCKER_BUILDKIT=0 docker compose --profile php81 build

# Run tests (each profile starts its own MySQL)
docker compose --profile php81 up --abort-on-container-exit --exit-code-from php81   # PHP 8.1
docker compose --profile php82 up --abort-on-container-exit --exit-code-from php82   # PHP 8.2
docker compose --profile php83 up --abort-on-container-exit --exit-code-from php83   # PHP 8.3
docker compose --profile php84 up --abort-on-container-exit --exit-code-from php84   # PHP 8.4
docker compose --profile php85 up --abort-on-container-exit --exit-code-from php85   # PHP 8.5

# Run a single test class or method
docker compose --profile php81 run --rm php81 vendor/bin/phpunit --filter PulseStorageMysqlTest
docker compose --profile php81 run --rm php81 vendor/bin/phpunit --filter test_value_is_persisted_with_php_computed_key_hash
```

Running `vendor/bin/phpunit` directly (outside Docker) works too — point it at a MySQL instance via `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` (defaults: `127.0.0.1:3306`, db/user/pass all `testing`).

CI runs PHP 8.1–8.5 via `.github/workflows/tests.yml`.

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](https://opensource.org/license/MIT).

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance94

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity42

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

Unknown

Total

1

Last Release

28d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2bdb64c6c087c331b8bd5906bb1aa7eb06bc83af3654a48ba8ab9da365976651?d=identicon)[X-Adam](/maintainers/X-Adam)

---

Top Contributors

[![x-adam](https://avatars.githubusercontent.com/u/60411758?v=4)](https://github.com/x-adam "x-adam (2 commits)")

---

Tags

laravelmysqlMD5pulsepatchkey-hash

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/weldist-laravel-pulse-md5-patch/health.svg)

```
[![Health](https://phpackages.com/badges/weldist-laravel-pulse-md5-patch/health.svg)](https://phpackages.com/packages/weldist-laravel-pulse-md5-patch)
```

###  Alternatives

[tpetry/laravel-mysql-explain

Get Visual MySQL EXPLAIN for Laravel.

265166.1k](/packages/tpetry-laravel-mysql-explain)[moharrum/laravel-adminer

Adminer database management tool for your Laravel application.

451.0k](/packages/moharrum-laravel-adminer)[mpyw/laravel-mysql-system-variable-manager

A tiny extension of MySqlConnection that manages session system variables

116.0k](/packages/mpyw-laravel-mysql-system-variable-manager)[vitalibr/laravel5-exporter

MySQL Workbench Schema Exporter for Laravel 5.0

161.0k](/packages/vitalibr-laravel5-exporter)

PHPackages © 2026

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