Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tip on passing the database connection $link around forms 2

Status
Not open for further replies.

svar

Programmer
Aug 12, 2001
349
0
0
GR
This is a question on passing the database link. In one form(authentication.php) I have
Code:
 include ('db_connect.php');
whose code is given below
This runs fine within the form. However the form calls another php form(menu.php) which has a menu and calls a third form(queryform.php)$resultu = mysqli_query($link,"SELECT ID,user,passwd FROM LOGIN WHERE user='$username' and passwd='$passwd' LIMIT 0,1");

There, any query, including the successful authentication query
Code:
$resultu = mysqli_query($link,"SELECT ID,user,passwd FROM LOGIN WHERE user='$username' and passwd='$passwd'  LIMIT 0,1");
returns no results ($username and $passwd were obtained from the first form and, I assume are in scope of ALL forms called by it)

I tried
Code:
$resultu = mysqli_query(LINK,"SELECT ID,user,passwd FROM LOGIN WHERE user='$username' and passwd='$passwd'   LIMIT 0,1");

after adding
Code:
define("LINK","link");
just below the db_connect
but again got no result.
How is this issue normally handled in PHP scripts? Is there any reference on this with examples?



The connect script
Code:
?php
 include_once 'globaldata.php';// This defines globals USER, PASSWORD and DATABASE
//$dbusername = "myuser";
//$dbpasswd   = "mypasswd";
//$db         = "mydatabase";

$link =mysqli_connect(HOST, USER, PASSWORD, DATABASE);
//$link =mysqli_connect("localhost", $dbusername, $dbpasswd, $db);
if (!$link) {
    die('Connect Error (' . mysqli_connect_errno() . ') '
            . mysqli_connect_error());
}

echo 'Success... ' . mysqli_get_host_info($link) . "\n";

/* for oracle use...
$link = OCILogon(USER,PASSWD,DATABASE);
if(!$link) {    die();}
*/
?>
 
you can't use constants for non-scalar values.

well .... in fact you can use a constant to hold a resource (such as a database link) but the manual strongly recommends against it. And in any event, mysqli_connect and mysqli_init return an object, not a resource (like mysql_connect does)

the easiest way to do this (and the 'normal' way) is to create a database connection script that you store outside of your web-root. You do this to protect sensitive data like passwords from inadvertent disclosure.

Code:
<?php
$dbHost = '';
$database = '';
$user = '';
$password = '';

$mysqli = mysqli_connect($dbHost, $user, $password, $database);
if(NULL !== ($err = mysqli_connect_error())) die($err);
?>

then in your script you require this file to bring it into scope.

Code:
require_once('/path/to/dbConnect.php');

then you can use the $mysqli variable in various scopes like this

Code:
//in the global scope
$result = mysqli_query($mysqli, 'some query');

//in functions
function myFunc(){
  global $mysqli; //bring in the mysqli connection
  $result = mysqli_query($mysqli, 'some query');
}
 
Thanks. Two points left to clarify:
1) since I only call db_connect if username and password are not blanc, I probably need include_once
instead of require_once if I understand correctly
2)I am not sure about global scope. The mysqli variable is defined in dbConnect,
which is called from authentication.php. So authentication.php "knows" $mysqli.
Next, authentication.php has an html code with HREF to menu.php and menu.php an HREF to queryform.php
queryform.php needs a mysqli_query($mysqli,...)

So all I need to do is a statement
Code:
global $mysqli;
probably as the first statement in query.php

Do I also need the same statement in authentication.php? and, if so, where? At the top (before dbconnect is called), or after it is called?

I will also get to the functions, but I am still trying one thing at a time.
 
you can use include or require as you wish.

however require_once is better because for most applications if a database connection cannot be established there is no point in continuing to execute the script. thus if the script does not exist or is not readable (and require fails) then equally the script should stop execution.

Next, authentication.php has an html code with HREF to menu.php and menu.php an HREF to queryform.php
queryform.php needs a mysqli_query($mysqli,...)

i have no idea what that means. if they are just href attributes of html links then this is irrelevant.
So all I need to do is a statement
Code:
global $mysqli;
probably as the first statement in query.php

no idea.
however you need to add
Code:
global $mysqli;
whenever you are trying to USE the $mysqli variable INSIDE A FUNCTION OR A CLASS METHOD. you do not need to use the global keyword simply because the script is in a different file. that is not relevant to scope. scope is global unless you are in a function or a class method (in which case it is local).
 
Thanks again.

Code:
..
if($flag ){
$href1='<td width="30%"> <A class=lightblue HREF="menu.php"> Authenticated as a user, click on link to
 proceed</A> </td>';
echo "$href1";}else{
$href2='<td width="30%"> <A class=lightblue HREF="menu2.php"> Authenticated as a superuser, click on link to proceed</A> </td>'; 
echo "$href2";
}

menu.php reads:
Code:
<?php
$htmlstring=' <div id="header">
<div id="navigation"> //moved this before the other elements
        <a href="query.php">do a query</a>
        <a href="new_access.php">Request new Access</a>';
echo "$htmlstring";
?>

and query.php reads:
Code:
<?php
$resultu = mysqli_query($mysqli,"SELECT * FROM MYTABLE");
if($resultu === false):  echo "Error in SQL query t false %s\n";  printf("Error: %s
\n", mysqli_error($mysqli));
else:// so sql statement is ok
if($mysqli){echo "link is true";}else{echo "link is false";}//here is says link is false
while($row = mysqli_fetch_array($resultu,MYSQLI_NUM)):
     echo " $row[0]  $row[1]  $row[2] $row[3]  $row[4]";
endwhile;
endif;
?>

So even though SELECT * FROM MYTABLE gives result if I do it from the command line (or in authentication.php), nothing is echoed from query.php, presumably because $mysqli is false.
This would mean that query.php has 'forgotten' the $mysqli object that authentication.php knew about.
Hope I make more sense now...
 
Variables do not subsist between script execution. Php is a stateless language.

You need to ensure mysqli is established for each script execution.
 
Variables do not subsist between script execution....
You need to ensure mysqli is established for each script execution.
In general I guess I need ALL variables somehow 'stored'.
That is, in one form the user enters a user name and password; authentication is done and the form knows its name and/or ID
when another form is used to do queries based on the user's name/ID, one does not wish to ask the user to retype credentials. So somehow such data MUST be passed. How do people solve this issue in PHP?
 
Using sessions.

You store any variables you need over different script executions in a session so you ca refer to them when you need them.

However the connection to a MYSQL DB must be instantiated every time.


You must use session start before attempting to read or write from a session.






----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.

Web & Tech
 
Thanks vacunita,
so, to recap:
1) with regard to the database link $mysqli, I need a dbconnect call once per php file which does at least a query
2)With regard to other scalar variables, I need in authentication.php
Code:
session start();
$id=....;
$_SESSION["id"]=$id;

and then in query.php
Code:
session_start();
$id=$_SESSION["id"] ;
So this works. The only question is then syntax, e.g. how does one _SESSION an array or associative array?

 
1) with regard to the database link $mysqli, I need a dbconnect call once per php file which does at least a query

no.

you need to connect to the database once per script. a script can consist of many hundreds of php files.

if you are remotely unsure about this then I'd advise that you use the following function in a library file (i.e. a file that you are guaranteed to load every script execution)
Code:
function myDBConnect(){
[indent]global $mysqli;[/indent]
[indent]if(empty($mysqli)) require_once '/path/to/dbConnect.php';[/indent]
}

and then include a call to myDBConnect() every time you might want to query the database.

in the alternative should you wish an example of a login and authentication script then I would be happy to post one of mine later today. you can then use it to develop your own.
 
Thanks. I want to try as many things as possible to figure out both how to work with PHP and how to work efficiently.

So
1) with respect to myDBConnect if I understand correctly
- a library file is just a php file and to load every script execution means via require/include statements in every file or some autoload? I'd like to see an example of its use if so.
-$mysqli need not be declared global anywhere else. Just calling the function will do

2) with respect to passing session variables, like user ID,
- for scalars something like
Code:
$id=$_SESSION["id"]
will work
-for nonscalars (e.g. an object like $mysqli) it will not and the solution was given below
-what about arrays? How does one store session variables like arrays or associative arrays? My solution would be
Code:
for $i=0,N
$_SESSION[$i]=$array[$i];
...
or similarly for associative arrays

Am I on the right track or is there a more standard and preferable way?
 
The distinction with scalars is only for constants.

You can store an object in a session variable. The only constraint is that php must know about the class to which the object belongs before the session is instantiated. This can be done with autoloaders. But whilst that deals with objects generally the $mysqli object references a resource handle internally. I do not know for sure whether it would work but there is no advantage to doing so anyway. The norm is to instantiate the connection for each script.

You treat $_SESSION just like a normal array. It can be as multidimensional as you like.

 
Code:
$id=$_SESSION["id"]

correct. but why bother? just reference the session variable directly rather than duplicate the memory footprint of the variable.

a library file is just a php file and to load every script execution means via require/include statements in every file or some autoload? I'd like to see an example of its use if so.

sure - you can look at it like that. I have a bunch of files that contain related functions. i store these files in a folder called library. in that folder i have a file called includes.php that automatically includes all other files in the folder that have a php extension.

but if there is a complex architecture it may be better to create sub folders of the library folder (each with an includes.php) and only pull in those files that you need depending on what type of process is going on (e.g. there is no need to pull in admin related functions if there is no admin interaction).

-$mysqli need not be declared global anywhere else. Just calling the function will do
any variable that is declared in the global scope is automatically global. but being global does not make a variable available in the global scope. you need to use the global keyword within the local scope for that. it's confusing nomenclature. you can also reference the variable without using the global keyword if you find that semantically more obvious. e.g.
Code:
global $mysqli; //bring $mysqli into the global scope
if ($mysqli === $GLOBALS['mysqli']) echo 'all is equal';

to store an array in a session

Code:
if(session_id() == '') session_start();
$array = array('black','orange','white','green');
$_SESSION['colours'] = $array;

$associativeArray = array('fruits'=>array('orange','tomato','banana'), 'vegetables'=>array('carrots','cabbage'));
$_SESSION['legumes'] = $associativeArray;

of course you can also assign things directly

Code:
if(session_id() == '') session_start();
$_SESSION['legumes'] = array('fruits'=>array('orange','tomato','banana'), 'vegetables'=>array('carrots','cabbage'));

and address elements directly

Code:
echo $_SESSION['legumes']['fruits'][0];

likewise objects

Code:
if(session_id() == '') session_start();
$obj = new stdclass;
$obj->foo = 'bar';
$_SESSION['myObject'] = $obj;

//or
$_SESSION['myObject'] = new stdclass;
$_SESSION['myObject']->foo = 'bar';

// and addressing it:

echo $_SESSION['myObject']->foo;

the only hard rule is that php MUST know about the class to which the object belongs before you start the session. otherwise it does not know how to unserialise it. obviously php knows about the stdclass so we don't need to worry. but take the following example:

Code:
class myClass{
 public $foo;
}
Code:
include_once 'classDef.php';
if(session_id() == '') session_start();
$myClass = new myClass;
$myClass->foo = 'bar';
$_SESSION['myClass'] = $myClass;
session_write_close();

Code:
if(session_id() == '') session_start();
echo $_SESSION['myClass']->foo; //error

Code:
include_once 'classDef.php';
if(session_id() == '') session_start();
echo $_SESSION['myClass']->foo; //no error.

you can happily involve sessions in loops

Code:
if(session_id() == '') session_start();
for($i = 0; $i<5; $i++) $_SESSION['myRandomCounter'][] = $i;

print_r($_SESSION['myRandomCounter']);
 
Thanks, clear on $_SESSION. On the database link, I am a bit confused since PHP supports both procedural and OO programming.
Based on my experience with perl, and for something that is essentially a straightforward procedural web page , I decided that at least at first I will stick to the procedural style here. Hence I am not sure what $mysqli 'object' means in that setting. In procedural terms this would be something like a C struct or perl hash. In such languages you pass a pointer/reference to the struct/hash. I assume PHP has no passing of pointers/references. Is that correct?
 
When you use mysqli_connect it returns an object or boolean false. Essentially identical to a similar call to a mysqli constructor.

The procedural functions are just wrappers for the class methods. That is why you have to pass the mysqli object to each function as the first argument.

So in this case $mysqli is not a resource handle (as would be returned from mysql_connect) but an object which incorporates a public property which holds the resource handle for the database connection. That's why you may not be able to store it in a session variable (although it is possible that the mysqli class will automatically reconnect if the resource handle 'goes away'); not worth testing/trying though as storing a standard object like mysqli in a per session file would be horrendously inefficient.
 
I assume PHP has no passing of pointers/references. Is that correct?

yes - it does have something equivalent.

variables can be passed by reference to functions and class methods by using the ampersand. this is not quite the same as a C pointer (in that I have no idea whether the memory mapping changes) but has more or less equivalency from a practical viewpoint.

the doubt I expressed above relates mainly to the fact that php is loosely typed. you can change a variable type simply by reassigning it mid-script. and if you change the type of a variable passed by reference to a function, then the variable will equally have changed within the global scope (of course). So it cannot really be quite the same as a pointer to a memory space. but at the abstracted level of the variable and its content, they are equivalent.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top