songshenzong/support
Support utilities for Laravel and PHP applications, bundling reusable helper functions and small tools that reduce boilerplate. Simple to install and call from anywhere, it offers a convenient home for common array, string, and formatting helpers.
Treat songshenzong/support as a grab-bag utility library rather than a framework extension. It ships no service provider conventions you can rely on, so onboarding is almost entirely a source-reading exercise.
1. Install and pin it exactly
composer require songshenzong/support:2.0.6
Pin the exact version, not ^1.0 and not ^2.0. The 2.0.6 release note is a single line — "Only Release." — which tells you nothing about what moved between the 1.x line and 2.x. With no changelog, no dependents, and no upstream activity to lean on, floating a caret range over an unmaintained package means the next composer update is an unreviewed code change.
2. Read composer.json first, not the README
The single most important thing to check is the autoload block. Utility packages like this usually expose one of two shapes:
| Autoload shape | What it means for you |
|---|---|
psr-4 only (Songshenzong\\Support\\ → src/) |
Pure static classes; you call SomeClass::method() |
files: ["src/helpers.php"] |
Global functions are loaded on every request — check for collisions |
| Both | Mixed; expect duplicated capability |
cat vendor/songshenzong/support/composer.json
While you are in there, read the require.php constraint. A major version bump is the most likely place for a 2022-era >=7.4 floor to have been raised or, conversely, left untouched while the code drifted.
3. Reconstruct the 1.x → 2.x diff yourself
This is the new step, and it is the one that matters most for this release. "Only Release." is anti-information: it is what a maintainer writes when they tag from the GitHub UI and nothing else. Semver says a major bump is a breaking change; an empty note says the maintainer did not consider it worth describing. Both can be true at once.
# Compare the two tags directly if the repo is reachable
git clone --quiet https://github.com/songshenzong/support /tmp/support && cd /tmp/support
git diff --stat 1.* 2.0.6
git diff 1.* 2.0.6 -- composer.json
# Or, if the repo is not reachable: install both into scratch dirs and diff
composer require songshenzong/support:1.* --working-dir=/tmp/old
composer require songshenzong/support:2.0.6 --working-dir=/tmp/new
diff -ru /tmp/old/vendor/songshenzong/support/src /tmp/new/vendor/songshenzong/support/src
If the diff is empty apart from composer.json metadata, the 2.x bump is cosmetic and you can stay on the version you already tested. If method signatures, return types, or the autoload block moved, treat it as a full re-adoption and re-run step 5 below.
4. Map the API surface
There is no published API docs worth trusting at this age. Enumerate it yourself:
ls vendor/songshenzong/support/src
grep -rn "public static function" vendor/songshenzong/support/src | head -60
grep -rn "^if (! function_exists" vendor/songshenzong/support/src
The second grep is the one that matters for a files autoload — it tells you whether the package guards its global functions (good) or blindly redeclares them (fatal error risk). Run it again on 2.0.6 even if you ran it on 1.x; a major bump is exactly when a guard gets dropped.
5. First use case
Pick exactly one thing you were about to hand-roll and compare it against illuminate/support. A reasonable first candidate is array/string massaging — deep flatten, case conversion, or JSON-safe casting — where Illuminate\Support\Arr is verbose. Write the framework version and the package version side by side, then keep whichever is clearer to the next reader. If the framework version wins, uninstall.
// Before adopting, prove it's actually shorter.
// Compare your framework call...
$value = \Illuminate\Support\Arr::get($payload, 'a.b.c');
// ...against the package equivalent discovered in src/.
// If the package adds no clarity, do not adopt it.
6. Verify on your target PHP/Laravel before writing code
php -v
composer why-not songshenzong/support 2.0.6
vendor/bin/phpunit --filter Support
A 2.0.6 tag with a one-line note does not prove the code was modernised. Verify the constraint actually admits your runtime rather than assuming the major bump came with PHP 8.2/8.3 or Laravel 10/11 support — it may have been bumped for reasons entirely unrelated to compatibility.
Pattern: thin adapter over the package
Never call Songshenzong\... statics directly from controllers, jobs, or Blade. Wrap the two or three functions you actually use behind your own class so you can swap implementations when (not if) the package is abandoned.
namespace App\Support;
final class Text
{
public static function slug(string $value): string
{
// Delegate now; replace with Str::slug() later without touching call sites.
return \Songshenzong\Support\Str::slug($value);
}
}
This costs ten lines and buys you a one-file migration later. Given zero dependents and a changelog that says nothing, this is still the single highest-value pattern in this document — arguably more so now that 2.x exists and you have no idea what is in it.
Pattern: use it at the edges, not in the domain
Helper packages are strongest in serialization, formatting, and I/O glue — turning a nested array into a flat key list, normalizing a phone number, clamping a numeric range. They are weakest where behaviour needs to be explicit and testable. Keep them out of pricing, permissions, and anything with money or PII.
Pattern: Blade and one-off scripts
If the package exposes global functions, they are convenient in Blade and in artisan tinker / throwaway migration scripts — contexts where you are not going to write a proper service anyway. This is where most of the day-to-day value will actually land.
{{-- Acceptable: presentation-only formatting helper --}}
{{ truncate_text($post->excerpt, 120) }}
Pattern: test the wrapper, not the package
Do not write coverage for third-party internals. Write a small characterization test around your adapter so you notice if a version bump changes behaviour. If you already had these tests for 1.x, re-running them is the cheapest possible validation of the 2.0.6 upgrade.
it('flattens nested keys', function () {
expect(\App\Support\Arr::flattenKeys(['a' => ['b' => 1]]))
->toBe(['a.b' => 1]);
});
Pattern: upgrade through the adapter, not through the call sites
When moving 1.x → 2.0.6, change the constraint in composer.json, run the adapter tests, and stop. If the adapter tests pass, the upgrade is done regardless of what the release notes did or did not say. If they fail, you have localised the breakage to one file instead of every call site.
{
"require": {
"songshenzong/support": "2.0.6"
}
}
Pattern: feature-flag adoption
If you are introducing this into an existing codebase, land the adapter plus one call site first. Resist the temptation to bulk-replace framework helpers — an unmaintained utility package is not a reason to churn working code.
Integration tips
app()->make() — the package is not resolvable from the container. Do not attempt constructor injection of package types unless you register them yourself.extra.laravel.providers, do not add one. Most of these packages are stateless and a provider adds nothing.final class with static methods is honest and sufficient.An empty changelog is a finding, not a gap. "Only Release." means you cannot reason about upgrade risk from the release itself. Compensate with a mechanical diff (Getting Started, step 3) and pin the exact version. Do not substitute optimism for a diff.
^2.0 is a worse idea than ^1.0 was. A caret on an unmaintained package invites a future 2.1 that nobody reviews. If you want the convenience of a range, constrain it: "songshenzong/support": ">=2.0.6 <2.1". Otherwise pin 2.0.6 and bump deliberately.
Name collisions are the top risk. A Songshenzong\Support\Str or Arr class invites use conflicts with Illuminate\Support\Str and Arr in the same file, and a global str_* helper file invites fatal redeclare errors if it is not function_exists-guarded. Grep for the guard before you trust it, and alias on import:
use Illuminate\Support\Str;
use Songshenzong\Support\Str as SupportStr;
Static state is untestable state. Utility classes with static caches or static config are invisible to Laravel's container and hostile to parallel tests. If you find static $cache in the 2.0.6 source, prefer the stateless siblings or skip the package.
Autoload files are cached. After install or update, composer dump-autoload before debugging "function not found". This bites hardest immediately after a major bump, when you have swapped src/ contents and the classmap still points at the old shape. And when you inevitably fork, composer.json autoload changes require a dump too.
Compatibility debt may or may not have been paid. A 2.0.6 tag does not by itself mean the 2022-era code was touched. Expect the possibility of:
return type mismatches if your project runs strict Larastan/PHPStan at level 6+Verify against your actual runtime; do not infer support level from the version number. And if the constraint blocks install, composer require --ignore-platform-req=php is not a fix — it is a scheduled incident.
Debugging approach. With no docs, ReflectionClass is your best friend:
$r = new ReflectionClass(\Songshenzong\Support\Str::class);
foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC) as $m) {
dump($m->getName());
}
Combine with grep -rn "function " vendor/songshenzong/support/src and read the docblocks. Ten minutes of this beats an hour of guessing.
Extension points are likely absent. Do not plan for config publishing, macros, or contract binding — packages of this shape rarely offer them, and a bare major bump is not evidence of a redesign. Your extension point is your adapter class. That is by design.
Fork strategy, decided up front. Treat this as effectively vendored code:
"repositories": [{"type": "vcs", "url": "..."}]) rather than waiting on upstream.When to skip it entirely. If your first-pass comparison in Getting Started showed Illuminate\Support is equally readable, you have no reason to carry an unmaintained dependency for marginal ergonomics. A 2.0.6 tag with a one-line note does not change that calculus — the package is a convenience, not a capability, and conveniences should clear a higher bar when nobody is maintaining or documenting them.
How can I help you explore Laravel packages today?