php 7.4 DOM support not enabled

Hi there,

I have a 12.1-RELEASE-p10 box running nginx and php7.4 (both installed from pkg) for largely hosting wordpress sites (mariadb on another server), and i've just struck a rather unusual error.

When trying to use a 'one click install' theme to import some templated settings, the process didnt seem to complete properly, with lots of imported settings missing.

nginx's error log shows:
Code:
 FastCGI sent in stderr: "message: PHP Warning:  DOM support is not enabled in [PATH TO SITE HERE]WXRImporter.php on line 386PHP message: PHP Warning:  Invalid argument supplied for foreach()...
Which then repeats a few times across that line.

However the php dom extension is installed:

output of php -m:
Code:
[PHP Modules]
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gd
hash
iconv
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
Reflection
session
SimpleXML
soap
sockets
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlrpc
xmlwriter
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache
I've done a fair bit of googling and most of the solutions are "make sure these packages are installed and enabled" which they appear to be. The closest thing i can find is this, which notes:
This appears to be a FreeBSD specific issue.

Build php74 from the ports collection, and add the following CONFIGURE_ARGS= flags:

--enable-dom
--enable-xmlreader

Then make sure the php74-dom and php74-xmlreader packages are not installed. If they are installed as a prerequisite for another package, just remove the extension ini from /usr/local/etc/php since these extensions are now compiled in directly.


I'm a relative newcomer to FreeBSD, with most of my sites currently living on an ubuntu box, but chose to make the progressive switch to FreeBSD to allow for better scaling and growth. This is certainly not an issue I've encountered on Ubuntu.

Just wondering if anyone has any thoughts? Removing php and recompiling from ports sounds pretty drastic...

Thanks!
 
What does the output of pkg info look like?

The FreeBSD port for php has very few modules compiled in unless they are absolutely necessary (even basic stuff like session support).
This is to allow users to choose their own modules without having to compile from source.

As far as I'm aware there are no modules that actually require recompiling from source to enable. You likely simply need to install the php74-dom package and restart the php-fpm service (or whatever service is handling php).

EDIT: Just noticed you do have dom in the module list which suggests it's already installed. Strange. Still be interesting to see the pkg info list and I'd also make sure you've restarted all the relevant services just in case you haven't done that since installing this module
 
What does the output of pkg info look like?

The FreeBSD port for php has very few modules compiled in unless they are absolutely necessary (even basic stuff like session support).
This is to allow users to choose their own modules without having to compile from source.

As far as I'm aware there are no modules that actually require recompiling from source to enable. You likely simply need to install the php74-dom package and restart the php-fpm service (or whatever service is handling php).

EDIT: Just noticed you do have dom in the module list which suggests it's already installed. Strange. Still be interesting to see the pkg info list and I'd also make sure you've restarted all the relevant services just in case you haven't done that since installing this module

Hi! Thanks for your help!

Here's just the PHP modules, or would the entire output help?

Code:
php74-7.4.10                   PHP Scripting Language
php74-ctype-7.4.10             The ctype shared extension for php
php74-curl-7.4.10              The curl shared extension for php
php74-dom-7.4.10               The dom shared extension for php
php74-exif-7.4.10              The exif shared extension for php
php74-extensions-1.0           "meta-port" to install PHP extensions
php74-fileinfo-7.4.10          The fileinfo shared extension for php
php74-filter-7.4.10            The filter shared extension for php
php74-ftp-7.4.10               The ftp shared extension for php
php74-gd-7.4.10                The gd shared extension for php
php74-iconv-7.4.10             The iconv shared extension for php
php74-json-7.4.10              The json shared extension for php
php74-mbstring-7.4.10          The mbstring shared extension for php
php74-mysqli-7.4.10            The mysqli shared extension for php
php74-opcache-7.4.10           The opcache shared extension for php
php74-openssl-7.4.10           The openssl shared extension for php
php74-pdo-7.4.10               The pdo shared extension for php
php74-pdo_sqlite-7.4.10        The pdo_sqlite shared extension for php
php74-phar-7.4.10              The phar shared extension for php
php74-posix-7.4.10             The posix shared extension for php
php74-session-7.4.10           The session shared extension for php
php74-simplexml-7.4.10         The simplexml shared extension for php
php74-soap-7.4.10              The soap shared extension for php
php74-sockets-7.4.10           The sockets shared extension for php
php74-sqlite3-7.4.10           The sqlite3 shared extension for php
php74-tokenizer-7.4.10         The tokenizer shared extension for php
php74-xml-7.4.10               The xml shared extension for php
php74-xmlreader-7.4.10         The xmlreader shared extension for php
php74-xmlrpc-7.4.10            The xmlrpc shared extension for php
php74-xmlwriter-7.4.10         The xmlwriter shared extension for php
php74-zip-7.4.10               The zip shared extension for php
php74-zlib-7.4.10              The zlib shared extension for php
 
I got same configuration here (12.1-RELEASE-p10) and it works without any modifications

- nginx-1.18.0_15,2
- php74-7.4.10
- php74-dom-7.4.10

Did you try to use dom in a simple script and see what happens. ie:
Code:
$d = new domDocument;
.....
 
Would be interesting to know what is around line 386 of that file to see what it's trying to do. If dom shows up in phpinfo, PHP should not be complaining about it missing when Wordpress tries to use it.
 
I got same configuration here (12.1-RELEASE-p10) and it works without any modifications

- nginx-1.18.0_15,2
- php74-7.4.10
- php74-dom-7.4.10

Did you try to use dom in a simple script and see what happens. ie:
Code:
$d = new domDocument;
.....

I'm so sorry i didnt see this post earlier!

Only difference in our setups is im running nginx-1.19.0! I doubt that means anything however :)

To your suggestion, i just put:

Code:
<?php $d = new domDocument; ?>

Into https://dev.duraplan.co.nz/labsolutions/test2.php and get a blank page.
PHP is not my strong suit, but is this expected?


Would be interesting to know what is around line 386 of that file to see what it's trying to do. If dom shows up in phpinfo, PHP should not be complaining about it missing when Wordpress tries to use it.

I'm starting to wonder this actually. I posted the same question on the php mailing list and someone there suggested the code could be at fault.

this is what is at line 386 - second line below but this is the full function:

Code:
                                case 'item':
                                        $node = $reader->expand();
                                        $parsed = $this->parse_post_node( $node );
                                        if ( is_wp_error( $parsed ) ) {
                                                $this->log_error( $parsed );

                                                // Skip the rest of this post
                                                $reader->next();
                                                break;
                                        }

The other error is throwing at line 617 (first line):

Code:
                foreach ( $node->childNodes as $child ) {
                        // We only care about child elements
                        if ( $child->nodeType !== XML_ELEMENT_NODE ) {
                                continue;
                        }

A similar issue was raised on the theme support forums about two months ago here. I missed earlier where a downgrade in wordpress version appears to have worked, but ultimately the chap who posted the issue in the first place has said he changed host and that fixed it.

If the test DOM page above is behaving as expected (which i hope one of you extremely helpful people can advise...) then it would seem to be an issue with the theme the way it's calling the DOM extension in PHP7.4, wouldn't it? I wonder if the OP there just switched to a host on an earlier version of php. Certainly my ubuntu box is running 7.3 right now.

Thanks again for all your help, i really appreciate it.
 
Into https://dev.duraplan.co.nz/labsolutions/test2.php and get a blank page.
PHP is not my strong suit, but is this expected?
yes its working its not gonna show anything anyways: just creating dom object

if DOM wasn't working properly then it would have thrown error (also you can check your logs)
So there is no problem with php and dom

i dont use wordpress but i can install and check if i got a chance today

Note: its normal you see my msgs late im still on "probation period" :)
 
The test page appears to be doing what is expected if it is not generating any errors in the page or logs. It's creating an object but not doing anything with it so blank output is expected.

Be interesting to see what this test program does as it replicates what the theme is doing - creating an XMLReader, then trying to use expand to get a dom object.

Code:
<?php
$x = XMLReader::xml('<?xml version="1.0"?><doc></doc>');
$x->read();
$y = $x->expand();
var_dump($y);

Running from the console on one of my web servers that has php-dom installed, I get the following output.

Code:
# php
<?php
$x = XMLReader::xml('<?xml version="1.0"?><doc></doc>');
$x->read();
$y = $x->expand();
var_dump($y);

object(DOMElement)#2 (17) {
  ["tagName"]=>
  string(3) "doc"
  ["schemaTypeInfo"]=>
  NULL
  ["nodeName"]=>
  string(3) "doc"
  ["nodeValue"]=>
  string(0) ""
  ["nodeType"]=>
  int(1)
  ["parentNode"]=>
  NULL
  ["childNodes"]=>
  string(22) "(object value omitted)"
  ["firstChild"]=>
  NULL
  ["lastChild"]=>
  NULL
  ["previousSibling"]=>
  NULL
  ["nextSibling"]=>
  NULL
  ["attributes"]=>
  string(22) "(object value omitted)"
  ["namespaceURI"]=>
  NULL
  ["prefix"]=>
  string(0) ""
  ["localName"]=>
  string(3) "doc"
  ["baseURI"]=>
  NULL
  ["textContent"]=>
  string(0) ""
}

I think I came across the same fix on github as you, but I see no reason why the dom extension should need to be compiled in. Additionally, I clearly have no issue using XMLReader and then expand() to get a dom object in test code that is using PHP from packages.
 
In the source code for the PHP extension (this is 7.3.22 but close enough, maybe) ext/xmlreader/php_xmlreader.c
Code:
1108 /* {{{ proto bool XMLReader::expand()
1109 Moves the position of the current instance to the next node in the stream. */
1110 PHP_METHOD(xmlreader, expand)
1111 {
1112 #ifdef HAVE_DOM
...
1150 #else
1151         php_error(E_WARNING, "DOM support is not enabled");
1152         return;
1153 #endif

So the PHP warning looks like there's a compile-time check (?) for HAVE_DOM in the XMLReader expand() code and if that falls, you'll get the message at run time.

I've not quite worked out what sets HAVE_DOM and how it would differ from port build versus pkg install.

Might be a complete red herring!
 
yes its working its not gonna show anything anyways: just creating dom object

if DOM wasn't working properly then it would have thrown error (also you can check your logs)
So there is no problem with php and dom

i dont use wordpress but i can install and check if i got a chance today

Note: its normal you see my msgs late im still on "probation period" :)

Okay thanks! Just ran it again and checked the logs - no error.

However...

The test page appears to be doing what is expected if it is not generating any errors in the page or logs. It's creating an object but not doing anything with it so blank output is expected.

Be interesting to see what this test program does as it replicates what the theme is doing - creating an XMLReader, then trying to use expand to get a dom object.

Code:
<?php
$x = XMLReader::xml('<?xml version="1.0"?><doc></doc>');
$x->read();
$y = $x->expand();
var_dump($y);

Running from the console on one of my web servers that has php-dom installed, I get the following output.

Code:
# php
<?php
$x = XMLReader::xml('<?xml version="1.0"?><doc></doc>');
$x->read();
$y = $x->expand();
var_dump($y);

object(DOMElement)#2 (17) {
  ["tagName"]=>
  string(3) "doc"
  ["schemaTypeInfo"]=>
  NULL
  ["nodeName"]=>
  string(3) "doc"
  ["nodeValue"]=>
  string(0) ""
  ["nodeType"]=>
  int(1)
  ["parentNode"]=>
  NULL
  ["childNodes"]=>
  string(22) "(object value omitted)"
  ["firstChild"]=>
  NULL
  ["lastChild"]=>
  NULL
  ["previousSibling"]=>
  NULL
  ["nextSibling"]=>
  NULL
  ["attributes"]=>
  string(22) "(object value omitted)"
  ["namespaceURI"]=>
  NULL
  ["prefix"]=>
  string(0) ""
  ["localName"]=>
  string(3) "doc"
  ["baseURI"]=>
  NULL
  ["textContent"]=>
  string(0) ""
}

I think I came across the same fix on github as you, but I see no reason why the dom extension should need to be compiled in. Additionally, I clearly have no issue using XMLReader and then expand() to get a dom object in test code that is using PHP from packages.

I set that code up in a php file here and i get NULL.

And in the nginx error.log:
Code:
*2387 FastCGI sent in stderr: "PHP message: PHP Warning:  DOM support is not enabled in [path]/test3.php on line 4" while reading response header from upstream, client: [my ip], server: dev.duraplan.co.nz, request: "GET /labsolutions/test3.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "dev.duraplan.co.nz"

I must apologise, im not sure how to run that from console, but if i do:
Code:
php [path]/test3.php

I also get:

Code:
PHP Warning:  DOM support is not enabled in /usr/local/www/duraplan.co.nz/dev/html/labsolutions/test3.php on line 4
NULL

So DOM is working, but it's having a hard time doing expand() ?

This server is running on digitalocean, so i could take a snapshot and deploy it to a new droplet, remove php and then reinstall from ports, if you think that would be a worthwhile endeavour?
 
Think you are (sadly) right - it makes a difference ports versus pkg.

So on this machine I've used ports to get install php-7.4, and I try the test code from usdmatt.

I pkg install as required, and I end up with the same message:
Code:
# php test.php
PHP Fatal error:  Uncaught Error: Class 'XMLReader' not found in /usr/home/xyz/test.php:2
Stack trace:
#0 {main}
  thrown in /usr/home/xyz/test.php on line 2
# pkg info | grep php
php74-7.4.10                   PHP Scripting Language
# pkg install php74-dom
Updating FreeBSD repository catalogue...
Fetching meta.conf: 100%    163 B   0.2kB/s    00:01   
Fetching packagesite.txz: 100%    6 MiB 827.4kB/s    00:08   
Processing entries: 100%
FreeBSD repository update completed. 31943 packages processed.
All repositories are up to date.
Updating database digests format: 100%
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
    php74-dom: 7.4.10

Number of packages to be installed: 1

54 KiB to be downloaded.

Proceed with this action? [y/N]: y
[1/1] Fetching php74-dom-7.4.10.txz: 100%   54 KiB  55.4kB/s    00:01   
Checking integrity... done (0 conflicting)
[1/1] Installing php74-dom-7.4.10...
[1/1] Extracting php74-dom-7.4.10: 100%
=====
Message from php74-dom-7.4.10:

--
This file has been added to automatically load the installed extension:
/usr/local/etc/php/ext-20-dom.ini

# php test.php
PHP Fatal error:  Uncaught Error: Class 'XMLReader' not found in /usr/home/xyz/test.php:2
Stack trace:
#0 {main}
  thrown in /usr/home/xyz/test.php on line 2

# pkg install php74-xmlreader
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
    php74-xmlreader: 7.4.10

Number of packages to be installed: 1

12 KiB to be downloaded.

Proceed with this action? [y/N]: y
[1/1] Fetching php74-xmlreader-7.4.10.txz: 100%   12 KiB  12.3kB/s    00:01   
Checking integrity... done (0 conflicting)
[1/1] Installing php74-xmlreader-7.4.10...
[1/1] Extracting php74-xmlreader-7.4.10: 100%
=====
Message from php74-xmlreader-7.4.10:

--
This file has been added to automatically load the installed extension:
/usr/local/etc/php/ext-20-xmlreader.ini
# php test.php
PHP Warning:  DOM support is not enabled in /usr/home/xyz/test.php on line 4
NULL

I'll try deleting the packages and building those two from ports - JUST as an experiment, it's not good to mix ports & packages.
 
Delete packages, build from ports - works here for me.
Code:
# pkg delete php74-xmlreader-7.4.10 php74-dom-7.4.10
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 2 packages (of 0 packages in the universe):

Installed packages to be REMOVED:
    php74-dom: 7.4.10
    php74-xmlreader: 7.4.10

Number of packages to be removed: 2

Proceed with deinstalling packages? [y/N]: y
[1/2] Deinstalling php74-xmlreader-7.4.10...
[1/2] Deleting files for php74-xmlreader-7.4.10: 100%
[2/2] Deinstalling php74-dom-7.4.10...
[2/2] Deleting files for php74-dom-7.4.10: 100%
# cd /usr/ports/lang/php74-extensions/
# make config
-- select DOM and XMLREADER only --
# make install
# php /home/xyz/test.php
object(DOMElement)#2 (17) {
  ["tagName"]=>
  string(3) "doc"
  ["schemaTypeInfo"]=>
  NULL
  ["nodeName"]=>
  string(3) "doc"
  ["nodeValue"]=>
  string(0) ""
  ["nodeType"]=>
  int(1)
  ["parentNode"]=>
  NULL
  ["childNodes"]=>
  string(22) "(object value omitted)"
  ["firstChild"]=>
  NULL
  ["lastChild"]=>
  NULL
  ["previousSibling"]=>
  NULL
  ["nextSibling"]=>
  NULL
  ["attributes"]=>
  string(22) "(object value omitted)"
  ["namespaceURI"]=>
  NULL
  ["prefix"]=>
  string(0) ""
  ["localName"]=>
  string(3) "doc"
  ["baseURI"]=>
  NULL
  ["textContent"]=>
  string(0) ""
}

So is there something you can "tickle" with the pkg version to make it work?
 
Delete packages, build from ports - works here for me.
Code:
# pkg delete php74-xmlreader-7.4.10 php74-dom-7.4.10
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 2 packages (of 0 packages in the universe):

Installed packages to be REMOVED:
    php74-dom: 7.4.10
    php74-xmlreader: 7.4.10

Number of packages to be removed: 2

Proceed with deinstalling packages? [y/N]: y
[1/2] Deinstalling php74-xmlreader-7.4.10...
[1/2] Deleting files for php74-xmlreader-7.4.10: 100%
[2/2] Deinstalling php74-dom-7.4.10...
[2/2] Deleting files for php74-dom-7.4.10: 100%
# cd /usr/ports/lang/php74-extensions/
# make config
-- select DOM and XMLREADER only --
# make install
# php /home/xyz/test.php
object(DOMElement)#2 (17) {
  ["tagName"]=>
  string(3) "doc"
  ["schemaTypeInfo"]=>
  NULL
  ["nodeName"]=>
  string(3) "doc"
  ["nodeValue"]=>
  string(0) ""
  ["nodeType"]=>
  int(1)
  ["parentNode"]=>
  NULL
  ["childNodes"]=>
  string(22) "(object value omitted)"
  ["firstChild"]=>
  NULL
  ["lastChild"]=>
  NULL
  ["previousSibling"]=>
  NULL
  ["nextSibling"]=>
  NULL
  ["attributes"]=>
  string(22) "(object value omitted)"
  ["namespaceURI"]=>
  NULL
  ["prefix"]=>
  string(0) ""
  ["localName"]=>
  string(3) "doc"
  ["baseURI"]=>
  NULL
  ["textContent"]=>
  string(0) ""
}

So is there something you can "tickle" with the pkg version to make it work?

Wow okay that looks like progress!

What is the best thing to do here? Noting this server is currently serving up one other site at the moment so is effectivly in production, should i just remove the DOM and XML reader packages then install them both from ports, or should i remove my entire PHP PKG install and recompile everything from ports?

i will obviously test it on a snapshot of the server first, but just in terms of best execution here!

And how do we report this bug?!
 
Not sure of the "best" thing. If you need the server working ASAP then you could try and build the ports (via a test instance as you say) but that's really a BandAid - you don't want to mix ports and packages if you can help it but might do as a temporary bodge. If you do that and walk away it's going to cause grief at upgrade time (7.4.11 was recently released so will be arriving at some time).

My test machine has ports build already so any build dependencies will be on there already - if you try on a machine there might be a few more steps (but I think in theory you could then take the packages you built and put just those on production).

I've come along this far out of interest (I still use ports but keep meaning to take the leap to packages) but not sure what to advise next.

Will be interested to see what usdmatt has to say (that sounds rude but I don't mean it!) It seemed to work with packages on that set-up, so there might be a solution there that doesn't involve ports.
 
Not sure of the "best" thing. If you need the server working ASAP then you could try and build the ports (via a test instance as you say) but that's really a BandAid - you don't want to mix ports and packages if you can help it but might do as a temporary bodge. If you do that and walk away it's going to cause grief at upgrade time (7.4.11 was recently released so will be arriving at some time).

My test machine has ports build already so any build dependencies will be on there already - if you try on a machine there might be a few more steps (but I think in theory you could then take the packages you built and put just those on production).

I've come along this far out of interest (I still use ports but keep meaning to take the leap to packages) but not sure what to advise next.

Will be interested to see what usdmatt has to say (that sounds rude but I don't mean it!) It seemed to work with packages on that set-up, so there might be a solution there that doesn't involve ports.

Having come from ubuntu, using pkg is a lot more familiar to me that's for sure, and mixing ports and pkg does seem like a recipe for disaster!
It will be interesting to see what udsmatt can add for sure

(Sorry i didnt see the comment around "tickling"! I am unsure, but again wiser folks may have some thoughts!)
 
Unfortunately it looks like the "solution" at the moment that doesn't involve ports is to use php-73.

Didn't pay it much attention as it's only a minor version difference but my machine is running 7.3 instead of 7.4. The freshports page for php73-xmlreader lists php73-dom as a dependency. Obviously that port is being built with dom switched on.

The freshports page for php74-xmlreader does not list dom as a requirement. I don't know if this is an intentional choice or a mistake. Might be worth a bug report to see what the response from the maintainer is.
 
So it seems the solution, pending the fix from the maintainer, is to completely remove php74 by and then install php73, right? Im not sure im particularly keen to swap to ports at this point!

You folks are so incredibly helpful, i cannot thank you enough for all the help and support you've given me on this. Really, truly appreciate all the assistance and effort you've all gone to.
 
That is a very good question because it depends. The pkg on quarterly is built on specific intervals, so it can take between 1 to 3 days. Most times it is available the next day.

Just a heads up: if everything goes fine, i will commit the latest PHP update today.
 
Back
Top