When to Use Laravel Collections vs. Plain Arrays
When you write PHP in Laravel, you can store values in a native array or use a Laravel collection. A collection is…
When you maintain a Laravel package, upgrading a dependency changes the libraries your package uses. Neither Composer’s selection of new versions nor a successful test run on your machine shows that the package works with every Laravel and PHP version it claims to support.
Review the package versions Composer selects and its PHP requirements. Then test the package’s public features in a Laravel application and across the versions the package supports. Composer’s dependency resolution is the set of package versions it selects to install. These checks help you decide whether to release the change, adjust the package’s version limits, or investigate a regression.
Before upgrading, record the current test results and the PHP and Laravel versions the package supports. Then update dependencies on a branch and review the changes to composer.json and composer.lock.
Composer’s update command selects versions allowed by composer.json and writes those exact versions to composer.lock. Target one dependency to narrow the change, or update the full dependency set to check for interactions between packages:
composer update vendor/package
To resolve all dependencies allowed by the manifest, run:
composer update
Use composer install when you need to reproduce the versions in the committed lock file; use composer update to select new versions and change that file. Comparing the results with your baseline helps separate pre-existing failures from failures that appeared after the upgrade. See Composer’s basic usage documentation for how these commands handle the lock file.
For a library, the lock file fixes versions for the package’s own development and tests. People who install the library do not get those locked versions. Composer selects their dependency versions based on the version limits the library publishes. Composer therefore recommends testing library dependency resolution with both composer update and composer update --prefer-lowest. These commands check different parts of the allowed version range. The Composer library guidance explains why a passing test run with locked versions alone cannot confirm that the versions consumers install will work.
Run the checks configured for your package after changing dependencies. A typical sequence is:
composer validate
composer check-platform-reqs
composer audit
composer validate checks the manifest and whether the lock file matches it. composer check-platform-reqs checks whether the PHP version and installed extensions meet the requirements of the installed packages. Composer’s command documentation describes both checks. Do not use --ignore-platform-reqs to make an incompatible environment appear to pass. Skipping a requirement does not show that the package works with that PHP version or set of extensions.
composer audit checks installed dependencies against configured security policies. Investigate any finding and decide whether to resolve it or document why it does not block the release. An audit result concerns dependency policy and security findings; it does not establish whether package behavior remains correct.
Also run the package’s own tests. Run its code checks and formatting scripts too. For example, use vendor/bin/phpunit if the package uses PHPUnit. Run its configured static-analysis command, which checks code without running it, and its formatting command. Laravel’s package development documentation describes a package setup that uses Pest, Larastan, Pint, and a workbench application. Individual packages use different tools and scripts.
A unit test checks a small piece of code on its own. A feature or integration test checks how multiple parts work together, such as when a request passes through Laravel services. For a Laravel package, include tests that start a Laravel application when the behavior depends on service providers, which register package services, or on configuration, routes, database access, or other framework services. Laravel’s testing documentation distinguishes tests that run without starting the application from feature tests that check broader behavior.
Orchestral Testbench starts a Laravel application for package tests. This lets maintainers test package code in conditions closer to what consumers encounter. Match the tests to the package’s public features. For example, a package that registers routes should check the HTTP status and response content. A package that provides commands should check what those commands do. Packages that publish configuration or database migrations, files that describe database changes, should check that users can apply the documented settings or database behavior.
Check what the code changes, as well as what it returns. A dependency upgrade can affect how your code calls another object, writes to a database, or changes files. PHPUnit’s test-writing guidance explains how test doubles, substitute objects used in tests, let you control inputs from other code and check calls to those objects. For database tests, choose a reset strategy that proves what you need to test. Laravel’s RefreshDatabase trait helps isolate records between tests, but when the database structure is current, it may use a transaction instead of rerunning migrations. The database testing documentation explains this behavior.
Use dependency and framework upgrade notes to identify focused regression tests. For example, Laravel’s 12.x-to-13.0 upgrade guide describes changes to Eloquent model booting and collection serialization. It also covers HTTP response callback signatures and test teardown behavior. If your package relies on one of those behaviors, test that specific path against the affected framework version. Those changes apply to that upgrade path; they are not general effects of every dependency upgrade.
A package’s compatibility range is the set of PHP, Laravel, and dependency versions allowed by the version limits it publishes. Test the combinations covered by those claims. Passing tests on the latest Laravel version do not show that the package works with an older supported major version. Testing with the newest dependencies also does not show whether the lowest allowed versions work.
A practical continuous integration (CI) setup runs one repeatable job with the locked versions and separate compatibility jobs that select other allowed versions. Composer recommends jobs using composer update and composer update --prefer-lowest for libraries. Run dependency updates in test jobs, not build or release steps. As Composer advises, limit those jobs’ access to secrets and write permissions.
For Laravel package tests, choose a Testbench release that supports the Laravel version you are testing. Testbench’s package documentation and its Core repository have listed different compatibility mappings for the newest Laravel releases. Check the information for the exact Testbench release you install instead of relying on one version table.
Treat the upgrade as a release candidate when the Composer files validate, the PHP versions and extensions meet the installed packages’ requirements, and relevant tests pass with the upgraded dependencies. Review security audit findings, failures, skipped tests, and warnings. Do not hide a failed check by ignoring platform requirements or excluding a compatibility job without understanding the consequences.
Then compare the CI test coverage with the package’s published support claims. If you did not test a supported Laravel or PHP version, record that gap; a successful test run on your machine does not establish compatibility with that version. If the dependency changed behavior that your package exposes, update the regression tests and, when needed, revise the package’s version limits or release notes. Passing tests reduce uncertainty, but they do not prove that the package has no defects.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com