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

Deprecation Contracts Laravel Package

symfony/deprecation-contracts

This package provides a single global function, trigger_deprecation(), that triggers silenced deprecation notices so a custom PHP error handler can catch and log them in dev and prod environments. It takes the package name, version, and a printf-style message.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Deprecation-as-roadmap-instrument. trigger_deprecation() turns "we want to remove X" from an opinion into a measurable signal. Every call emits Since <package> <version>: <message>, which means a PM can ship a notice first, watch the log for weeks, and only greenlight the actual removal once usage data says it's safe. This is the difference between a breaking-change decision backed by telemetry and one backed by a guess.
  • Sequenced breaking changes instead of big-bang releases. Because the version argument is the release that introduced the deprecation, the roadmap acquires a durable audit trail: which release warned, about what, and what the replacement is. That supports committing to public "removal in v3.0" statements across major versions rather than vague "will be removed in a future release."
  • Build vs buy resolves instantly toward buy. The entire package is a ~10-line global function under MIT with no runtime dependencies, already present transitively in nearly every Laravel app via symfony/console, symfony/http-foundation, and friends. There is no plausible internal build that beats zero maintenance cost. The build decision is therefore not about the contract — it is about the surrounding pipeline (log channel, CI gate, dashboards), which is genuinely our work and genuinely worth scoping.
  • Prioritization input for platform/API-surface work. Aggregating deprecation log volume by call site gives a ranked list of what the team is actually still calling: an evidence-based backlog for upgrade work, SDK cleanup, and documentation rewrites. First-occurrence alerts mean "someone is still on the old path"; last-occurrence alerts mean "the deletion ticket is now safe to pick up."
  • Use cases that pay off disproportionately: internal Composer packages consumed by multiple services (the classic multi-team upgrade coordination problem), deprecating config keys and route names in a product that other teams configure, sunsetting Blade directives or facade aliases, and any "we promised we'd remove this next major" commitment made to customers.
  • Package-development differentiation. If we ship a package to external users, adopting the Symfony convention means our notices are greppable and consistent with the wider PHP ecosystem. That is a small but real support-cost reduction — fewer "what is this warning" tickets.
  • Explicit non-goal to record: this package provides warnings, not enforcement, not versioning, not a migration tool. It should never be sold internally as an upgrade-automation story.

When to Consider This Package

Adopt when most of the following hold:

  • You maintain code that other people consume — internal packages, a shared library, or a product with documented config/API surfaces — and you need a low-cost way to announce intent to change.
  • You already have, or are willing to fund, the observability path: LOG_DEPRECATIONS_CHANNEL configured (it defaults to null), a log sink you actually read, and ideally failOnDeprecation in CI. The package is inert without this; the pipeline is the project.
  • You want ecosystem-standard formatting so notices are machine-parseable (Since vendor/pkg 2.4.0:) and can be filtered, counted, and alerted on.
  • You're planning a multi-release deprecation cycle and need evidence before committing to a removal date.
  • You are willing to enforce version-string discipline — real tagged releases only. 'next', 'TBD', or 'upcoming' destroy the semantic value of the prefix and should be treated as a review-blocking defect.

Look elsewhere or don't bother when:

  • It's a single-app codebase with no external consumers and no upgrade commitments. A Log::warning() or an inline // TODO: remove in v5 comment carries the same information with no new dependency.
  • The team won't operate the pipeline. Adopting this without a deprecation log channel produces confident silence — the worst outcome, because it feels like coverage. Silent failure on two layers (@trigger_error suppression plus a null log channel) is the package's defining gotcha.
  • You need hard enforcement. If the requirement is "this code must not be called," use static analysis (PHPStan/Psalm deprecation rules), @deprecated docblocks with IDE strikethrough, or CI rules — not a runtime notice that production may never surface.
  • You need usage attribution to a tenant, user, or request. Queue workers and long-lived Octane workers log against the worker process, not the originating request. If attribution matters, this package alone won't give it to you.
  • You want to suppress notices globally. The README's "declare an empty trigger_deprecation()" trick reliably causes a fatal redeclare in apps where Composer already loaded the dependency's files autoload. Set the channel to null instead — and never let anyone add a global stub to a test bootstrap or shared utility package, because it silently no-ops notices project-wide with no compiler protection.

How to Pitch It (Stakeholders)

To executives — 30 seconds: "This is a nearly free mechanism for retiring old code safely. Instead of deciding to remove something and hoping nobody depended on it, we ship a version that logs a warning, watch the data for a few weeks, and then remove it with evidence. The package itself is a ten-line open-source function we already have; the investment is a small amount of logging setup so the warnings are actually visible. Total cost is days, not a quarter, and it converts recurring 'is anyone still using this?' meetings into one dashboard."

To engineering — the honest framing:

  • The dependency is a five-minute install: composer show symfony/deprecation-contracts first — you almost certainly already have it. Add it explicitly only if your own code will call it, so a transitive change can't remove a function you depend on.
  • The real work is the pipeline, and it must be treated as the deliverable, not an afterthought: a deprecations log channel, LOG_DEPRECATIONS_CHANNEL set (default is null, which drops everything silently), deprecation tracing off in production, and failOnDeprecation in CI so new noise can't merge.
  • Establish three small conventions up front, and enforce them in review: (1) centralize the package name and version in a single helper like App\Support\Deprecations::since() so a version bump is one edit; (2) call it on the first line of the legacy path, so it fires even if the method subsequently throws; (3) guard hot paths and per-row accessors with once() — the cost is log volume, not CPU.
  • Two known footguns to pre-empt: no global function stub anywhere in the codebase or vendor tree (redeclare fatal / silent suppression), and deprecation messages are formatted strings — an argument-count or placeholder mismatch throws ArgumentCountError or ValueError and crashes the request, so test that the notice fires.
  • Expect vendor noise once enabled (Symfony's own deprecations appear); plan to filter it in local logs and tag our own calls so the two streams separate.

What success looks like, stated as a metric: for each deprecated surface, a first-occurrence alert (still in use → keep it) and a last-occurrence alert (no longer in use → delete it, on schedule, with a documented rationale). That is the deliverable. The package is just the messenger.

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.
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode