Hi,
Just a question about how to manage dependencies versions in composer.json for Mezzio (when major version module released).
As a example a created a website ~4 years ago (zend expressive) and used the skeleton and migrate to mezzio later. Until now i updated sometime my composer dependencies via composer update and apply in my hosting with composer install. I see by example that laminas-form still in 2.17.1 (of course i have ^2.11 in composer.json).
So my question is what is the best way to be up to date with the latest versions (major) ? Do i have to change manually the version of each packages in composer.json ?
By example, with laminas-form i have 2.17.1 and it is not compatible with PHP 8.1. Do i have to replace laminas/laminas-form": “^2.11”, by laminas/laminas-form": “^3.1”, ?
Part of my composer.json:
...
"require": {
"php": "^7.1",
"roave/security-advisories": "dev-master",
"laminas/laminas-component-installer": "^2.1",
"laminas/laminas-config-aggregator": "^1.0",
"laminas/laminas-diactoros": "^1.7.1",
"mezzio/mezzio": "^3.0",
"mezzio/mezzio-csrf": "^1.0",
"mezzio/mezzio-fastroute": "^3.0",
"mezzio/mezzio-helpers": "^5.0",
"mezzio/mezzio-session-ext": "^1.0",
"mezzio/mezzio-laminasviewrenderer": "^2.0",
"laminas/laminas-form": "^2.11",
"laminas/laminas-i18n": "^2.7",
"laminas/laminas-mail": "^2.9",
"laminas/laminas-servicemanager": "^3.3",
"laminas/laminas-stdlib": "^3.1",
"laminas/laminas-dependency-plugin": "^1.0"
},
...
Thanks!
I wrote a small scripts that will
- read
composer.json
for required PHP version and all dependencies (dev and non-dev)
- delete
composer.lock
and vendor/
- require all dependencies while specifying required PHP version
That will essentially upgrade everything across all major versions. So it is very breaking, and it will modify your composer.*
without any confirmation. But it should get the job done.
If you are unsure, you can comment out the execution of commands, near RUNNING
, and just see what commands it would run instead.
Here it is:
#! /usr/bin/env php
<?php
class Updater
{
private function toRemove(array $packages): string
{
$packages = $this->filterExcluded($packages);
return $this->toArgs(array_keys($packages));
}
private function toRequire(array $packages): string
{
$packages = $this->filterExcluded($packages);
// Keep @stable version
$packageWithOptionalStable = [];
foreach ($packages as $package => $version) {
if ($version === '@stable') {
$package = $package . ':' . $version;
}
$packageWithOptionalStable[] = $package;
}
return $this->toArgs($packageWithOptionalStable);
}
private function toArgs(array $args): string
{
$escaped = [];
foreach ($args as $arg) {
$escaped[] = escapeshellarg($arg);
}
return implode(' ', $escaped);
}
private function filterExcluded(array $packages): array
{
ksort($packages);
return array_filter($packages, function (string $version, string $package) {
$isPhp = preg_match('~^(php|ext)(-.*)?$~', $package);
$isCrossMajor = strpos($version, '||') !== false;
return !$isPhp && !$isCrossMajor;
}, ARRAY_FILTER_USE_BOTH);
}
public function majorUpdate(): void
{
$data = json_decode(file_get_contents('composer.json'), true);
$deps = $data['require'] ?? [];
$devDeps = $data['require-dev'] ?? [];
preg_match('~\d\.\d~', $data['require']['php'] ?? $data['require']['php-64bit'], $m);
$php = 'php' . $m[0];
$composerPath = trim(`which composer`);
$composer = "$php $composerPath --ansi --no-interaction";
$argsToRemove = $this->toRemove($deps);
$devArgsToRemove = $this->toRemove($devDeps);
$argsToRequire = $this->toRequire($deps);
$devArgsToRequire = $this->toRequire($devDeps);
$cmds = [];
if ($argsToRemove) {
$cmds[] = "$composer remove --no-update $argsToRemove";
}
if ($devArgsToRemove) {
$cmds[] = "$composer remove --no-update --dev $devArgsToRemove";
}
$cmds[] = 'rm -rf composer.lock vendor/';
$cmds[] = "$composer update";
if ($argsToRequire) {
$cmds[] = "$composer require $argsToRequire";
}
if ($devArgsToRequire) {
$cmds[] = "$composer require --dev $devArgsToRequire";
}
echo 'COMMAND LIST:' . PHP_EOL;
foreach ($cmds as $cmd) {
echo $cmd . PHP_EOL;
}
echo PHP_EOL . 'RUNNING:' . PHP_EOL;
foreach ($cmds as $cmd) {
echo $cmd . PHP_EOL;
$return = 0;
passthru($cmd, $return);
if ($return) {
die($return);
}
}
}
}
$updater = new Updater();
$updater->majorUpdate();