Been struggling to make some simple code work, but face a problem with the global/local reach of one variable.
Here is the code I try to get to work. This code is contained in a PHP file called by an AJAX GET procedure from Javascript. None of the GET variables appears in the below chunks of code.
$location = "./Treewindow/tree_structure.xml";
function openXML($url) {
if (file_exists($url)) {
$xml = simplexml_load_file($url);
}
else {
echo("Failed to open XML at ".$url);
exit;
}
}
function cubicleAvailableSpace() {
openXML($location);
}
When I call the last function:
cubicleAvailableSpace();
I get:
Failed to open XML at
Why is the variable $location not recognized in the function cubicleAvailableSpace()?! I thought it would be considered as "visible" from all functions within this PHP code...
Now, I am sure this is easy, but I tried the whole afternoon to make this work... Looked all around the place, but could not find any reply which helped me (though there are many such cases in this website)
Of course, when I replace the variable by its actual value ("./Treewindow/tree_structure.xml"), everything works: the XML file is at the right place :-)
Can you help me find what's wrong and make this $location variable visible in both functions ?
Thanks
try this
function cubicleAvailableSpace() {
global $location;
openXML($location);
}
you declared the variable outside the function so it is not readable inside.
Related
I am a newbie in php and rest and I'm trying to understand what is going on in my API when using echo vs return....
I've tried to get down to the simplest possible scenario to isolate an issue of my rest API not returning any value, so here is goes:
I have a test.php file on my server with following content:
<?php
if(function_exists($_GET['t1'])) {
echo $_GET['t1']();
}
else if(function_exists($_GET['t2'])) {
return $_GET['t2']();
}
function test() {
return json_encode("test...");
}
?>
I then make a simple request using, as unique header 'Content-Type: application/json`
https://www.eswys.ch/tmp/test.php?t1=test
https://www.eswys.ch/tmp/test.php?t2=test
And results are, respectively
"test..."
""
I really struggle to understand this, why is my returned value somehow "lost" - is there any explanation to this?!
Returning from a function does not actually render any content to the response. You may have seen people returning data in different frameworks but the framework is actually echoing the data for you behind the scenes.
return assigns a value to a function call (like a variable) and echo is simply output to the html page or possibly a terminal window.
I have two files that are included in my page. Like this:
// mypage.php
include 'script1.php';
include 'script2.php';
I need both of them in first, and then I need to remove one of them, something like this:
if ($var == 'one') {
// inactive script1.php file
} else {
// inactive script2.php file
}
That's hard to explain why I need to inactive one of them, I Just want to know, how can I do that? Is it possible to do unlike include?
The simple answer is no, you can't.
The expanded answer is that when you run PHP, it makes two passes. The first pass compiles the PHP into machine code. This is where includes are added. The second pass is to execute the code from the first pass. Since the compilation pass is where the include was done, there is no way to remove it at runtime.
Since you're having a function collision, here's how to get around that using objects(classes)
class Bob {
public static function samename($args) {
}
}
class Fred {
public static function samename($args) {
}
}
Note that both classes have the samename() function but they live within a different class so there's no collision. Because they are static you can call them like so
Bob::samename($somearghere);
Fred::samename($somearghere);
If you need just the output of either file you could do this
ob_start();
include('file1.php');
$file1 = ob_get_contents();
ob_start();
include('file2.php');
$file2 = ob_get_contents();
Then later if you need to call them
if ($var == 'one') {
echo $file2;
} else {
echo $file1;
}
Your only option is something like this:
if ($var == 'one') {
include('script2.php');
} else {
include('script1.php');
}
You can't 'remove' code, you can only choose to not include/execute it in the first place.
As by your comments you said its because of duplicated function names, i'm assuming you use both files elsewhere separately, but what your trying to achieve now is to merge these files together for a different reason (both files have functions/variables, etc that you need)
If your first file had a function like so my_function:
my_function() {
// code here
}
and your second file also had the same named function you can wrap an if statement around it to exclude it:
if (!function_exists('my_function')) {
my_function() {
// code here
}
}
This way the second file's function wont be available when merging the two files together but using file separately both functions will be available.
For the sake of providing options for others that come here, some solutions I've used myself on occasion...
If the files you're including, you're including for some function with a return value or some execution that doesn't need to be displayed on the page (such as mailing stuff out), and let's say you can't alter either of the target files (let's say they're somebody else's code or part of some highly integrated other piece of software that you really don't want to untangle).
A solution is to create a quick and dirty restful interface for both files to pull from them what you need from them, and then call that interface with your program, effectively bypassing the need to include them.
A worse method but if your situation is truly desperate, and is truly the route of last resort, and will only work in some cases (for example, will break on namespacing)...
$bad_idea = file_get_contents("foo.php");
eval($bad_idea);
unset($bad_idea);
Again, note, this is an option of last resort.
I'm trying to use PHP variables into echoed file, and couldn't get where is a trouble at first using that script:
$head = new mod_head("head.php");
$id="ASDSSgdfsfsdfS";
echo $head;
mod_head class:
class mod_head
{
private $out="";
function __construct($arg)
{
$this->out=$this->parts($arg);
}
public function __toString()
{
return $this->out;
}
private function parts($file)
{
return fread(#fopen(PATH . "parts/".$file, 'r'), filesize(PATH . "parts/".$file));
}
}
and the file is "head.php"
<h1><center style="background:orange; border-radius:15px;">LOGO</center></h1>
<br><?php print_r($id)?>
<div>BANNER <div>$id <?php echo $id ;?></div></div>
i dont want to create global vars, why it doest echo $id var?
First, you're going to need to parse the file, not just read it. The second problem you'll have is a scope issue. $id is outside of the scope of the parts() function. In order to return the contents of the required file instead of just printing it I've used the output control functions
Try changing your parts function to this:
private function parts($file)
{
ob_start();
require(PATH . "parts/".$file);
$output = ob_get_contents();
ob_end_clean();
return $output;
}
To fix the scope issue try changing $id="ASDSSgdfsfsdfS"; to $head->id = "ASDSSgdfsfsdfS";, then change head.php to be the following:
<h1><center style="background:orange; border-radius:15px;">LOGO</center></h1>
<br><?php print_r($this->id)?>
<div>BANNER <div>$id <?php echo $this->id ;?></div></div>
Simply reading a file with fread will not parse any PHP contained inside. Perhaps you are looking for something like:
http://php.net/manual/en/function.require.php
Using require() is basically like copying and pasting the required file directly where your require() statement is. This means that the required file would only be able to use variables that are within the scope of where the require() statement is.
Because you are reading the contents of head.php and echoing them verbatim; nowhere do you make PHP compile and run that file as code. You could do that using include('head.php'), but that would not work blindly because you also have to make sure that $id is in scope at the point you do the include.
However that's not as easy as it sounds because it is not possible to automatically "pack the whole local scope" for later use because automatically implies code inside a function, and the very act of calling that function causes the scope to change.
My thought is that you are probably using mod_head is passing in a php file so it can be used as a view, right?
if thats the case, usually there is also a way to include a variable so that way it exists in the other file, head.php.. since there isn't one, you'd need to create a method for that. and then make that fread an include or require instead.
If not, and you're simply loading the file, the other comments about fread not parsing is totally correct and you will not be able to simply access $id from the other file.
Alright, so a content page uses this:
$tab = "Friends";
$title = "User Profile";
include '(the header file, with nav)';
And the header page has the code:
if ($tab == "Friends") {
echo '<li id="current">';
} else {
echo '<li>';
}
The problem is, that the if $tab == Friends condition is never activated, and no other variables are carried from the the content page, to the header page.
Does anyone know what I'm doing wrong?
Update:
Alright, the problem seemed to disappear when I used ../scripts/filename.php, and only occurred when I used a full URL?
Any ideas why?
When you include a full URL, you're not including the PHP script -- you're including the HTML it generates. It's just like you went to http://wherever.your.url.goes, but it's done by the server instead of the browser. The script runs in a whole separate process, caused by a separate request from the server to itself, and none of the $variables are shared between the two.
Short version: When you include http://wherever.your.url.goes, $tab will always be blank. If you include the actual file name, the variable will be shared.
Your code as posted should work. How are you actually including that file? Does that happen inside a function? Then you need to use the global statement for it to work. Example:
File 1:
function my_include($file) {
global $tab; // <-- add this
include '/some/path/' . $file;
}
$tab = 'Friends';
my_inlcude('file_2.php');
File 2:
if ($tab == 'Friends') { ... }
Now you see why it's awful practice to post some stubs and skeches instead of the real code
Try to think, Your question is not a rocket science. Include is like copy-pasting code in place of include operator. Go load your inclided URL in browser, copy resulting code and paste it into your first file and see.
I have the following dilemma. I have a complex CMS, and this CMS is to be themed by a graphic designer. The templates are plain HTML, with several nested inclusions. I'd like to make it easier for the designer to locate the file to be modified, by looking at the HTML of the page.
What I thought in the first place was to build something stupid like this:
function customInclude($what) {
print("<!-- Including $what -->");
include($what);
print("<!-- End of $what -->");
}
but, guess what? Variables obviously come out of scope in the included file :-) I can't declare them as global or as parameters, as I don't know how they are called and how many are there.
Is there any possibility to implement some kind of "macro expansion" in PHP? An alternative way to call it: I'd like to modify each call of the modify function, in an aspect-oriented style.
I have thought about eval(), is it the only way? Will it have a big impact on performance?
I know this is an old question, but I stumbled upon it and it reminds me of something I used to do it too.
how about if you create the function using a very weird variable?
<?php
function customInclude($___what___) {
echo '<!-- Including '.$___what___.' -->';
include($what);
echo '<!-- End of '.$___what___.' -->';
}
?>
I usually suggest to add a possible variable to display those tags only when necessary, you do not want other people to know...
<?php
function __printIncludeInfo($info, $dump = false){
//print only if the URL contains the parameter ?pii
//You can modify it to print only if coming from a certain IP
if(isset($_GET['pii'])){
if($dump){
var_dump($info);
} else {
echo $info;
}
}
}
function customInclude($___what___) {
__printIncludeInfo('<!-- Including '.$___what___.' -->');
include($what);
__printIncludeInfo('<!-- End of '.$___what___.' -->');
}
?>
in this way you can use the function to print any other information that you need
Not sure if I entirely understand the question, but if you're just trying to make life easier for the designer by showing them the underlying filename of the included file, then you can probably just use this within the template files:
echo '<!-- Start of '.__FILE__.' -->';
....content...
echo '<!-- End of '.__FILE__.' -->';
__FILE__ is just one of several Magic Constants.
Also there's the get_included_files() function that returns an array of all the included files, which might be of use (you could output a list of all the included files with 'tpl' in their name for example).
This is my 100% harcoded solution to custom include problem. It's about using a global var to point the next include filename and then include my custom proxy-include-file (wich replace your custom proxy-include-function)
1 - Add this code to a global include (wherever your customInclude function is defined)
$GLOBALS['next_include'] = "";
$GLOBALS['next_include_is_once'] = false;
function next_include($include_file) {
$GLOBALS['next_include_is_once'] = false;
$GLOBALS['next_include'] = $include_file;
}
function next_include_once($include_file) {
$GLOBALS['next_include_is_once'] = true;
$GLOBALS['next_include'] = $include_file;
}
2 - Create some include proxy-include-file, by example "debug_include.php"
<?php
if(empty($GLOBALS['next_include'])) die("Includes Problem");
// Pre-include code
// ....
if($GLOBALS['next_include_is_once']) {
include_once($GLOBALS['next_include']);
} else {
include($GLOBALS['next_include']);
}
// Post-include code
// ....
$GLOBALS['next_include'] = "";
3 - Perform a search and replace in all your files: (except debug_include.php)
search: 'include((.*));' as a reg.exp
replace with: '{next_include($1);include('debug_include.php');}'
and
search: 'include_once((.*)); as a reg.exp
replace with: '{next_include_once($1);include('debug_include.php');}'
Maybe you should need another search-and-replaces if you have some non-standard includes like
include (.... include (.... include (....
I think you can find some better search-and-replace patterns, but I'm not a regular expression user so I did it the hard way.
You should definitely use objects, namespaces and MVC model. Otherwise there is no pure and clean solution to your problem. And please, don't use eval, it's evil.