shivella/ideal-bundle
Shivella iDEAL Bundle adds iDEAL payments to Symfony applications, with payment initiation, provider configuration, and status handling for PHP checkout flows. A lightweight way to support Dutch bank payments.
The package has been deprecated since 1.0.6, published 2018-09-18. That date is the most important fact in this assessment. This is not a fresh deprecation notice you caught early — it is a package that has been marked dead for roughly seven years and, on the evidence of the release history, has had no release since. Treat it as abandoned until Packagist proves otherwise.
Minimal steps before you write any code:
composer show <vendor>/<package> and read the abandoned flag. Composer surfaces this directly. Given a 2018 deprecation with no subsequent tag, expect it to be set — and expect the suggested replacement, if any, to be named there. That flag is more authoritative than the changelog line.composer.json for the illuminate/* constraints (these will tell you which Laravel era the package was written for and how far behind it is), the service provider's register()/boot(), the README banner for a replacement pointer, and a diff of 1.0.6 against 1.0.5.The realistic first task is a containment spike, not a feature: pick your single most-used integration point, wrap it behind an interface, and ship that. It gives you the template, the migration estimate, and a concrete ticket to point at.
Day-to-day patterns for a package in this state are containment patterns. You are no longer optimising for leverage; you are optimising for cheap removal and bounded blast radius.
Adapter / anti-corruption layer. Never call the package from controllers, jobs, models, or Blade templates. Define an interface in your domain (Contracts\X) and a concrete implementation that delegates to the package. One file changes when you migrate; every call site stays put. This is the highest-value hour you will spend on this package, and it is more urgent here than for a freshly deprecated one because you cannot rely on upstream ever fixing a bug your adapter would have to work around.
Pin the constraint, and pin it hard. Use "vendor/package": "1.0.*". Do not use ^1.0 and do not float it — the caret is meaningless on a package with no releases since 2018, but the habit matters for the transitive graph. Note that a seven-year dormancy also means "a final security patch" is not a realistic hope; the pin is now about reproducibility, not about absorbing a future patch.
Freeze the surface area. Declare a code freeze on new call sites. Any new requirement goes through the adapter, which reframes the work as "the adapter needs method X" — a question you answer once during migration rather than per-feature. This is what stops the dependency quietly growing while the migration ticket sits in the backlog.
Strangler migration, sequenced around your Laravel upgrade. Stand up the replacement behind the same interface, gate it with a config flag, and cut over per environment. If a Laravel major upgrade is anywhere on your roadmap, the replacement goes first — a package last touched in 2018 will pin you to an old illuminate/support constraint and block composer update at the worst possible moment. Doing both under upgrade pressure is how these migrations get done badly.
PHP runtime compatibility is now a live concern, not a theoretical one. Code written in 2018 predates PHP 8.0/8.1. Expect dynamic-property deprecations, implicit nullable-parameter deprecations, and possibly harder breaks around string/array function signatures. If you are already on PHP 8.2+, the package may be emitting noise or failing on edge paths. Budget for this in the containment spike — you may need a local patch or a compatibility shim before the migration completes.
Fork or vendor if you are staying. For a small surface, copying the source into app/Support/ with the licence header intact is often cheaper than carrying a dead dependency through several PHP and Laravel majors — and unlike a freshly deprecated package, you are not racing upstream improvements, so a fork costs you nothing in lost updates. Check the licence first: permissive means this is legitimate, restrictive means it is not.
Container binding over facade. Bind the adapter in a service provider and inject it. This keeps Facade::shouldReceive out of your test suite and makes the implementation swappable without touching tests.
composer install stops on an abandoned package. Add a CI step that greps composer show output, or a small denylist script that fails the build on known-dead packages. Without enforcement, this deprecation has already survived seven years of ticket closures and will survive another.composer.json change — possibly the abandoned key itself, possibly just the description. Diff it against 1.0.5 before assuming behaviour changed. If it is metadata-only, you can update the lock file with confidence and you have learned nothing new about the code. Note this also means there is no test signal here: a docs-only release tells you the maintainer's intent, not that anything was audited or fixed.composer why <vendor>/<package>. If something else pulled it in, the maintainer of that package owns the fix — open the conversation upstream rather than forking something you did not choose. Your own migration ticket cannot close until they move.E_DEPRECATED notices are a separate problem. Notices surfacing from the package's internals on PHP 8.x are a bug you can patch locally; the package's own deprecation status is an end-of-life decision. Given the 2018 vintage you will likely see both in the same log file. Read the message, not the word.register() for $this->app->bind/singleton calls — if you can re-bind one class, you may be able to replace the internals without touching any call site, which turns a multi-sprint migration into an afternoon.How can I help you explore Laravel packages today?