A problem caused by wrong use of composer and its solution

  • 2021-11-29 06:32:49
  • OfStack

Preface

This thinking comes from an accident. Let me rethink the version dependence for 1 time. Share it for reference and study by friends in need. Let's not say much below. Let's take a look at the detailed introduction

Accident phenomenon

1 online management background, 1 management background built with laravel, which ran well online before. Today, after comopser install, an error message appeared:

[2019-02-25 16:00:33] production.ERROR: Parse error: syntax error, unexpected '?', expecting variable (T_VARIABLE) {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Parse error: syntax error, unexpected '?', expecting variable (T_VARIABLE) at /xxxx/application/estimate-admin/vendor/symfony/translation/Translator.php:89)

Accident analysis

This is a low-level library, basically, 1 see is the version compatibility problem, go in code 1 see, there is a line of code is it? string, a new feature introduced in php 7.1.

Look at my composer.json, which mainly refers to the framework of laravel. The previous version of laravel/framework was "~ 5.5"

So I took it for granted that it was due to the upgrade of laravel, so I fixed the version of laravel to 1 sub-version


"laravel/framework": "5.5.21",

It is found that this error will still occur. It is estimated that it may not be caused by the upgrade of laravel version. The version of laravel then depended on the package "symfony/translation" in question.

The chain is as follows:

My project "laravel/framework": "5.5. 21",
laravel/framework "symfony/http-kernel": "~3.3",
symfony/http-kernel (version 3.3. 13) "symfony/translation": "~ 2.8 ~ 3.0",
symfony/http-kernel (version 3.4) "symfony/translation": "~ 2.8 ~ 3.0 ~ 4.0",

symfony/translation3.4 Version:


public function __construct($locale, $formatter = null, $cacheDir = null, $debug = false)

In 4.0, the feature of 7.1 was added


 public function __construct(?string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false)

The version on my machine is PHP 7.0. Therefore, symfony/http-kernel was upgraded when composer was upgraded, which brought symfony/translation to 4. x and introduced new features of PHP7.1.

Solution

It is impossible to upgrade the PHP version of online machines. So I can only force the version number to be qualified.

Directly at the top level in my project require symfony/translation, and specify the version number.


"symfony/translation" : "3.3.13"

Just re-composer update.

Thinking

This is a typical case of business application error caused by dependency package upgrade. symfony/translation is upgraded from 3.3. 13 to 4.*, and the required version of PHP is upgraded from 7.0 to 7.1. For this upgrade, laravel/framework version v 5.5. 21 is non-aware.

And we look at laravel/framework v5.5. 21 (comopser.json) [https://github.com/laravel/framework/blob/v5.5. 21/composer.json]


{
 "name": "laravel/framework",
 "description": "The Laravel Framework.",
 ...
 "require": {
 "php": ">=7.0",
 "ext-mbstring": "*",
 "ext-openssl": "*",
 ...
 "symfony/http-kernel": "~3.3",
 },
 ...
}

PHP here > = 7.0 is particularly conspicuous, which is simply unreliable.

The real solution

Ha, it's not over here. This problem package version depends on the fact that there is no problem with each package.

Actually, there is a problem here. The PHP version of my packaged machine is 7.1, but the online machine is 7.0. 0, which will cause this problem.

In fact, composer is more powerful than we thought. According to the PHP version of your current machine, it will judge which version you use for all dependencies. When composer update, it will choose the best version according to the requirements of all dependencies.

So I switched PHP to 7.0 on my packaging machine and looked at the generated composer. lock, where symfony/translation was limited to 3.3. x without this problem.

Correct Posture of composer

Do you want to add composer. lock to the git library

This is a mistake I made this time. I didn't put composer. lock into the version library. When packaging the machine composer install, it is equivalent to update operation. For business, this is wrong. What the business needs to do is to ensure the stability of the business. In fact, any upgrade of library dependence needs to be tested and verified by the business before it can go online. Therefore, it is strongly recommended to force composer. lock into the git code base in business projects.

Do you want to use automatic upgrade

For version dependencies, the ~, ^ symbol will be used in composer udpate according to the existing class library of the dependency package.

I understand that the automatic upgrade mechanism has both advantages and disadvantages, which is equivalent to putting the initiative (the initiative of update has been mentioned here). As a basic class library, I certainly hope you can trust me when you use me. Every version upgrade is compatible and bug will not be introduced. Therefore, the class library will hope that you will use automatic upgrade. In this way, my 1 bug fixes will be automatically downloaded and fixed when you update.

But for business, business stability is a dead requirement. 1 When I was update, I used your newly downloaded package, which actually made it possible to introduce an bug. This operation should not be done without complete testing.

But in fact, we can't completely eliminate this situation. For example, when one of your lib packages depends on another lib package, if it uses automatic upgrade, you have no choice at all.

Therefore, once we use package dependence, automatic upgrade can't be eliminated.

Use update with caution

When using update operation, you must think of what operation will be triggered, try to compare the differences between composer. lock, and understand the differences between the two dependent packages before and after.

Summarize

Package dependency problem, not only php, golang also have, the basic points of attention are as above, 1 kind.


Related articles: