Bug 1181292

Summary: no json in php8 although it should be built in
Product: [openSUSE] openSUSE Tumbleweed Reporter: Erik Martre <erik.martre>
Component: OtherAssignee: Petr Gajdos <pgajdos>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P5 - None CC: dimstar, guenter.stoehr, i, jimc, rickscafe.casablanca, suse+build
Version: Current   
Target Milestone: ---   
Hardware: x86-64   
OS: openSUSE Tumbleweed   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Erik Martre 2021-01-22 14:54:53 UTC
Trying to open a local site fails with fatal uncaught error : undefined function json_encode(). 
PHP version is 8.0.1-1.1 built on 2021-01-20.
After coming back to  PHP7 (7.4.14-2.1) the site opens and works as usually.

I tried first to install all PHP8 packages similar to those I have with PHP7, but it didn't work and the site was unreachable because of connection reset, though I had restarted apache2.
Comment 1 Mark Draheim 2021-01-23 14:34:58 UTC
I think this a rpm problem. The php8 spec offers a provides:php-json which in turn somehow triggers nextcloud to install istall it as dependency. This breaks the php7 setup nextcloud sits on.

Generally, please, please be extra careful when updating php, even the minor versions that php considers major can easily break php apps like nextcloud. This happened several times in the past. I will move nextcloud to docker containers to avoid this but it would still be nice not having to check package names before updating TW installs here.
Comment 2 Mark Draheim 2021-01-23 15:07:24 UTC
Short term workaround for php7 installs:

* zypper in php7-json, which will bring up a conflict where you want to uninstall php8
* zypper al 'php8*'

I am not sure how to solve this in terms of rpm deps, other than adding an explicit requires:php7-json to nextcloud.
Comment 3 Yunhe Guo 2021-01-24 17:04:44 UTC
This also breaks php-composer dependencies. After zypper dup, it uninstall all php7 extensions and install php8.
Comment 4 Petr Gajdos 2021-01-27 10:40:29 UTC
Adding Arjen and Dominique.

(In reply to Erik Martre from comment #0)
> Trying to open a local site fails with fatal uncaught error : undefined
> function json_encode(). 

$ rpm -q php8
php8-8.0.1-0.x86_64
$ /usr/bin/php8 -r "if (function_exists('json_decode')) { echo 'exists'; }"
exists$

(In reply to Mark Draheim from comment #2)
> I am not sure how to solve this in terms of rpm deps, other than adding an
> explicit requires:php7-json to nextcloud.

At a glance, in case that we want to have both php7 and php8 in Tumbleweed, packages will have to choose one in case they are not compatible with the other. But note that provides are now versioned, e. g.

php8.spec
Provides:       php-json = %{version}

php7.spec
Provides:       php-hash = %{version}
Comment 5 Arjen de Korte 2021-01-27 19:09:49 UTC
This is caused by not resolving dependencies at package build time, but delaying it to install time. In some cases (like the above) this will lead to problems when there is a choice to be made and the choice leads to different results during package build and package install time (like we see here).

There are basically two ways to solve this (requirements are just examples):
 
1) Check during packaging which PHP version is used

%define php_name %(php -r "print 'php' . PHP_MAJOR_VERSION;")
BuildRequires: php-cli
Requires: apache-mod_%{php_name}
Requires: %{php_name}-openssl

2) Require the exact version of packages used during packaging

BuildRequires: php-devel
Requires: mod_php_any = %{php_version}
Requires: php-json = %{php_version}
Requires: php-openssl = %{php_version}

Both of these have their pros and cons.

The first will only depend on the major PHP version and therefor will not have to be reinstalled on each release of PHP (provided the package builds reproducible). But for instance with php-json this will fail, as php7-json is external, but in php8 this is a built-in and therefor there is no php8-json.

The second case will not suffer from this (php8 will still provide php-json, now it is built-in), but this also means that the package will need to be reinstalled with every release of PHP. Especially in Tumbleweed, this will mean a every month a new version will be built.

Note that in the above examples, the BuildRequires don't depend on the PHP version. This is intentional, as which version is used is determined by the Project Config the package is built in.

Please also be aware that in many cases, packages currently do actually depend on the PHP version used during packaging, as files are packaged in directories that contain the PHP major version number. This means these packages must depend on the PHP version as well, to make sure PHP can find these files.
Comment 6 Petr Gajdos 2021-01-28 07:43:01 UTC
*** Bug 1181487 has been marked as a duplicate of this bug. ***
Comment 7 Dominique Leuenberger 2021-01-28 07:47:06 UTC
From what I see, the main trouble is php8 providing php-json and obsoleting php7-json

so anything asking for 'php-json' gets php8

The provides is probably ok (for completeness, it should also provide the php8-* symbol), but the obsolete leads to this kind of issue.
Better to Conflict: php7-json in this case
Comment 8 Yunhe Guo 2021-01-28 08:19:46 UTC
(In reply to Dominique Leuenberger from comment #7)
> From what I see, the main trouble is php8 providing php-json and obsoleting
> php7-json
> 
> so anything asking for 'php-json' gets php8
> 
> The provides is probably ok (for completeness, it should also provide the
> php8-* symbol), but the obsolete leads to this kind of issue.
> Better to Conflict: php7-json in this case

Does it help if we make php7-json a "Requires" of php7?
Comment 9 Dominique Leuenberger 2021-01-28 08:23:24 UTC
(In reply to Yunhe Guo from comment #8)
> (In reply to Dominique Leuenberger from comment #7)
> > From what I see, the main trouble is php8 providing php-json and obsoleting
> > php7-json
> > 
> > so anything asking for 'php-json' gets php8
> > 
> > The provides is probably ok (for completeness, it should also provide the
> > php8-* symbol), but the obsolete leads to this kind of issue.
> > Better to Conflict: php7-json in this case
> 
> Does it help if we make php7-json a "Requires" of php7?

Not entirely sure - the Obsoletes in php8 might still give hints that php7-should not be present, as it's an obsolete package. so zypp might very well try to get PHP8 in place.

I'd argue, with PHP8 not ready to step in the shoes of php7, it should not obsolete php7-*, but only conflict: where needed; this gives much more control to the user and not to the solver trying to find a solution
Comment 10 OBSbugzilla Bot 2021-01-29 11:40:07 UTC
This is an autogenerated message for OBS integration:
This bug (1181292) was mentioned in
https://build.opensuse.org/request/show/867684 Factory / php8
Comment 11 Petr Gajdos 2021-02-01 12:45:52 UTC
*** Bug 1181603 has been marked as a duplicate of this bug. ***
Comment 12 Petr Gajdos 2021-02-02 08:53:30 UTC
I guess the fix is on its way to factory. Closing, reopen in case the issue persists.

Thanks for reporting and thanks Arjen and Dominique for fixing.
Comment 16 OBSbugzilla Bot 2023-10-26 10:35:52 UTC
This is an autogenerated message for OBS integration:
This bug (1181292) was mentioned in
https://build.opensuse.org/request/show/1120490 Backports:SLE-15-SP5 / php81