Registering Database Migrations in Laravel Packages
When a Laravel package needs its own database tables, its maintainers must decide how the host application will find the package’s migration…
When you manage a Laravel project with Composer, the version constraint in composer.json tells Composer which package releases it may choose when it selects versions that meet all package requirements. An exact constraint such as "2.4.1" permits only that release. A range such as "^2.4" permits compatible releases within a defined interval.
For a Laravel application, use a range for most packages and commit composer.lock. The lock file records the exact versions Composer selected, so deployments install the same set of dependencies and you can choose when to update packages. Pin a version exactly when you have a specific compatibility reason; widen a constraint when your code supports more releases than the current range allows.
Composer reads the constraints in composer.json when it chooses package versions that meet the requirements, such as during composer update. The Composer constraint syntax supports exact versions. It also lets you set ranges with upper or lower limits using operators such as the caret (^) and tilde (~).
For example, this constraint accepts only version 2.4.1:
{
"require": {
"acme/laravel-widget": "2.4.1"
}
}
If another required package needs a different version of acme/laravel-widget, Composer cannot satisfy both constraints and stops with a dependency-resolution error.
A range allows Composer more choices:
{
"require": {
"acme/laravel-widget": "^2.4"
}
}
Under Composer’s caret rules, ^2.4 allows versions from 2.4.0 up to, but not including, 3.0.0. The caret expresses an expectation that releases within that major version remain compatible. The tilde operator also sets an upper bound, but the bound depends on how many version components you specify. For instance, ~2.4.1 allows updates below 2.5.0.
The constraint and the lock file do different jobs. A constraint defines which versions Composer may select; the lock file records the versions it selected for the project. For a Laravel application, commit composer.lock and use composer install for deployments to keep the installed dependency set consistent. When you run composer update, Composer chooses package versions again within the declared constraints and updates the lock file.
Pin a package to one release when you have verified that release and need to prevent Composer from selecting another one during future updates. A temporary pin helps when a newer release breaks an integration your code needs, or when a release introduces a bug that affects your code.
Before pinning, check whether the lock file already provides the control you need. If you only want production deployments to keep using the currently tested release, commit the lock file and deploy with composer install. An exact constraint in composer.json adds a stronger limit: future updates cannot select any other release, even after you are ready to upgrade.
If another Laravel package requires a different version, Composer cannot resolve the dependency set until you change the pin or adjust the conflicting requirement. Exact constraints also make routine package upgrades a manual composer.json edit.
For a short-term workaround, document why the pin exists and what must happen before you remove it. Then test the proposed replacement and widen or update the constraint when the incompatibility is resolved.
Use a bounded range when your code supports several releases and you want Composer to find a compatible one. For most application dependencies, a caret range provides room for fixes and compatible updates while excluding the next major version:
{
"require": {
"acme/laravel-widget": "^2.4"
}
}
Avoid unbounded constraints such as ">=2.4". That expression has no upper limit, so Composer can select a future major release that changes behavior. Composer’s documentation recommends bounded constraints, and its version-constraint guidance describes how to express those limits.
Widen a constraint when tests show that your code works with more package releases than the current requirement allows. For example, if a Laravel package supports two major versions of the framework components, its requirements might say:
{
"require": {
"illuminate/support": "^10.0 || ^11.0"
}
}
That declaration tells Composer the package accepts either range. A package maintainer should set ranges based on the versions the package supports and test those versions. If the maintainer declares a broader range without checking compatibility, users can install a combination of versions the package has not been shown to handle.
A development release comes from a branch rather than a tagged stable release. Composer defaults to stable packages, so a project that needs a development release can add a stability flag to that package’s constraint:
{
"require": {
"acme/laravel-widget": "^2.4@dev"
}
}
The @dev flag permits development-stability versions for that requirement while leaving the project-wide stability setting unchanged. Composer documents stability levels and flags alongside its version constraints. Use a branch-specific constraint when you need a particular development line, and keep the lock file current so it records the resolved reference. A bare @dev requirement is broad and can make the selected branch unclear.
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