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!

trying to understand classes' variable scope 1

Status
Not open for further replies.

southbeach

Programmer
Jan 22, 2008
879
0
0
US
OK, I have the following:
index.php which includes a script where a class is defined. Class is called appVars and it is initialized as $appVars=new appVars.

As a condition, if user has not logged on, he/she will be taken to a log on form. index.php also includes other scripts where UDFs are defined and are used for opening databases and executing queries.

One of the UDF is used by XAJAX to validate user ID and Password via AJAX. So, the login form calls JS which in turn calls XAJAX PHP function passing user ID and password as parameters.

As part of the index.php script, if $appVar->appTitle has not been set, the class instance is declared and initiated. The UDF where user ID is validated attempts to use variables which are set within the class: $appVars->dbName, $appVars->dbUser, $appVars->dbPwd, $appVars->dbServer, etc.

The problem is that they are all blank ...

I really thought that once an instance of a class is set, all variables set through this class are basically global and can be referenced as $class_instance->variable

Where am I mistaken? What am I doing wrong?

Thank you all in advance for your assistance!
 
Here is my class
Code:
class appVars {
	public $dbName;		// Database Name
	public $dbUser;		// Database User
	public $dbServ;		// Database Server
	public $dbPasw;		// Database Password
	public $appTitle;	// Application Title

	function initAppVars() {
		$this->dbName = 'demo';
		$this->dbUser = 'root';
		$this->dbServ = 'localhost';
		$this->dbPasw = '';
		$this->appTitle = 'Welcome!';
	}
}

index.php invokes the class as follows
Code:
// Lets initialize the Application Variables CLASS and set variables to default.
// Notice that we are doing this ONLY if it hasn't been done.  Lets make sure we
// work with a single instance.
if (!isset($appVars->appTitle)) { $appVars = new appVars; $appVars->initAppVars(); }

As the user attempts to login, XAJAX calls
Code:
function Open_DB($db) {
// Lets open the database as requested.  Notice that no password is used here.
// If you have set your MySQL to use password, you must add it here.

// Connect to MySQL Server
$dbserver = mysql_connect($appVars->dbServ,$appVars->dbUser,$appVars->dbPasw);

// Select database
mysql_select_db($db);

}

from a UDF
Code:
// This function is called by JS IsUserValid().  Here is where we will validate
// user credentials.
function IsUserValid($id,$pwd) {
	// Open Database.  Global database is used to store data common to all databases
	// in the system.  In this case, we will consider the user table as a global table.
	// Within the user profile itself, we will identify the database user is authorized
	// to work with.

	OpenDB($appVars->dbName);
	$sql = 'SELECT * FROM `users` WHERE usrCode = "' . $id . '" AND usrPWD = "' . $pwd . '" LIMIT 1;';
	
	$query = DoQuery($sql); $recs = mysql_num_rows($query);
	$objResponse = new xajaxResponse();
	if ($recs > 0) {
		$row = mysql_fetch_assoc($query);
		$_SESSION['_userID'] = $id;
		$_SESSION['_userFName'] = $row['usrFName'];
		$_SESSION['_userLName'] = $row['usrLName'];
		$_SESSION['_userDB'] = $row['usrDB'];
		$objResponse->script("document.getElementById('loginLayer').style.display='none';");
		$objResponse->script("window.reload(true);");
	} else {
		$_SESSION['_userID'] = '';
		$_SESSION['_userFName'] = '';
		$_SESSION['_userLName'] = '';
		$_SESSION['_userDB'] = '';
		$objResponse->assign("loginmessage","innerHTML","Invalid User ID & Password.  Please try again!");
	}
	return $objResponse;
}


I added code to write to a file what the values are and they are blank ... I had var to initialize the variables but changed it to public and still blank.

What say you?

Thanks!
 
$appVars is not in the global scope so will not be available inside the open_db function.
try adding
Code:
global $appVars;
as the first line in the function.
 
Same problem. I hate when something like this happens. I just went through and made sure the $appVars is properly spelled in all instances where referenced.

Any other possible solution?

I am just trying to start using classes. I normally use session variables. I would hate to give up on classes this soon.

Thanks,
 
$appVars is just a variable. the normal rules on variable scope apply. to use it in a function it must be brought into the global scope for that function.

and you (obviously) need to make sure that the object is instantiated before referring to it.
 
jpadie,

The object is instantiated within index.php way before any UDF attempts to reference it.

Remember:
- index.php checks if user is logged on.
- if user is not logged on, user is given is log in form.
- once user submits form, JS calls XAJAX registered function
to validate user credentials.
- I have a script named com/procs.php which is included within
index.php
- inc/proces.php is where the UDF and the CLASS are found
- The UDF named IsUserValid is the one used by XAJAX
- I also have another script named com/db.php
- db.php is a set of UDF strictly for MySQL related calls
- UDF IsUserValid calls upon Open_DB() which is within
db.php
- I added global $appVars in both IsuserValid and in
Open_DB
- None of my UDF show any values for $appVars->objects

That said, if I echo $appVars->objects within the index.php page while it is initially loaded, I can see set values.

What else can I or must I do?

Thanks!
 
what does the javascript look like that creates the call to what you're calling the xajax function?
 
NOTE: This post is a bit long - I have included all scripts.

I use XAJAX
- the WWW link said:

As per their website:
The xajax class generates the xajax Javascript for your page including the Javascript wrappers for the PHP functions that you want to call from your page. It also handles processing and executing the command messages in the XML responses sent back to your page from your PHP functions.

Basically, to use XAJAX
- You include the XAJAX class
- You register PHP functions you intend to call

Here is a sample snippet created by XAJAX
Code:
<script type="text/javascript" charset="UTF-8">
/* <![CDATA[ */
try { if (undefined == xajax.config) xajax.config = {}; } catch (e) { xajax = {}; xajax.config = {}; };
xajax.config.requestURI = "[URL unfurl="true"]http://localhost/phpdev/";[/URL]
xajax.config.statusMessages = false;
xajax.config.waitCursor = true;
xajax.config.version = "xajax 0.5 Beta 4";
xajax.config.legacy = false;
xajax.config.defaultMode = "asynchronous";
xajax.config.defaultMethod = "POST";
/* ]]> */
</script>
<script type="text/javascript" src="xajax/xajax_js/xajax_core.js" charset="UTF-8"></script>
<script type="text/javascript" charset="UTF-8">
/* <![CDATA[ */
window.setTimeout(
 function() {
  var scriptExists = false;
  try { if (xajax.isLoaded) scriptExists = true; }
  catch (e) {}
  if (!scriptExists) {
   alert("Error: the xajax Javascript component could not be included. Perhaps the URL is incorrect?\nURL: xajax/xajax_js/xajax_core.js");
  }
 }, 2000);
/* ]]> */
</script>

<script type='text/javascript' charset='UTF-8'>
/* <![CDATA[ */
xajax_IsUserValid = function() { return xajax.request( { xjxfun: 'IsUserValid' }, { parameters: arguments } ); };
/* ]]> */

</script>

If I have UDF named IsUserValid defined within my PHP scripts, once registered with XAJAX I can invoice this function by prefixing xajax_ to the registered function name.

In my case, I can executing xajax_IsUserValid(id,pwd) as a JS function which in turn will execute PHP UDF IsUserValid.

My com/procs.php script
Code:
<?PHP

class appVars {
	public $dbName = '';	// Database Name
	public $dbUser;			// Database User
	public $dbServ;			// Database Server
	public $dbPasw;			// Database Password
	public $appTitle;		// Application Title

	function initAppVars() {
		$this->dbName = 'phpdev';
		$this->dbUser = 'root';
		$this->dbServ = 'localhost';
		$this->dbPasw = '';
		$this->appTitle = 'Welcome!';
	}
}

// This function is called by JS IsUserValid().  Here is where we will validate
// user credentials.
function IsUserValid($id,$pwd) {

public $appVars;

// Open Database.  
// Within the user profile itself, we will identify the
// database user is authorized to work with.

	Open_DB($appVars->dbName);
	$sql = 'SELECT * FROM `users` WHERE usrCode = "' . $id . '" AND usrPWD = "' . $pwd . '" LIMIT 1;';

	$ScriptName=$_SERVER['PHP_SELF'].': ';
	$LogFile=fopen("c:/temp/joseweb.log","a+");
	if($LogFile) { $LogTxt=fputs($LogFile,$ScriptName.$sql."\r\n"); }

	$query = DoQuery($sql); $recs = mysql_num_rows($query);
	$objResponse = new xajaxResponse();
	if ($recs > 0) {
		$row = mysql_fetch_assoc($query);
		$_SESSION['_userID'] = $id;
		$_SESSION['_userFName'] = $row['usrFName'];
		$_SESSION['_userLName'] = $row['usrLName'];
		$_SESSION['_userDB'] = $row['usrDB'];
		$objResponse->script("document.getElementById('loginLayer').style.display='none';");
		$objResponse->script("window.reload(true);");
	} else {
		$_SESSION['_userID'] = '';
		$_SESSION['_userFName'] = '';
		$_SESSION['_userLName'] = '';
		$_SESSION['_userDB'] = '';
		$objResponse->assign("loginmessage","innerHTML","Invalid User ID &amp; Password.  Please try again!");
	}
	return $objResponse;
}

?>

The db.php script
Code:
<?PHP

function Open_DB($db) {

public $appVars;

// Lets open the database as requested.
$dbserver = mysql_connect($appVars->dbServ,$appVars->dbUser,$appVars->dbPasw);

// Select database
mysql_select_db($db);

}

function DoQuery($sql) 
{ 

$Results = mysql_query($sql) or die (mysql_error());	// Run SQL Query

return $Results; 										// Return Query Results
}

?>

The index.php script
Code:
<?PHP
session_start();					// Make sure session variables are accessible within this script
include("com/procs.php");			// Include all common procedures
include("com/db.php");				// Include dabase control routines or UDFs

require("xajax/xajax_core/xajax.inc.php");
$xajax = new xajax();
$xajax->registerFunction("IsUserValid");
$xajax->processRequest();

// Lets initialize the Application Variables CLASS and set variables to default.
// Notice that we are doing this ONLY if it hasn't been done.  Lets make sure we
// work with a single instance.
if (!isset($appVars->appTitle)) { $appVars = new appVars; $appVars->initAppVars(); }

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "[URL unfurl="true"]http://www.w3.org/TR/html4/strict.dtd">[/URL]
<html>
<head>
<?PHP 
include("inc/head.php"); 			// Include head script. Setup CSS and JS links/external files

// Lets make sue we do not get a JS error.  Menus are only load ready if user has already logged on.
if (isset($_SESSION['_userID'])) echo '
<script language="JavaScript" type="text/JavaScript">
//SuckerTree Horizontal Menu (Sept 14th, 06)
//By Dynamic Drive: [URL unfurl="true"]http://www.dynamicdrive.com/style/[/URL]

var menuids=["treemenu1"] //Enter id(s) of SuckerTree UL menus, separated by commas

function buildsubmenus_horizontal(){
for (var i=0; i<menuids.length; i++){
  var ultags=document.getElementById(menuids[i]).getElementsByTagName("ul")
    for (var t=0; t<ultags.length; t++){
		if (ultags[t].parentNode.parentNode.id==menuids[i]){ //if this is a first level submenu
			ultags[t].style.top=ultags[t].parentNode.offsetHeight+"px" //dynamically position first level submenus to be height of main menu item
			ultags[t].parentNode.getElementsByTagName("a")[0].className="mainfoldericon"
		}
		else{ //else if this is a sub level menu (ul)
		  ultags[t].style.left=ultags[t-1].getElementsByTagName("a")[0].offsetWidth+"px" //position menu to the right of menu item that activated it
    	ultags[t].parentNode.getElementsByTagName("a")[0].className="subfoldericon"
		}
    ultags[t].parentNode.onmouseover=function(){
    this.getElementsByTagName("ul")[0].style.visibility="visible"
    }
    ultags[t].parentNode.onmouseout=function(){
    this.getElementsByTagName("ul")[0].style.visibility="hidden"
    }
    }
  }
}

if (window.addEventListener)
window.addEventListener("load", buildsubmenus_horizontal, false)
else if (window.attachEvent)
window.attachEvent("onload", buildsubmenus_horizontal)
</script>';

// Lets load the JS needed as declared above
$xajax->printJavascript('xajax'); 

?>

<script language="JavaScript" type="text/JavaScript">
<!--
function MM_reloadPage(init) {  //reloads the window if Nav4 resized
  if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
    document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
  else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
}
MM_reloadPage(true);
//-->
</script>
</head>
<body>

<div id="banner" style="position:absolute; left:0px; top:1px; width:835px; height:76px; z-index:1">
	<?PHP 
	// Give user option to log out if already logged in
	if (isset($_SESSION['_userID'])) echo '<img src="img/logout.gif" id="logouticon" title="Log me out!"><label for="logouticon" class="label" lang="en">Log Me Out!</label>'; 
	?>
</div>
<div id="menus" float: left; style="position:absolute; left:0px; top:78px; width:1000px; height:30px; z-index:10">
<?PHP 
// If user has logged on, then Load/run code for navigation menus
if (isset($_SESSION['_userID'])) include("inc/menus.php");
?>
</div>
<!--- This is the container where all of the content goes.  Basically, this is the body of the form/page --->
<div id="container" style="position:absolute; left:0px; top:108px; float: left; width:1000px; height:100%; z-index:3">
<?PHP
// If user has not logged on, then give him a logon form
if (!isset($_SESSION['_userID'])) echo '
<div id="loginLayer" style="position:absolute; left:260px; top:75px; z-index:4;">
<form name="login" id="login" action="#" method="post">
	<table id="loginTable" border="0" cellpadding="0" cellspacing="0">
		<tr>
			<td>
				<label for="_userID" lang="en">User ID</label><br /><input name="_userID" id="_userID" type="text" size="15" maxlength="15" class="login" /><br />
				<label for="_userPWD" dir="ltr" lang="en">User Password</label><br /><input name="_userPWD" id="_userPWD" type="password" size="15" maxlength="15" class="login" /><br />
				<p><input type="button" align="middle" value="LOGIN" onClick="IsUserValid(); return false;" /></p>
				<p id="loginmessage">&nbsp;</p>
			</td>
		</tr>
	</table>
</form>
</div>';
?>
</div>
</body>
<?PHP
// If user has not logged on, then place cursor on User ID field
if (!isset($_SESSION['_userID'])) echo '
<script type="text/javascript">
	document.login._userID.focus();
</script>
';
?>
</html>

Hope this gives you the material needed to help me identify why am I having such problem.

Thanks!
 
OK - I think I found the answer to my problem. I found
Objects and Sessions

You may or may not be aware that you can maintain data between the execution of one script and another by using PHP's session capability. It is also possible to save an object's properties in this session data so that it can be reinstated by the next script within the same session. You can save an object's properties by using the serialize() command as follows:

include 'foo.class.inc';
$dbobject = new Foo;
...
...
$_SESSION['dbobject'] = serialize($dbobject);

In a subsequent script you can reinstate the object to exactly the same condition by using the unserialize() command like this:

include 'foo.class.inc';
if (isset($_SESSION['dbobject'])) {
$dbobject = unserialize($_SESSION['dbobject']);
} else {
$dbobject = new Foo;
} // if

This and more about objects can be read here
Code:
[URL unfurl="true"]http://www.tonymarston.net/php-mysql/databaseobjects.html[/URL]

I will give this try and see what happens!
 
Well, using global $appVars did not help and it appears that using the serialize() and unserialize() approach does.

One thing I do not like is that to reference the object outside the class methods, I have to unserialize the session variable.

 
What's up with these lines in your db.php:
Code:
function Open_DB($db) {

public $appVars;
Declaring a variable public inside a function? That doesn't make any sense. In fact, it's not even legal - you should be getting a parse error on that line. If not, you need to turn up your error reporting level. And I see you're also doing it in com/procs.php.

Clearly you're confused about the visibility declaration keywords. The public keyword is used to control accessability of class member variables. It has nothing to do with variable scope and when used in the context of a regular function, it has no meaning. As jpadie suggested, you probably meant to use global in those places, not public.

As for your particular problem, I suggest you take a closer look at the xajax documentation. Note that it says that the code after processRequests() is only called on the initial page load. So, basically, your problem is that you're creating your $appVars variable after you call processRequests(). It gets created on the first page load, but on subsequent AJAX requests, it never gets created at all, so your functions can't access it. That's also why it works when you put it in $_SESSION - because session variable survive across HTTP requests.
 
personally i wouldn't go putting objects in session variables unless you have a really good reason to do so. and yes, if you do put the object into a session variable there is an implicit serialisation that takes place and, to unserialise the object implicitly, php will need information about the class before session_start() is called.

so
Code:
session_start();
include 'myclass.php';

will not work, but

Code:
include 'myclass.php';
session_start();
will work ok.

i would also recommend that you abandon xajax and other easy-ajax libs until you understand the basic mechanics of what's going on, more fluently. code the javascript and the php yourself. i tend to have a separate file that acts as the ajax server and contains the relevant functions that i call externally. like a web despatcher but for ajax calls instead. keeps life simple.
 
AdAhacker,

Thanks for highlighting those points for me ... makes a lot of sense. As per the use of 'public' in lieu of 'glogal', it was typo made just as I posted my code here. I have been going back and forth so much that I quickly added the lines of code after having removed them ... I had just finished reading some articles on php.net where they talked about the use of public variables and functions and had also replaced var for public within the class. In short, that public stuck in my mind!

jpadie,

I understand your point about knowing what you are dealing with to better understand its behavior and yielding results. I will take your advise into consideration ... That said, giving up XAJAX may be difficult since it really simplifies things a lot, specially for a person like myself that is trying to learn so many things at once. Not advocating that shortcuts are the way to go, but if a tool is available and such tool provides all that you need, perhaps it is not a bad thing to use it.

Thanks!


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top