0

I'm new to PHP and am trying to write a few PHP scripts which connect to a local MySQL server. FYI, I'm developing on Ubuntu 22.04, coding in PHP 8.1.2, and connecting to a MySQL server, version 8.0.28.

Here's the problem in a nutshell: In my PHP scripts, I try to connect to the DB server using a mysqli object:

$con = new mysqli($servername, $username, $password, $database, $mysqlPort, $socket);

To use mysqli, you have to install mysqli, which I've done on my development machine. I got the command to work in my first script:

function openDBConn( $servername, $username, $password, $database, $mysqlPort, $socket, $tr )
{
        $con = null;

        try{
                $con = new mysqli($servername, $username, $password, $database, $mysqlPort, $socket);
        } catch (Exception $e){
                $error = $e->getMessage();
                echo $error;
        }
        print("Connection successful!\n");

        // write to DB

        $con->close();
}

You'll note that I'm using a function to open a connection, write to, and close the connection to the DB. This bit of code works great.

But now here's my problem: I need a second script to also open a connection to the same DB server. Here's Script #2:

<?php

// DB Variables
$servername = "10.10.10.123";
$database = "myDB";
$username = "user01";
$password = "password01";
$mysqlPort = "3306";
$socket = "/var/run/mysqld/mysqld.sock";

if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
    echo 'We don\'t have mysqli!!!';
} else {
    echo 'Phew we have it!';
}

$con = null;
print("\nOpening db connection...\n");
try{
        $con = new mysqli($servername, $username, $password, $database, $mysqlPort, $socket);
} catch (Exception $e){
        $error = $e->getMessage();
        echo $error;
}
print("Connection successful!\n");

...more...

If you hold both scripts side-by-side, you'll see that I'm creating a new mysqli object with the same lines of code. The difference is that the second script crashes on the new mysqli() line. Here's the script output:

We don't have mysqli!!! Opening db connection...

No error is caught, nothing happens after $con = new mysqli(). The output from the proceeding if() check does explain the problem: mysqli is not loaded (installed? available? linked?) for this script, which is why Script #2 fails.

But what the heck? I installed mysqli on this server. The fact that Script #1 works demonstrates this much. Both Script 1 and Script 2 run in the same directory, both are run by the same user, both use the same code. I've searched Script 1 for additional references to mysqli, but I can't find any. Any idea why one script would have mysqli and the other wouldn't? The only difference I see between the two is that Script 1 calls $con = new mysqli() from a function; why would that make a difference?

FYI, my question has sort of been asked on SO before (see here and here) but not with the "one script works, the other doesn't" angle. Any advice/insight is welcome, thank you.

=================================================================== EDIT Based on feedback, I've since created this file in the same directory where Script1 and Script2 are:

me@myUbuntu:/var/www/html$ more SOtest.php
<?php phpinfo();
me@myUbuntu:/var/www/html$

That's it; the entire file is just that one line of code, <?php phpinfo();. When I set it to the same permissions and ownership as Script1 and Script2 and then run it and scan its output, I see this:

me@myUbuntu:/var/www/html$ sudo php SOtest.php > OUTPUT.txt
me@myUbuntu:/var/www/html$ more OUTPUT.txt | grep mysqli
/etc/php/8.1/cli/conf.d/20-mysqli.ini,
mysqli
mysqli.allow_local_infile => Off => Off
mysqli.allow_persistent => On => On
mysqli.default_host => no value => no value
mysqli.default_port => 3306 => 3306
mysqli.default_pw => no value => no value
mysqli.default_socket => /var/run/mysqld/mysqld.sock => /var/run/mysqld/mysqld.sock
mysqli.default_user => no value => no value
mysqli.local_infile_directory => no value => no value
mysqli.max_links => Unlimited => Unlimited
mysqli.max_persistent => Unlimited => Unlimited
mysqli.reconnect => Off => Off
mysqli.rollback_on_cached_plink => Off => Off
API Extensions => mysqli,pdo_mysql
me@myUbuntu:/var/www/html$

It sure looks like mysqli is installed, even if Script2 can't see it.

=================================================================== EDIT Some commenters asked how Script1 and Script2 are called. I originally thought that both Script1 and Script2 were called by the website's HTML code. But that's not actually true. Script1 is actually called by another PHP script, a wrapper script that is invoked by the HTML. Here's the bit of PHP that calls Script1:

function runDBOperations(){
        print("Called runDBOperations()...");
        $someOutput = shell_exec("php /var/www/html/Script1.php");
        print("...done!\n");
}

I'd forgotten that the wrapper PHP script invokes Script1 in a function. Interesting.

Script2, however, is called directly from the HTML code:

<html>
        <body>

        <form action="Script2.php" method="post">
                Search <input type="text" name="search"><br>
                <input type ="submit">
        </form>

        </body>
</html>

(Yes, that's the entire webpage at this point.)

...There must be something in that wrapper PHP script which loads mysqli, don't you think? HmmmmMMMMmmmmm....

Pete
  • 1,511
  • 2
  • 26
  • 49
  • 1
    Well, it says that you don't have mysqli, then you try to use it anyway. I would suggest checking both the `function_exists` and `extension_loaded` separately to see if one or both are failing. Another question is are you running both scripts in a browser or command line, or one in a browser and one in a command-line? – aynber Apr 22 '22 at 16:23
  • @aynber Thanks good catch, aynber. So when I break up the `function_exists` and `extension_loaded` checks, both fail independently. So both are a problem. And to answer your question, both PHP scripts are being launched from two different HTML webpages. Script 1 runs from from Webpage 1, but Script 2 crashes from Webpage 2. – Pete Apr 22 '22 at 16:48
  • @YourCommonSense Thanks, Common Sense, that's a great idea. So when I add that line at the top of script2.php, I get: `Fatal error: Uncaught Error: Class "mysqli" not found in /var/www/html/script2.php:49 Stack trace: #0 {main} thrown in /var/www/html/script2.php on line 49` ... which pretty much says "I don't have mysqli installed" – Pete Apr 22 '22 at 16:51
  • 1
    And both scripts are running on the same webserver? Same website? Try creating a file in the same directory as the second script with the contents ` – aynber Apr 22 '22 at 16:52
  • 1
    Now, add the some code to the script1. you'd be surprised! @anyber, I got it, it's much simpler. Look closer to the first script – Your Common Sense Apr 22 '22 at 16:54
  • 1
    @YourCommonSense Oh, good point. There's no error thrown if the function is never called. – aynber Apr 22 '22 at 16:54
  • 1
    @aynber actually I thought about something different. But if the OP claims the first script deliberately works, it is not the case... – Your Common Sense Apr 22 '22 at 16:58
  • 1
    @Pete how do you know the first one works? What is the exact output? – Your Common Sense Apr 22 '22 at 16:59
  • @YourCommonSense Thanks YCS. So I know that the first script works because it is successfully scraping some data from an HTML form and writing it to the database. Script2 is intended to read the DB and display information on another HTML page... once I get the `mysqli()` connection working, that is – Pete Apr 22 '22 at 17:01
  • 2
    Scripts that do some scraping are usually called from the command line/cron. So again, how you're calling the script one? – Your Common Sense Apr 22 '22 at 17:04
  • @aynber I added the output from ` – Pete Apr 22 '22 at 17:07
  • @YourCommonSense Let me add that code into the Original Post, three minutes please... – Pete Apr 22 '22 at 17:07
  • 1
    Well, I see you have mysqli enabled for the command line. Is script2 being used on the command-line, or in a web browser? (Chrome, Firefox, Safari, etc and so on) You can have two different set of extensions enabled between CLI and Web – aynber Apr 22 '22 at 17:11
  • @aynber Thanks so much aynber! I think we're closing in on the answer. I checked, and Script1 is actually invoked from a wrapper PHP script, where Script2 (the one that doesn't work) is invoked by the HTML code. See edit to the Original Post, above... – Pete Apr 22 '22 at 17:18
  • 1
    You'll need to enable mysqli for the web browser. It should have it's own php.ini. If you view the phpinfo() *in the browser*, it will tell you which INI it's loading. – aynber Apr 22 '22 at 17:30
  • @aynber Thanks, that's incredibly helpful. Clarification: Did you mean to say that I'll have to enable `mysqli` in my web *server*, not the browser? i.e., make sure `mysqli` is enabled in Apache2, not Google Chrome running here on my laptop? Thanks – Pete Apr 22 '22 at 17:33
  • 2
    PHP has nothing to do with browsers. it runs on the web server. It is possible that you already installed mysqli though and only need to restart the web server – Your Common Sense Apr 22 '22 at 17:38
  • @YourCommonSense That makes a world of sense. I have to run to a business meeting, so I will check to see if I must enable mysqli on Apache2 and restart the service. I've a funny feeling this will solve the problem. Pls keep an eye on your SO inbox. If this works, I'll let you know, and if you do a Solution write-up, I'll give you the credit. Thanks! – Pete Apr 22 '22 at 17:43

1 Answers1

0

Please, consider to refactor this fragment of code:

if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
    echo 'We don\'t have mysqli!!!';
} else {
    echo 'Phew we have it!';
}

to

if (!function_exists('mysqli_init') {
    print("mysqli_init function doesn't exist");
} 
if (!extension_loaded('mysqli') {
    print("mysqli extension is not loaded");
}

This refactoring will help to track an error more precisely. I suppose that this error may eventually appear in the try-catch block, so previous checks are not necessary. Also, I propose to move the function openDBConn and connection settings to a separate file and append it to the two scripts via 'require_once'. This will help to debug two scripts at once. The last thing is that there is no 'graceful shutdown' in the catch block - you will see the error message at one line and simultaneously the successful message after it, because there is no 'if-else' logic behind this code.

Daria Motorina
  • 60
  • 1
  • 2
  • 26
  • @Daria Thanks, Daria. When I break out the two checks like you suggest, both conditions fail; both are problems. I guess I could remove the `mysqli` stuff from this script and transplant it into another, but script2 is pretty slimmed-down right now. Basically, all it tries to do is open the DB connection. I wish I knew why it was failing... – Pete Apr 22 '22 at 16:54