-1

I'm fairly new to programming and have to make a website compatible to php7. I don't want to change more of the code then I need to so I decided to change the old deprecated (and not working anymore) mysql_ to the newer mysqli_ db-connection.

So far everything works quite well but in a few scripts I have a problem with the require_once of db-connection-script it's included at the top of the script and works well but in a "function" in the same script the included db-connection-file and it's variables are not usable not even when I "include_once" it again.

But if i just "include()" it, it works again. My question is, why? As i have understood it including a file multiple times without the "include_once" could cause problems so I really need help in understanding this issue.

index.php:

<?php
require_once('../../Connections/db.php');
mysqli_select_db($dbcon, $dbname);
$query = "SELECT x, y FROM dbtable WHERE z";

works well but within the same file:

function pruefe_datum($datum){

if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {
require_once('../../Connections/db.php');
$theValue = mysqli_escape_string($dbcon, $theValue);
} } }

throws:

Notice: Undefined variable: dbcon and Warning: mysqli_escape_string() expects parameter 1 to be mysqli, null given

Martin
  • 19,815
  • 6
  • 53
  • 104
Rocktale
  • 1
  • 1
  • Are you using `require_once('../../Connections/db.php');` twice in the same file? – Abhishek Nov 11 '16 at 09:58
  • You forgot to show initialization of the `$dbcon` variable – Ruslan Osmanov Nov 11 '16 at 09:59
  • 3
    What do you think the `_once` bit means? – Jonnix Nov 11 '16 at 09:59
  • That's the problem, as far as i can tell values are not unset. And should be carried through but aren't. @Jon Stirling I know it won't be included again if it already has been. Al i want to know is, why the is the connection-variable not available within the function? – Rocktale Nov 11 '16 at 10:14
  • @Rocktale I think you've just answered your own question. The file has been included elsewhere, so the file won't be included here within the function scope. – Jonnix Nov 11 '16 at 10:20

2 Answers2

2

You are using require_once('../../Connections/db.php');

outside the function. So the Connections/db.php is already included and hence not available inside the function even if you include it by require_once again.

See difference

Solution: remove the second require call and to instead pass the variable into the function: GetSQLValueString($theValue, $dbcon, ....)

Community
  • 1
  • 1
Abhishek
  • 3,504
  • 17
  • 39
  • 1
    so *a* solution would be to remove the second require call and to instead pass the variable into the function: `GetSQLValueString($theValue, $dbcon, ....)` – Martin Nov 11 '16 at 10:08
  • @Martin Correct. Including it in the answer. Thanks. – Abhishek Nov 11 '16 at 10:09
  • Yes it is included outside the function but why isn't the connection available inside the function now? I mean, the whole script worked with the older mysql but not with mysqli. – Rocktale Nov 11 '16 at 10:11
  • @Rocktale your `$dbcon` variable is available in the file but not in the local scope of the function – Abhishek Nov 11 '16 at 10:17
  • unless i pass it as a parameter as @Martin has stated isn't it? Yea that sounds logical to me. Well okay, is it still possible to take the last connection with "mysqli_" as it was with "mysql_" when not passing a parameter? i guess not, just curious. – Rocktale Nov 11 '16 at 10:23
-1

Assuming you did not close the DB connection before this function the following should work:

function pruefe_datum($datum){
    if (!function_exists("GetSQLValueString")) {
        function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {
            global $dbcon; 
            $theValue = mysqli_escape_string($dbcon, $theValue);
        }
    } 
}

It is a scope issue. The $dbcon variable doesn't exist inside the function and the second require_once is ignored and not needed.

Tim
  • 1,950
  • 11
  • 16
  • Yes i guess that's the best way to resolve it. I know some others here have stated the scope-problem too and thanks to them all! As i said, i'm still learning. And the older "mysql_"-method didn't necessarily needed a connection passed to it, it just took the last one available or tries to open a new one but the "mysqli_"-method wants a connection passed as parameter so that seemed to be the reason why it worked with the old "mysql_" but doesn't with my changes to "mysqli_". Thanks a lot! – Rocktale Nov 11 '16 at 10:32
  • @Rocktale NO. Using `global` is a bad idea for this sort of code construction. It combines the two values (the function and the database var) far too closely and can easily cause you complexity problems down the line. [read more about why](http://stackoverflow.com/q/130878/3536236) . This answer by varlogtim is not best practise. [More here](http://stackoverflow.com/q/1557787/3536236) – Martin Nov 11 '16 at 11:49
  • @Martin Okay i understand it could cause problems setting global vars, thanks for the links. What i still don't understand what else could i do to solve my problem? As stated, i don't want to change more of the code then i need to but i also want it to work and also want to learn how things are considered to be done correctly. So, should i pass the connection variable as parameter to every function, where i need it rather then declaring it as global? Or what else could i do? – Rocktale Nov 14 '16 at 09:27
  • If you have lots of functions that use a database connection, then you shuold simply make a database `Class` which contains these functions and havea variable in the class to hold the db connection. Then it's accessible to everyone in the class. On other notes; if you want to do best practise but you don't want to edit your code, then that's a bit of a crux as you need to constantly develop and redesign non-best-practise code, so it's a bit like wanting to talk but not wanting to open your mouth.... :-/ – Martin Nov 14 '16 at 12:15
  • @Rocktale to further illustrate, say you have a set of functions for dealing with a customer basket, you can then set these functions all into a `basket` class and in that basket class you can define (in the construct) a variable to contain the database connection and then use that from any function (called method) within the class. `$basket = new BasketClass($dbcon);` where `dbcon` is then saved into the basket class as a variable that can be reached with `$this->basketDbVar` – Martin Nov 14 '16 at 12:17
  • @Martin Yep that's also how i would do it, if i would have to make a new project. But the website here was developed several years ago, and many scripts and addons were just plugged on top of the former website-code with own db-connections and relations all developed from different programmers. Some decisions worked okay with the former php4 and php5 but now aren't at all with newer code like "mysqli" as said i'm new to this and didn't know about all the incompatibilities that could ocure. – Rocktale Nov 17 '16 at 08:31
  • The worst thing for me, this code is "grown" and a real mess. So i decided to only change what i have to, not because i'm stupid or lazy but because the customer doesn't want to pay much for this project and if i want to make such heavy changes so it would be considered "good practise" i feel would need to understand every single bit of that project which in the present form would sure take me at lot more time than i have. I have no other developer here to ask or to confirm what i think so i decide the best i can. hanks for your help, it's really appreciated! – Rocktale Nov 17 '16 at 08:33
  • @Rocktale I sympathise exactly with your issues; I have the same issue as I've inherited lots of frankly horrific code from other companies/programmers. It's a tough call to improve the code without getting a set price for the job, but I manage it as one of those salami slices -- 20 minutes a day tweaking up, and gradually sites will be improved. Good luck with it `:-)` – Martin Nov 17 '16 at 11:14