angkor/laravel-support
angkor/laravel-support provides practical helpers and utilities for Laravel applications, simplifying common tasks and promoting cleaner, more consistent code. Lightweight, easy to install, and designed to integrate smoothly into existing projects.
angkor/laravel-support is a foundation package: it ships shared helpers, contracts, traits, a validator layer, and a base controller that the rest of the Angkor suite builds on. Treat it as infrastructure you inherit rather than a feature you call directly.
Install and inspect
composer require angkor/laravel-support
Laravel's package auto-discovery should register the service provider. Confirm it landed:
php artisan about # provider list
composer show angkor/laravel-support
Then read the source before writing code against it. This package has zero dependents and zero stars, so the README is likely thinner than the code. Walk these in order:
composer.json — PHP and Laravel version constraints, PSR-4 namespace (expect Angkor\Support\...), and any extra.laravel providers/aliases.src/ top-level directories — usually Contracts/, Traits/, Validators/, Http/Controllers/, and a helpers.php or Support/ folder.config/ — if a config file exists, publish it: php artisan vendor:publish --tag=angkor-support.First use case
The fastest way to get value is the validator functionality, because it is self-contained and does not require you to adopt the base controller. Find the rule class or trait, then wire it into a FormRequest:
use Angkor\Support\Validators\...; // confirm exact FQCN from src/
class StoreOrderRequest extends FormRequest
{
public function rules(): array
{
return [
'reference' => ['required', 'string', new YourDiscoveredRule()],
];
}
}
If instead you find a ValidatesRequests-style trait, apply it to a controller and call its validation method with your rules array.
Second use case
Extend the base controller for a single new controller and see what it gives you for free (likely AuthorizesRequests, ValidatesRequests, JSON response helpers, or a standard error envelope). Do this on a throwaway controller first — do not retrofit your existing controller hierarchy until you know what the base class overrides.
Compose traits rather than extend
The package's value is mostly in traits. Prefer use over inheritance so you keep your own base classes:
class Invoice extends Model
{
use \Angkor\Support\Traits\HasUuid; // verify actual trait names
use \Angkor\Support\Traits\HasStatus;
}
Before applying a trait to a model, grep it for boot{TraitName}() methods, $this-> assumptions, and protected $casts / $fillable merging. A trait that mutates $fillable will surprise you on models that already define it.
Program to the contracts
The Contracts/ directory is the intended seam. Type-hint interfaces in your own services and let the package (or your app) supply the implementation:
use Angkor\Support\Contracts\...;
class SyncService
{
public function __construct(private readonly YourContract $impl) {}
}
Then rebind in your own provider if the default behavior is wrong for you:
$this->app->singleton(YourContract::class, App\Impl\CustomImpl::class);
Do this in AppServiceProvider::register() and it wins over the package's binding, provided the package uses singleton/bind and not instance.
Base controller as a thin layer
If you adopt the base controller, extend it once and put your app's shared behavior on top:
namespace App\Http\Controllers;
use Angkor\Support\Http\Controllers\Controller as AngkorController;
abstract class Controller extends AngkorController
{
// your shared helpers
}
Then every controller extends App\Http\Controllers\Controller. This contains the blast radius if the package changes its base class API.
Package-development pattern
The real intended workflow: if you are building on other Angkor packages, this one is a transitive dependency. Add it explicitly to your composer.json at the same version constraint the sibling packages use, so you get a consistent helper API rather than whichever version Composer resolves.
Helpers
If the package registers global helper functions (check autoload.files in its composer.json), they are callable anywhere. Use them in Artisan commands, jobs, and Blade — places where injection is awkward — but prefer injected services in application code so the dependency stays visible.
Validation in tests
Validator rules are the easiest thing to unit-test without booting HTTP:
$rule = new YourDiscoveredRule();
$v = Validator::make(['field' => 'bad'], ['field' => [$rule]]);
$this->assertTrue($v->fails());
Pin these tests early. Rule behavior is the most likely thing to shift between releases.
Zero-adoption risk is the headline. Zero stars and zero dependents means essentially no public bug surface and no community answers. Read the source, and pin an exact version ("angkor/laravel-support": "1.2.*" or a commit hash) in composer.lock. Do not use dev-main. Diff between releases before upgrading — there is no changelog culture you can rely on.
Helper function collisions. Global helpers are the classic footgun. If the package defines str_slug-style helpers that collide with laravel/helpers, symfony/string polyfills, or your own app/helpers.php, you get a fatal "cannot redeclare function" at autoload time. Check autoload.files in the package's composer.json and grep your app for the same names.
Trait method conflicts. Two traits defining the same method is a fatal error unless you resolve it. Use insteadof/as:
use AngkorTrait, AppTrait {
AngkorTrait::format insteadof AppTrait;
AppTrait::format as appFormat;
}
Base controller overrides. A package base controller that overrides AuthorizesRequests or ValidatesRequests can silently change exception handling and validation response shape. If your API suddenly returns a different 422 JSON envelope after installing, look here first. Check Illuminate\Foundation\Auth\Access\AuthorizesRequests usage and any failedValidation implementation.
Validation translation keys. Custom rules usually reference lang/*/validation.php keys prefixed with the package vendor (e.g. angkor-support::validation.foo). If the package ships translations, verify they are loaded — a missing namespace gives you the raw key in error messages. Publish them and translate as needed.
Debugging a silent no-op. If a trait or helper appears to do nothing, the service provider probably didn't register. Confirm with php artisan about, or dump app()->getLoadedProviders() and grep for Angkor. If auto-discovery is disabled in your app, add the provider manually to bootstrap/providers.php.
Extension points, ranked by safety. Container bindings for contracts are the safest customization. Config file values are next. Subclassing the base controller is fine if you extend once. Monkey-patching helpers is not possible — if a helper does the wrong thing, stop using it and write your own.
Do not build a hard dependency without an exit plan. Because the package is pre-adoption, wrap your usage: if you use its traits, keep the trait's surface area small; if you use its contracts, have a local interface mirror. That way replacing it later is a mechanical change rather than a rewrite.
How can I help you explore Laravel packages today?