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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PHP Require in Ajax Requested File

Status
Not open for further replies.

menkes

Programmer
Nov 18, 2002
47
US
I have three files: container.php, content.php, and action.php. All three files use a "require" statement to bring in some global data.

- container.php loads -> all good
- container.php requests data via Ajax from content.php ->all good
- container.php sends form data to action.php via Ajax -> BUT action.php fails as it does not have global values from the required file, specifically a database connection.

Both container.php and content.php need and correctly use the same required file. Container.php is correctly sending the form data to action.php...I can just echo it right back.

Why does action.php not correctly load the data from the required file? What am I missing?

- Scott

- Scott
 
Can we see the files?

If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
 
the answer to your question is to do with access protocols. when you are requiring a file without specifying a protocol the default is to use file:///. in doing so the php is not parsed by the web server, but the file is ingested by the current php process and parsed in accordance with the then current scope and configuration.

by contrast, if you are attaching a file across ajax then you are using http:// which will typically be processed by the webserver and will be a completely separate process of script execution to the one instantiated through the file:/// process. of course there is no sharing of variable scope (this would an horrendous security loophole, not to mention requiring a magical bridge between script execution processes.

if you are running scripts from php, i cannot see why you need to use ajax or any other non file:/// based method to 'include' files to the current scope. i also don't really understand how you are using ajax on the server unless you are running an ASP script and this question has nothing to do with php. or perhaps you are using jsp or jaxer? who knows. anyway, there are _much_ better ways of fixing variable scope issues but to help you, you need to come clean as to what you are doing, and why you are doing it together with what your aims are. oh, and as johnwm says, some code would be nice.
 
Fair enough. I have stripped non-relevant code such as validation and layout.

container.php
Code:
<?php
	require("../include/intranet.inc.php"); 

	$refer		= $_REQUEST[refer];	

	$client 	= $_REQUEST[client];
	$appl 		= $_REQUEST[appl];
	

?>	

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' '[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>[/URL]
<html xmlns='[URL unfurl="true"]http://www.w3.org/1999/xhtml'>[/URL]

    <head title='Add an Application'>
		<LINK HREF='clientAppl.css' REL='stylesheet' TYPE='text/css' />
			
		<script type='text/javascript' src='../include/jquery.js'></script>
		<script type='text/javascript' src='../include/jquery.highlight.js'></script>
		<script type='text/javascript' src='../include/jquery.validate.js'></script>
		<script type='text/javascript' src='../include/jquery.form.js'></script>
		<script type="text/javascript" src="../include/jquery.textarearesizer.js"></script>
		<script type="text/javascript" src="../include/jquery.tools.min.js"></script>
		
		<script type='text/javascript'>
				
			$(document).ready(function(){
				        
			});
			
				
            jQuery(function($) {   
                $('#form_container').load('layout.php', { 'client': <?php echo "'$client'" ?>, 'appl': <?php echo "'$appl'" ?> });   

                $().ajaxSend(function(r,s){   
                    $('#loading').show();   
                });   

                $().ajaxStop(function(r,s){   
                    $('#loading').fadeOut('fast');
                    $('#loading').remove();   
    		        $('form').highlight();
    				$('textarea.resizable:not(.processed)').TextAreaResizer();
    				
        			$('a').click( function() {
        			   var s1 = $('#stock1').val();
        			   var s2 = $('#stock2').val();
        			   var s3 = $('#stock3').val();
        			   var s4 = $('#stock4').val();
        			   var s5 = $('#stock5').val();
        
        			   var param = '?stk1='+s1+'&stk2='+s2+'&stk3='+s3+'&stk4='+s4+'&stk5='+s5;
        			   $('a').attr('href', 'clientEnsemble.php'+param);
        			    
        			});
        			
    				// if the function argument is given to overlay,
	                // it is assumed to be the onBeforeLoad event listener
	                $("a[rel]").overlay({
		                expose: '#c0c0c0',
                		effect: 'apple',

		                onBeforeLoad: function() {
			                // grab wrapper element inside content
                			var wrap = this.getContent().find("div.wrap");

			                // load only for the first time it is opened
			                if (wrap.is(":empty")) {
				                wrap.load(this.getTrigger().attr("href"));
			                }
		                }

	                });

                });   				

				var v = $('#frm').validate({
		                    rules: {
			                    applCode: {
			                        required: true,
			                        maxlength: 1
			                    },
			                    applName: {
			                        required: true,
			                        minlength: 5
			                    },
			                    svDays: {
				                    required: '#sv:checked',
				                    digits: true
		                        }
		                    },
		                    messages: {
			                    applCode: {
				                    required: 'Please enter an Application Code',
				                    maxlength: 'Application code is a single character'
			                    },
			                    applName: {
				                    required: 'Please enter an Application Name',
				                    maxlength: 'Please use a name with at least 5 characters'
			                    },
			                    svDays: {
				                    required: 'If S&V selected you must enter Hold months',
				                    digits: 'Only use numbers for hold days'
			                    }
		                    },
		                    submitHandler: function(form) {
				                $(form).ajaxSubmit({
					                target: "#form_results"
				                });
			                }
				        });

            });   

		</script>
			
</head>

<?php
echo "

<body id='main_body'>
	<img id='top' src='../images/form_top.png'>
    <div id='loading'>
        <img src='../images/loader_indicator.gif' alt='Loading, please wait...'><br>
        Loading Application...
    </div>

    <form id='frm' class='dpForm' name='frmApplication' method='POST' action='submit.php'>
        <div id='form_container'></div>
	</form>	
	<img id='bottom' src='../images/form_bottom.png'>
	</div>

    <div class='overlay' id='overlay'>
	    <div class='wrap'></div>
    </div>
    
</body>
</html>

";
	
?>

As you can see this is the requested url which then loads layout.php into <div id='form_container'>. Here is the abbreviated version of layout.php:

Code:
<?php
	require("../include/intranet.inc.php"); 

	$client 	= $_REQUEST[client];
	$appl 		= $_REQUEST[appl];

//**********************************************************************************//
//                                                                                  //
// Section to retrieve the current data if specific application requested           //
//                                                                                  //
//**********************************************************************************//


	// This query can ONLY occur if require above worked correctly - which it does


	    $sql = "SELECT *
			 	FROM someTable
			 	WHERE fldA = $client 
		 	 	AND   fldB = $appl 
		";

		$result = $db->Query($sql);
		$row = $db->FetchRow($result,3);


// ****************************************************************************
// Result set manipulated and placed in local vars 
// Layout created - not relevant to issue at hand
// ****************************************************************************    


?>

You can see the require at the top of the file. That required file contains all the database, security, global vars, and other goodies. The only way layout.php can return correct info is if the required file loads and the variables are available.

And finally, when the form is submitted submit.php is called after validation.

submit.php
Code:
<?php
	require("../include/intranet.inc.php"); 

    // Verify the application code is not already in use for this client
    $client = $_POST[client];
    $appl_code = $_POST[applCode];
    
    // Query below would ONLY occur if require above worked correctly - it does not    
    $sql = "SELECT COUNT(*) AS appCount
                FROM someTable
                WHERE fldA = $client
                AND fldB = '$appl_code'
    ";
    $res = $db->Query($sql);
	$row = $db->$db->FetchRow($res,3);
    
    if($row[appCount] > 0)
    {
        // This code already exists
        $msg = "Save failed! The application code $appl_code already exists.";
    } else {
        $msg = "Found $row[appCount] using $client and $appl_code";
    }

// ******************************************************
// Remainder of file is validation, inserts and updates
// ******************************************************
?>

The call works, and if I simply echo a result back it does what it should: namely display the result in the correct div in container.php. However, once I try to access any variables from the required file, such as my db connection, I get: "PHP Fatal error: Call to a member function on a non-object in path/submit.php on line 14". Line 14 is trying to use the database connection.

So, there you have it.

Why this way? Probably because I am a masochist. But, container = template, layout = design guys, submit = business logic.

Is this a javascript\ajax\jquery issue? No. Those are all behaving as they should.

Appreciate any constructive thoughts or advice. Thanks,


- Scott
 
i am slightly confounded that on the one hand the 'call' to submit.php 'works' and on the other accessing variables does not. since the variable $db is present in the submit.php script, surely what you say is impossible? for it to work the variable $db must be in scope?

in any event, the error is straightforward - the databse abstraction object that you are trying to address in $db is not an object. which means that something in your instantiation script has bust or, more likely, the script that you intend is somehow not being included. perhaps this is a directory schema issue. personally i look to avoid this by having all client interaction commence with a single file (index.php) which then despatches the script execution to other files as needed. all 'includes' are done using an absolute url with respect to index.php

Code:
$dir = realpath(dirname(__FILE__));
define('B', $dir .'/');
//despatch code
include files are then used like this
Code:
include B . 'subdirectory/classes/myclass.php';

i note separately that you are not correctly enquoting array keys and are not escaping user data before using it in your scripts. both are bad practice
 
Thanks for the responses.

The required file was pulling in just fine. The database abstraction was not creating a new object since the object had already been created in layout.php.

The solution was to simply create a database object unique to submit.php and it worked just fine.

As for the formatting and syntax: thank you. I am reworking some very old code and have not completed the cleanup yet. I know I needed to get to this, but advice is always welcome.

- Scott

- Scott
 
That is strange. Your code does not show layout.php being included by submit.php. And of course each Ajax connection will be treated as a separate php script thread. And even if layout.php had created a database object that should not prevent submit.php from recreating and/or reusing the object.
The issue lies somewhere else. However if you are happy that it has gone away, so be it. Oh and I was advising on format; escaping data protects against security vulnerability exploits, in this case SQL injection attacks.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top