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

Easy Core Laravel Package

eonx-com/easy-core

EonX Easy Core provides shared foundational utilities and abstractions for Laravel packages, helping developers build consistent, reusable components with less boilerplate. It underpins the Easy package family and simplifies common setup tasks.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm what you're installing before you commit. eonx-com/easy-core is a [READ-ONLY] split of the eonx-com/easy-monorepo — issues and PRs belong upstream, not here. With 3 stars and 0 dependents it is an internal EonX utility belt that happens to be public, not a community framework. The README is a summary, not the documentation; the source is the documentation. Budget an afternoon to read all of src/ before you design anything around it.

Install and pin a concrete version.

composer require eonx-com/easy-core

Then open vendor/eonx-com/easy-core/composer.json and check the php and illuminate/* constraints against your runtime. These packages were written for Lumen 8/9-era scaffolding. In a scratch Lumen skeleton, run composer update --dry-run and read the resolution output before touching a real service — conflicts here surface late and are expensive.

Where to look first, in this order:

  1. composer.json — PHP + framework version matrix, transitive pins (logging, HTTP client, validation).
  2. src/ServiceProvider/ (or equivalent) — what actually gets bound into the container, and whether it is deferred.
  3. Any config/ directory shipped with the package — these files define the conventions everything else assumes.
  4. The traits and base exception classes — this is where the "opinions" live.
  5. The upstream monorepo's tagged releases, to establish whether semver is practised.

Register the provider(s) in bootstrap/app.php. Lumen does not have Laravel's package auto-discovery, so despite the description, assume you must register manually:

// bootstrap/app.php
$app->register(EonX\EasyCore\Bridge\Lumen\Providers\EasyCoreServiceProvider::class);

Load config the Lumen way, not the Laravel way:

$app->configure('easy-core');   // looks for config/easy-core.php

Copy the package's default config into your app's config/ and commit it. Do not rely on the package's defaults staying stable across tags.

First use case to prove it out: a single non-critical internal JSON microservice. Wire the provider in, add one thin endpoint, and exercise the shared exception handling end-to-end — hit a 404, a 422 from validation, and a 500 with APP_DEBUG=false. If the response envelopes match what your other services already return, you've found the actual value: consistent error shaping across a Lumen fleet. If they don't, you've found the integration cost early and cheaply.

Implementation Patterns

Adopt the family, not the orphan. The value of easy-core is largely as the substrate beneath the sibling packages (easy-webhooks, easy-activity-log, easy-error-handler, easy-pagination). Pulling in easy-core alone to get one trait is over-coupling; pulling it in as the base layer for two or three siblings is the intended shape. Plan the whole set up front so you resolve their dependency graphs once.

Layering pattern for a Lumen service.

// bootstrap/app.php — order matters
$app = new Laravel\Lumen\Application(realpath(__DIR__ . '/../'));

$app->withFacades();
$app->withEloquent();

$app->configure('easy-core');
$app->configure('easy-error-handler');

$app->register(App\Providers\AppServiceProvider::class);
$app->register(EonX\EasyCore\Bridge\Lumen\Providers\EasyCoreServiceProvider::class); // after your own

$app->router->group([...], __DIR__ . '/../routes/web.php');

Register EonX providers after your own application providers so their bindings can override your fallbacks, and keep framework-level wiring (withFacades, config loading) above both.

Exception handling: wrap, don't replace. The most likely blast radius is the response envelope produced by the shared exception handler. Keep your own App\Exceptions\Handler extending Laravel\Lumen\Exceptions\Handler, delegate to the package's renderer for the standard cases, and keep an explicit match arm for anything domain-specific:

public function render($request, Throwable $e)
{
    // let domain exceptions shape their own payload
    if ($e instanceof DomainException) {
        return response()->json(['error' => $e->getMessage()], 422);
    }

    return parent::render($request, $e);
}

This gives you a seam to swap the package out later without touching endpoint code.

Use the traits as mixins on your base classes, not deep in leaf classes. If the package ships logging or config traits, apply them to your Controller / Command base classes once. Leaf classes stay package-agnostic, which means a future fork-and-own or removal is a one-file change.

Config conventions over config sprawl. Read every package config key through config('easy-core.*') — never reference package constants or class properties directly from your app code. When you fork the package, environment-variable names are the contract you most want to preserve.

Contract tests are non-negotiable. Because behaviour can shift on upgrade with no changelog and no crowd to catch regressions, add a small HTTP-level test suite that asserts response shape for your canonical cases:

public function test_not_found_envelope_is_stable(): void
{
    $this->getJson('/api/does-not-exist')
        ->assertNotFound()
        ->assertJsonStructure(['message', 'code']);  // whatever the package emits
}

Run this suite on every dependency bump. It is the only regression net you get.

Pin and mirror. Commit composer.lock. Additionally, mirror the package source into your own registry (Satis, Private Packagist) at the exact commit you tested. If EonX stops publishing, your build still resolves and you have the source to fork from — this is a five-minute setup that hedges the single biggest risk.

Fork-and-own drill, exercised once. Before you're forced into it, do a dry run: clone into your own namespace, change the name in composer.json, alias the namespace via a PSR-4 override, and confirm the app boots. If that takes you half a day, you're fine. If it takes a week, you've learned something critical about coupling you didn't intend.

Migration pattern for an existing Laravel app: extract, don't install. If you want the features (a config helper, a response trait) rather than the package, copy those specific classes into app/Support/ and own them. Dropping a Lumen core package into a full Laravel app produces a hybrid where neither framework's bootstrapping assumptions hold — Lumen's bootstrap/app.php has no analogue in Laravel's bootstrap/app.php + Kernel split, and providers written for the former can misbehave under the latter.

Gotchas and Tips

"Auto-discovery" is a Laravel concept — verify it. The description advertises package auto-discovery, but Lumen does not perform provider discovery from composer.json. Expect manual $app->register() in bootstrap/app.php. If you port the package to a Laravel app, the opposite trap applies: Laravel will auto-discover and register the provider whether or not you intended it — use composer.json's extra.laravel.dont-discover to suppress.

The read-only repo is a support boundary, not a formality. Issues and PRs filed here go nowhere. If a bug blocks you, your options are patch-via-Composer (cweagans/composer-patches), a local fork, or a direct relationship with an EonX maintainer. Assume self-support; if you have no such relationship, budget accordingly.

Lumen is in maintenance mode upstream. The package cannot outlive the framework. Scope adoption to existing Lumen services with a defined retirement horizon; never adopt it as a reason to build a new Lumen service. For greenfield, start on Laravel.

Silent behaviour drift is the top failure mode. A patch bump can change exception rendering, pagination metadata, or middleware ordering without a changelog entry. Never bump this package without re-running the contract test suite, and treat any response-shape diff as a breaking change requiring review — even on a patch version.

Dependency deadlock risk is real. A core package typically pins framework-adjacent libraries (monolog, guzzlehttp, symfony/*). When one of those pins a version behind your security-update floor, you are stuck between an insecure transitive dep and forking. Check the full resolution graph in a scratch project before adopting, and recheck on every Lumen security release.

Config publishing gotcha. Lumen's $app->configure('name') looks for config/name.php relative to the app base path. If the package's config file has a different filename than the key you configure, you'll silently get null from every config() call and the provider will fall back to hardcoded defaults. Verify by dumping the config in a tinker-style route before writing any code against it.

Don't assume deferred providers. If a provider registers a booted-time listener or a singleton with side effects, calling it lazily (resolve() rather than make()) can surface surprising ordering. Read the provider's boot() for anything that touches the request lifecycle.

Debugging with no community corpus. There is no Stack Overflow history, no blog posts, no issue tracker to search. Your debugging loop is dd() inside vendor/eonx-com/easy-core/src/, plus git log on the mirrored source. Instrument the provider's boot with a temporary log line to confirm it runs and in what order relative to your own providers — this saves hours when a binding silently overrides yours.

Document your own tribal knowledge. Every surprising behaviour one of your engineers encounters is a first encounter for the whole team. Keep a short internal docs/easy-core-notes.md recording each quirk, the version it appeared in, and the workaround. That file — not the README — becomes the real onboarding artifact, and it's what makes an eventual fork-and-own tractable.

Extension points worth knowing. Traits and base classes are the intended seams; container bindings are the escape hatch. Prefer overriding via your own provider's register() (binding an interface to your implementation after the package provider runs) over editing vendor files — it keeps you patch-free and makes removal a matter of deleting one provider line.

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.
friendlylabs/surveyr
mg-techlegend/laravel-notify-africa
islamabdurahman/laravel-sms-service
dmhendricks/b2-sdk-php
aplicativa/laravel-admin
ezavalishin/vkma
jackardios/laravel-json-api-paginate
viral/laravel-adminpanel
dieppk/log-viewer
daimakuai-ext/helpers
codexshaper/php-blade-view
abraxas81/charts
adamlien/laravel-cas
quimgc/tasks
sistem-atc/bank-sdk
core45/laravel-cookieconsent
projectsend/community-modules
ovac/laravel-hubtel-payment
capimail/capimail-php
shiroamada/green-api-laravel-notification