If I run the following PHP code, I get 123. I don't understand the logic behind it. What I think is when I call the function each time it suppose to output 1. So the output should be like 111.
function keep_track() {
STATIC $count = 0;
$count++;
print $count;
}
keep_track();
keep_track();
keep_track();
// output 123
I know that a static variable holds the value even after the function exits but in the above function I am assigning a value in the very first line, yet it still adding +1 with the previous value of $count.
Could you please explain this? (I am sorry if I sound like a stupid.. but I am trying to find out how exactly this happening)
$count is initialized only in first call of function and every time the method is called, it increments $count.
In this link, scroll down to Using static variables for a better understanding.
The code static $count = 0; is executed once upon compilation which is why with each call of your function the value is not overwritten. See the note "Static declarations are resolved in compile-time." at http://www.php.net/manual/en/language.variables.scope.php
Related
I started having a weird behavior with PHP's empty() function. Everything used to work properly, but now it doesn't, and I don't get why.
I have a tbInventory class that represents out products. One record per unit.
That class has a getBootloaderRevision method/property:
public function getBootloaderRevision() {
if (empty($this->cBootloaderRevision)) {
return null;
} else {
return $this->cBootloaderRevision;
}
}
It used to work, but now, the empty() function returns true even if the member has a value. Here is an example:
$prod = new tbInventory($db, 1009);
$test = $prod->cBootloaderRevision;
echo $prod->cBootloaderRevision . "<br>";
echo $test . "<br>";
echo (empty($prod->cBootloaderRevision) ? "1" : "02") . "<br>";
echo (empty($test) ? "1" : "0") . "<br>";
I'm loading an item from my database, an Item I know to have a BootLoader Revision. I declare and load it on the first line, then I put the value of the MEMBER itself straight in a variable. I then echo both the member and the variable to prove they both have the value.
I then echo a 1 or a 0 depending on the result of the empty() function for both the member and the variable. Here is the results:
01.07
01.07
1
0
I'm at a lost here. I do NOT understand why this is happening. I know it used to work, I haven't touched this in over a year. We made an update on the server recently, and it seems to have started acting this way since the server. I was not in charge of the update, but I think they updated both the OS and PHP.
Have you ever seen something like that???
Thank you,
The only thing that would explain this behaviour is if cBootloaderRevision isn't a "physical" property but is being retrieved with the __get magic method, and the class either has no __isset method implemented or that method is returning results inconsistent with __get. The reason is that empty will invoke __isset first, but $prod->cBootloaderRevision will just invoke __get.
See http://php.net/manual/en/language.oop5.overloading.php#object.get.
I wrote a foreach loop and saved on several lines of code. It basically takes all of the $_POST variables and uses their names to create normal php variables.
foreach(array_keys($_POST) as $str)
{
${$str}=mysqli_real_escape_string($connection,trim($_POST["$str"]));
}
It is working as expected, creating variables dynamically.
Now, I wanted to put it inside a custom function so i modified it like this:
function createvariablesfromPOST()
{
foreach(array_keys($_POST) as $str)
{
${$str}=mysqli_real_escape_string($GLOBALS["connection"],trim($_POST["$str"]));
}
return //something;
}
Its not working obviously, because i dont know how to make this function return // something (whatever that thing may be) to the global scope. Whats supposed to be done here?
I cant make the foreach loop return anything, till the loop is complete. Isn't that so?
Please help.
Assigning arbitrary variables supplied by the user could be EXTREMELY DANGEROUS! They can overwrite any of your variables.
The reason it isn't working, is because they aren't in the global scope. You would have to do something like $GLOBALS[$variable] = 'something';
Instead, you should assign the variables to an array so they are isolated from the global scope. i.e. $input[$$var] = $escaped_value;
I was unable to find a similar question on Stackoverflow, although I am sure someone has probably asked this before.
I have a class with methods that may be called several times per page. Each time the method is called I need to make sure the public variables are reset to their defaults, UNLESS they have been set before calling the method.
This cannot be achieved using a simple if condition because there is no way to tell whether the value has been set or is still set from the last method call
I cannot think of a way to achieve this because I cannot call my __construct method (which sets all the default values), as this would overwrite the parsed values. However, I need to reset them to prevent values from the last method call from being parsed.
The obvious answer is to give different names to the public variables and the return variables. I will do this if there is no other option but I like to keep the number of variables to a minimum
It is very hard to explain this in writing so I will update this question with an example of what I mean in code.
UPDATE
An example of where a problem may occur:
<?php
class test{
public $return_array;
public $return_string;
public $return_bool;
function __construct(){
// Set the default values
$this->return_array = false;
$this->return_string = false;
$this->return_bool = false;
}
public function method(){
// ... do something
$array = array('test');
$string = 'test';
$bool = true;
// Only return variables if asked to
$this->return_array = $this->return_array ? $array : NULL;
$this->return_string = $this->return_string ? $string : NULL;
$this->return_bool = $this->return_bool ? $bool : NULL;
return;
}
}
// Initiate the class
$test = new test;
// Call the method the first time with one parameter set
$test->return_array = true;
$test->method();
// Print the result
print_r($test->return_array);
// MOST OBVIOUS ANSWER WOULD BE TO RESET VARIABLES HERE LIKE SO
$test->reset(); // HOWEVER, I DO NOT WANT TO HAVE TO CALL THIS EACH TIME I CALL THE METHOD, HERE LIES MY PROBLEM!
// Call the method again with different parameters
$test->return_string = true;
$test->return_bool = true;
$test->method();
// Print the result
echo $test->return_array;
echo $test->return_bool;
/* The problem lies in the second call of the method because $test->return_array has not been reset to its default value. However, there is no way to reset it without affecting the other variables. */
?>
This is basically a very long winded way of asking whether it is possible to reset a classes variables to their default values, whilst ignoring the ones that have been parsed to the method being called
There are several ways to achieve this but they all bottle down to the same solution. Calling a function after each method that resets the variables within the class. Best way to do this is at the end of each method before the data is returned.
I have a page named ChangeApprovalInfo.php - It has a function called Row_Rendered as follows;
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
}
Echoing $RecordOwner gets me the data I will need for a sql query on another page....
I have another page called ChangeApprovalEdit.php - This page has
<?php include_once "ChangeApprovalinfo.php" ?>
at the top of the file.
ChangeApprovalEdit.php has a function where I need the $RecordOwner variable as defined in ChangedApprovalInfo.php
If I add "echo $RecordOwner" on the ChangeApprovalEdit.php page, I get an error saying it's an unknown variable. My understanding is that I need to "make it global" or some such business. I know very little about PHP and the pages I am editing are long and complex. (to me, at least)
What do I need to do? I know that the information I have provided might not be enough to answer the question. I don't know enough to even know exactly what I need to ask. If more information is needed, I will edit and follow up.
pastebin of the files
ChangeApprovalInfo.php = http://pastebin.com/bSRM1wwN
ChangeApprovalEdit.php = http://pastebin.com/AStG9pqb
EDIT:
Changing Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
Don't echo variables from functions, which just outputs them to the standard output. return them from the function so you can use the value elsewhere as well.
function Row_Rendered() {
$RecordOwner = $this->RequestUser->CurrentValue;
return $RecordOwner;
}
Then instead of
$obj->Row_Rendered();
use
echo $obj->Row_Rendered();
and if you want to use the value elsewhere, use
$value = $obj->Row_Rendered();
You can do a couple of things:
First, you can return $RecordOwner from the function, and store its value in a variable. This method is usually preferred.
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
return $RecordOwner;
}
// Store it in a variable when calling the function.
$RecordOwner = Row_Rendered();
Or, you can make it global inside the function:
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
echo $GLOBALS['RecordOwner'];
}
You can use the $GLOBALS superglobals array, like this:
function Row_Rendered() {
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
However, you should not do that. Instead, refactor your application so that the view in ChangeApprovalinfo.php just contains a function, which is then called with the appropriate parameters.
EDIT: Chaning Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
I feel compelled to write another answer to this update. Let me demonstrate the use of globals as seen from outside that function:
$obj->Row_Rendered();
$obj->foobar();
echo $GLOBALS['RecordOwner'];
Quick, what will be echoed and where does that value come from? Well, it depends on what $obj-foobar() does. Maybe it changes the global variable. Maybe it doesn't. Who knows if the variable has been set at all? How would you trace back what happened exactly without adding a debug line after every single function call?
And that's just three lines of code. Imagine that in an application of any complexity.
Now, the same thing if I return the value from Row_Rendered:
$owner = $obj->Row_Rendered();
$obj->foobar();
echo $owner;
If the Row_Rendered method is behaving as it should (returning the owner), this code is very predictable. If you do not follow this pattern, you'll have a hell of a time getting anything done when the application grows to any halfway complex size.
Set the variable as global from within the function
$my_global_var = "old value";
function doing_stuff(){
global $my_global_var; //this will use the global variable instead of creating a local one
$my_global_var = "new value";
}
echo $my_global_var;//returns "new value"
I have one php function on a seperate php file and I am calling this function from another php file by using an jquery ajax call. The php function is just increment its static value by 1 but its not incremented as I see the output. The static variable doesnt behave as I think.
Whats the reason for that ?
Thanks in advance,
Simple function:
function IncrementByOne()
{
static $count = 0;
$count++;
echo $count;
}
Static function variables are persistent across function calls of the same request. They don't keep their value across multiple requests.
Actually, that is true of all PHP variables, apart from the magic $_SESSION variable: They are always reset after the current request ends.
If you want a variable to persist between multiple requests, you can put it into:
a session
a database
a flatfile
APC
memcached
...