dynamophp/hash
Generate a deterministic float hash for any string mapped to the range 0–360. Uses a primary hash (e.g., SHA-256), then converts selected leading/trailing characters into a numeric value within the interval.
Installation:
composer require baptistecontreras/dynamo-php-hash
Add the package to composer.json under require.
Basic Usage:
use BaptisteContreras\DynamoPHPHash\Hash;
$angle = Hash::generate('example-string');
// Returns a float between 0 and 360
First Use Case: Generate a consistent angle for UI elements (e.g., circular progress bars, dynamic avatars):
$userAngle = Hash::generate(auth()->user()->email);
$style = "transform: rotate({$userAngle}deg);";
Deterministic Angle Generation:
$hash = Hash::generate($inputString);
// Use $hash for circular layouts, color hues, or directional logic
Custom Hash Algorithm:
$hash = Hash::generate($input, 'sha1'); // Override default 'sha256'
Laravel Service Binding:
Register the service in AppServiceProvider:
$this->app->singleton('hash', function () {
return new Hash(algorithm: 'sha256', x: 5, y: 5);
});
Use via dependency injection:
public function __construct(private Hash $hash) {}
Model Events:
Attach to created events for dynamic attribute generation:
public function created(Model $model) {
$model->angle = Hash::generate($model->id);
$model->save();
}
Caching: Cache results for static inputs (e.g., product IDs):
$angle = Cache::remember("hash_{$productId}", now()->addHours(1), function () use ($productId) {
return Hash::generate($productId);
});
Blade Directives:
@php
$dynamicStyle = "background-color: hsl({{ Hash::generate($user->name) }}, 100%, 50%)";
@endphp
<div style="{{ $dynamicStyle }}">...</div>
API Responses:
return response()->json([
'data' => $items,
'meta' => [
'angles' => collect($items)->map(fn($item) => Hash::generate($item->id)),
],
]);
Testing:
public function test_hash_reproducibility() {
$this->assertEquals(123.45, Hash::generate('test')); // Replace with actual expected value
}
Query Scopes: Filter records by hashed ranges (application-layer filtering):
public function scopeInAngleRange($query, $min, $max) {
return $query->where(function($q) use ($min, $max) {
$q->where('id', '>=', $min)
->orWhere('id', '<=', $max);
})->get()->filter(function($item) use ($min, $max) {
return Hash::generate($item->id) >= $min && Hash::generate($item->id) <= $max;
});
}
Floating-Point Precision:
$rounded = round(Hash::generate($input), 2);
$this->assertEquals($rounded, 123.45);
Non-Uniform Distribution:
X/Y parameters if needed.Empty/Null Inputs:
Hash::generate(null) or Hash::generate('') returns 0.0.$input = $input ?? 'default-fallback';
Performance Under Load:
sha1).Database Storage:
DECIMAL(6,2) for angles or store as integers (e.g., intval($hash * 100)).Collisions:
$angle = Hash::generate($input) + (rand() / 1000);
\Log::debug("Hash for '{$input}': " . Hash::generate($input));
$hashes = collect(range(1, 1000))->map(fn($i) => Hash::generate("test-$i"));
$hashes->sort()->unique()->count(); // Check for collisions
Custom Parameters:
The constructor accepts x (first characters) and y (last characters) to tune the hash:
$hash = new Hash(algorithm: 'sha256', x: 8, y: 4);
x/y values increase entropy but may reduce precision.Algorithm Limitations:
ripemd128 may not work).sha256, sha1, or md5.Custom Transformations:
Extend the class to add methods like toHex() or toColor():
class ExtendedHash extends Hash {
public function toHex(): string {
return sprintf('#%06x', (int)round($this->generate() / 360 * 0xFFFFFF));
}
}
Alternative Ranges:
Override the transformation logic to support other ranges (e.g., [0;100]):
class CustomRangeHash extends Hash {
protected function transform(string $hash): float {
return (float) $hash * 100 / pow(2, 256);
}
}
Input Normalization: Preprocess inputs for consistency (e.g., lowercase, trim):
class NormalizedHash extends Hash {
public function generate(string $input): float {
return parent::generate(mb_strtolower(trim($input), 'UTF-8'));
}
}
Service Container Binding: Bind the service with custom parameters:
$this->app->singleton(Hash::class, function () {
return new Hash(algorithm: config('app.hash_algorithm'), x: config('app.hash_x'), y: config('app.hash_y'));
});
Environment Configuration:
Add to config/app.php:
'hash' => [
'algorithm' => env('HASH_ALGORITHM', 'sha256'),
'x' => env('HASH_X', 5),
'y' => env('HASH_Y', 5),
],
Facade for Convenience: Create a facade to simplify usage:
// app/Facades/Hash.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Hash extends Facade {
protected static function getFacadeAccessor() {
return 'hash';
}
}
Usage:
use App\Facades\Hash;
$angle = Hash::generate($input);
Memoization: Cache results in memory for repeated calls:
$cache = [];
$hash = function ($input) use ($cache) {
return $cache[$input] ?? $cache[$input] = Hash::generate($input);
};
Batch Processing: For bulk operations, precompute hashes:
$inputs = ['user1', 'user2', 'user3'];
$hashes = collect($inputs)->map(fn($input) => Hash::generate($input));
How can I help you explore Laravel packages today?