Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Helper Laravel Package

madong/helper

A lightweight Laravel/PHP helper package that bundles convenient utility functions for common development tasks. Designed to reduce boilerplate and simplify everyday coding, it offers an easy-to-integrate set of helpers for faster, cleaner application development.

View on GitHub
Deep Wiki
Context7

Getting Started

madong/helper is not a Laravel package — it is the shared utility layer for the madong admin ecosystem running on Webman (Workerman). Treat it as the equivalent of laravel/framework's Illuminate\Support helpers plus your own app/helpers.php, extracted so that single-tenant and multi-tenant madong backends can share one implementation. That framing tells you most of what you need before you open the source.

Minimal steps

  1. Check your PHP version and the package's require.php constraint first. v1.1.2 is the release that added PHP 8.4+ syntax support (#1 对PHP8.4+语法支持) — meaning anything older than 1.1.2 is a liability on PHP 8.4. On a modern Webman image you are probably on 8.3/8.4 already, so treat 1.1.2 as the minimum rather than an optional bump.
  2. composer require madong/helper in the Webman project (it will almost certainly be pulled in transitively by madong/admin — check composer.lock first, you may already have it, and check which version you got).
  3. Open vendor/madong/helper/composer.json and read the autoload block. Helper libraries of this shape load global functions via "autoload": { "files": [...] }; that list is your actual API index. Read those files top to bottom — with a 0-star package there is no documentation, the source is the docs.
  4. Then read src/ for the class-based pieces: expect a tenant/context object, a response/result wrapper, tree/array utilities, and config accessors.
  5. Confirm whether the package registers anything with Webman's plugin system (config/plugin/madong/helper/*.php or an install.php/Webman\Bootstrap implementation). If it does, that config file is where tenant resolution mode is switched between single- and multi-tenant.

Where to look first, in order

  • composer.json → require.php, autoload.files and autoload.psr-4 (the floor version, the function list, and the namespace root).
  • The tenant/context class (search the source for tenant). This is the single most consequential piece of the library, because it determines whether your code is reusable across both deployment modes.
  • Any helpers.php-style file for global functions, and cross-check each name against Laravel/Symfony/Webman globals for collisions (see Gotchas).

First use case

The first thing you should actually do with this package is not call a string/array helper — it's to wire the tenant context correctly in a multi-tenant boot. Write a two-line probe:

// in a controller or a `php webman` tinker-style script
var_dump(function_exists('tenant_id') ? tenant_id() : null);

(or whatever the context accessor turns out to be called after step 3). Get a real tenant ID out of it for a request in both a single-tenant and a multi-tenant deployment before building anything on top. Everything else in the library is convenience; tenancy is correctness.

Implementation Patterns

Call helpers, don't re-wrap them. The whole value proposition is that madong/admin, madong/helper, and any plugin you write all resolve tenancy and formatting identically. If you write function my_tenant_id() you've just forked the ecosystem's source of truth and your plugin will drift on the next release. Use the package's accessor everywhere, including in your own plugin's models/repositories.

Tenant-scoped queries at the repository edge, not in controllers. The typical madong pattern is: controller → service → repository, with the repository applying the tenant predicate. Keep the helper's tenant accessor inside the repository so that a single-tenant deployment (where the accessor returns null/0 and the predicate is skipped) needs zero code changes. Any where('tenant_id', ...) you hand-write in a controller is a bug waiting for the multi-tenant switch.

Single-tenant/multi-tenant parity as a design constraint. Design so the mode is configuration, not code branching. Prefer:

$query = $this->applyTenantScope($model->newQuery()); // helper-driven, no-op in single-tenant

over

if (config('tenant.enabled')) { ... } else { ... }

The second form doubles your test matrix and is where most madong-ecosystem bugs live. If the helper exposes a "current tenant" object, code against the object's interface rather than checking a boolean flag.

Response shaping. madong backends conventionally expose a normalized JSON envelope (code/msg/data) so the admin frontend can interpret every endpoint uniformly. If the package ships a result/response helper, use it as the only return path from controllers — mixed envelopes is the fastest way to break the SPA's error handling. Wrap it once in your own base controller method if the raw API is verbose.

Array/tree utilities for menu and permission data. Admin ecosystems are full of parent-child arrays (menus, departments, categories). Use the package's tree builder rather than array_filter recursion in each plugin; it keeps ordering and children key conventions consistent with the admin UI's expectations.

Mapping to Laravel muscle memory. Useful translations when you're new to Webman:

  • app()/container → support\Container or the package's own accessor; there are no facades.
  • config('x.y') → config('x.y') still exists in Webman, but the package may have its own config accessor with defaults — prefer whichever the package itself uses internally so plugin config resolution matches.
  • Middleware → Webman middleware classes; the tenancy context is usually established here, so register the tenancy middleware globally and first in config/middleware.php. If it runs after auth, your auth queries are unscoped.
  • Eloquent vs. illuminate/database — madong is generally Laravel-DB-based, so models/query builder feel familiar but global scopes and booted() hooks may behave differently than you expect.

Version pinning and the upgrade cadence. Pin explicitly — "madong/helper": "^1.1.2", not *, and not ~1.0 (which can resolve below the 8.4-safe release on a fresh composer update). The library is 0-star with a very recent release date; you are effectively the QA team. For a syntax-only bump like 1.1.2 the risk is minimal (no new API surface), but that is also exactly why you should diff vendor/madong/helper before and after rather than trusting a one-line changelog.

Gotchas and Tips

Global function collisions are the #1 failure mode. Helper libraries that autoload files define functions in the global namespace. Watch for: str_*/arr_* names that overlap illuminate/support, env() and config() if you run madong code alongside Laravel components, and short names like tree(), format(), result(). Composer loads autoload.files before your app's own helper file in most setups, so a colliding name in your app/functions.php is a fatal Cannot redeclare. Grep before you add:

grep -rho "function [a-zA-Z0-9_]*(" vendor/madong/helper --include=*.php | sort -u > /tmp/helper_fns.txt

Diff that against your app's functions once, at install time.

PHP 8.4 is a hard floor on 1.1.2, and a question mark below it. The v1.1.2 changelog is a single line — "PHP 8.4+ syntax support" — which is a strong signal that pre-1.1.2 code either emitted E_DEPRECATED notices under 8.4 (the classic culprit being implicitly nullable parameters, function f(Foo $x = null)) or straight-up used syntax that only parses on newer interpreters. Two things to do:

  • Diff composer.json's require.php between your resolved version and 1.1.2. If the constraint did not change, the author fixed syntax without advertising a floor — you may still be fine on 8.1+, but don't assume 1.1.2 dropped older PHP.
  • Run your CI on the same PHP minor as production. "Supports 8.4 syntax" does not mean "behaves identically on 8.4"; E_DEPRECATED-to-ErrorException conversions in Webman's error handler can turn a harmless deprecation into a 500 on a request path you never exercise locally.

Static tenant state leaks across requests — this is the big one. Webman is a resident process, not PHP-FPM. A static $tenantId in the helper (a very common implementation) survives between requests handled by the same worker. In single-tenant mode nobody notices; in multi-tenant mode, request B can inherit request A's tenant under load. Verify that the tenancy context is reset per request — typically via a middleware before/after, or a request-scoped object. Write a test that hits the same worker twice with different hosts/headers and asserts the tenant ID changes:

// pseudo: two sequential requests via the same Webman worker
$first  = requestAs('tenant-a.test');
$second = requestAs('tenant-b.test');
assert($second->tenantId !== $first->tenantId); // if this fails, you have a leak

This same class of bug applies to any cached config, locale, or auth identity held statically. It is the single most valuable hour you will spend on this package.

No facades, no auto-discovery. Don't assume Laravel's package auto-discovery applies; Webman plugins register via config/plugin/... and Webman\Bootstrap classes. If something "doesn't work," you usually forgot to enable the plugin config or the bootstrap class — check config/plugin/madong/helper/app.php exists and is enabled.

Debugging the tenant resolution. Add a temporary log line in the tenancy bootstrap printing the resolved tenant, the source (subdomain/header/domain), and the worker PID. When a tenant appears wrong in staging, that log tells you instantly whether it's resolution or leakage. Include PHP_VERSION in that same line while you are validating a PHP bump — it makes "works on my machine" conversations with the 8.4 upgrade short.

Extension points to prefer over forking. If the package allows injecting a tenant resolver (interface + config binding) or overriding the config defaults, use that. Forking a 0-star helper library means you own its maintenance forever, and madong's own packages will still call the original namespace. If you must patch, use a composer patches entry (cweagans/composer-patches) so the change is visible and re-appliable — and note that a syntax-only release like 1.1.2 is the cheapest kind of upstream fix you can get, so prefer bumping over patching here.

Config quirks. Ecosystem helpers often read config with hardcoded defaults that hide the real value (e.g. config('plugin.madong.helper.tenant.enabled', false)), which makes a missing config file look like "feature off" instead of "misconfigured." Dump the effective config at boot once, and prefer the fully-qualified plugin. prefix — it's a common source of silently-ignored settings in Webman.

Testing and upgrade risk. Treat the library as third-party but load-bearing: add a smoke test suite that exercises tenancy resolution, response envelope shape, and tree building against a pinned version. When you bump it, those three tests catch essentially all the breakage, given how small the surface area is. Widen your CI matrix to the PHP minors you actually deploy when you move to ^1.1.2; the release is explicitly a runtime-compatibility change, so a single-version test run tells you nothing new. And because the license is Apache-2.0, you have the option to vendor/fork with explicit attribution if the project stalls — a reasonable contingency plan for a 0-star dependency in production.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums