chrysanthos/laravel-nova-future-trend
A Laravel Nova card for visualizing trend metrics, giving you an at-a-glance chart of how key values move over time directly on your dashboard. Simple to install and configure, it helps surface direction and momentum in your app's data without custom charting code.
This release (1.1.2) is a patch-level compatibility fix, not a feature release. It explicitly targets Carbon 3 and Laravel 11, which tells you two things up front:
Minimal steps to adopt it:
composer require <vendor>/<package>:^1.1.2
Then confirm what actually resolved, because the whole point of this release is the transitive constraint graph:
composer show <vendor>/<package>
composer show nesbot/carbon
composer why nesbot/carbon
Look first at:
composer.json — check whether the Carbon constraint is ^2.0|^3.0 or still pinned. A package can "fix Carbon 3" in code while leaving the constraint at ^2.0, in which case the fix is unreachable without a composer update --with-dependencies.config/<package>.php) — timezone and date-format keys are the usual suspects. Re-publish if the stub changed: php artisan vendor:publish --tag=<package>-config --force.First use case to validate in a scratch test or Tinker session: instantiate the package's date-bearing object with an explicit timezone and assert the output type.
$value = app(<Package>::class)->someDateBearingMethod();
dump($value::class); // Carbon or CarbonImmutable?
dump($value->getTimezone()->getName());
If you get a CarbonImmutable where you expected a mutable Carbon, that is a real behavioural difference worth catching before it reaches production.
Pin the floor, not the ceiling. Since the compatibility fix landed in 1.1.2, make that the minimum:
"<vendor>/<package>": "^1.1.2"
Using ^1.1.0 will happily resolve to a broken 1.1.1 on a fresh CI box if the lock file isn't committed.
Matrix-test the versions you actually claim to support. If your app supports both Laravel 10 and 11, run CI against both — the Carbon major usually follows Laravel, but not always, and this release is proof that the combination matters:
matrix:
laravel: [10.*, 11.*]
carbon: [^2.72, ^3.0]
Wrap the package behind a thin service or adapter. Any package that owns date logic is a candidate for isolation. If 1.2.0 later flips a default, you change one class instead of forty call sites:
final class ReportingPeriod
{
public function __construct(private <Package> $package) {}
public function current(): CarbonImmutable
{
return CarbonImmutable::instance(
$this->package->periodStart()
)->setTimezone(config('app.timezone'));
}
}
Normalise at the boundary. Let the package return whatever it returns internally; convert to CarbonImmutable and to your app timezone the moment it enters your domain, and never let a mutable Carbon instance live on a model or DTO.
Laravel 11 wiring. If the package ships a service provider, Laravel 11 auto-discovers it via bootstrap/providers.php — there's no config/app.php providers array to edit any more. Only touch bootstrap/providers.php if you're registering it manually (e.g. the package is excluded from discovery).
// bootstrap/providers.php
return [
App\Providers\AppServiceProvider::class,
<Vendor>\<Package>\<Package>ServiceProvider::class,
];
Fake time in tests, consistently. Laravel's travelTo() / freezeTime() helpers use the framework's Carbon instance. If the package constructs its own Carbon objects directly rather than going through now() / the Date facade, time travel won't reach it — a common source of flaky tests after a Carbon major bump. Prefer Carbon::setTestNow() alongside travelTo() if you see leakage.
Carbon 3 changed diffIn* return types. In Carbon 2, diffInDays() and friends returned int; in Carbon 3 they return float by default. If the package (or your code consuming it) does strict comparisons or type-hints int, you'll get TypeErrors or silent truncation differences. Audit with:
grep -rn "diffIn" app/ tests/
and cast explicitly ((int) $date->diffInDays($other)) rather than relying on coercion.
Carbon 3 also changed Carbon::create() overflow behaviour and tightened up some startOf*/endOf* semantics. If the package has a "period" or "range" concept, spot-check month-end and DST boundaries — 2024-03-31 in Europe/London and 2024-11-03 in America/New_York are the classic offenders.
"Fixed compatibility" ≠ "fixed the constraint." As above: verify composer why nesbot/carbon actually gives you Carbon 3 in the app that matters. Many "Laravel 11 compatible" patch releases were code fixes gated behind a constraint bump in the same tag — but not all.
Laravel 11 removed the HTTP/Console kernels. If the package publishes a service provider that read $this->app['config'] at register() time, that still works — but if it registers middleware or route middleware aliases in $middlewareGroups, those need to move to bootstrap/app.php's ->withMiddleware() closure. If the package's docs still show Kernel.php snippets, the docs are stale, not the code.
Config caching hides stale published config. After upgrading, if behaviour looks unchanged on Carbon 3:
php artisan config:clear
php artisan cache:clear
composer dump-autoload
Debugging date bugs: dump the timezone and the class, not just the value. 2024-01-01 00:00:00 is meaningless without both. $carbon->toIso8601String() plus $carbon::class will save you an afternoon.
Extension points to check before forking. Most date-oriented Laravel packages expose a config-driven date format, a Carbon instance factory, or a Date facade binding. If you need UTC-everywhere behaviour, override the binding in your own AppServiceProvider rather than patching vendor code:
$this->app->bind(<Package>::class, fn () => new <Package>(
timezone: 'UTC',
));
Treat 1.1.2 as a required floor, not a nice-to-have. Because the failure mode on Carbon 3 is often a deprecation notice or a subtly wrong float rather than a hard exception, this is exactly the kind of fix that silently sits un-applied in staging for months. Add a CI check that asserts the installed version:
composer show <vendor>/<package> --format=json | jq -r '.versions[0]'
Watch the 1.1.x line for follow-ups. Compatibility patches frequently ship as 1.1.2, then 1.1.3 a week later for the edge case the first patch missed (usually CarbonImmutable handling or diffIn* casts). Subscribe to the repo's releases rather than relying on composer outdated.
How can I help you explore Laravel packages today?