There are multiple ways I can conceive for achieving the following functionality; however I am hoping for a super elegant solution. Can I use a PHP superglobal variable as the default value for a user defined function parameter?
Example:
function test1($foo=$_SERVER['PATH']) {
echo $foo;
}
The above code spits out an error. Like I said I know that I can achieve the same thing using the following code (but the above code is more attractive):
function test2($foo) {
if (!isset($foo)) $foo = $_SERVER['PATH'];
echo $foo;
}
Thanks for the help!
I would recommend passing in the variable, but if you want to use a global one, you can do this
function test2() {
global $foo;
...
}
at the top of your function and set the value somewhere else, or go with your second idea - but you need to specify a default value in the function parameter to make it optional.
function test2($foo='') {
if (empty($foo)) $foo = $_SERVER['PATH'];
echo $foo;
}
Another way to work with variables from outside your function is to pass them in by reference. This passes in a reference to the original variable, not a copy, so any changes you make inside the function will affect the original variable value outside of the scope of the function as well.
$foo = 'bar';
function test2(&$foo) {
echo $foo; // this will output "bar"
}
Related
As per the PHP documentation on unset() function :
The behavior of unset() inside of a function can vary depending on what type of variable you are attempting to destroy.
If a globalized variable is unset() inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before unset() was called.
The code example demonstrating above saying is as below :
<?php
function destroy_foo()
{
global $foo;
unset($foo);
}
$foo = 'bar';
destroy_foo();
echo $foo; // o/p is bar
?>
Now my question is why the above behavior is not applicable in following program that I have written?
<?php
function increment_foo()
{
global $foo;
$foo++;
}
$foo = 36;
increment_foo();
echo $foo; // o/p is 37
?>
My doubt is why the behavior is different in above code than the behavior in the code written for unset() function?
In other words, I want to know in first code the unset() functionality remains limited to the local variable inside the function, it doesn't change the value in global scope outside the function but in the code that I have been written the increment functionality changes the value in global variable scope as well. In my code why it's not remaining limited to the local variable inside a function and changing value/affecting the variable outside the function as well?
Thank You.
The reason for this is that using the global keyword will create a local variable referencing the variable in the global scope. Unsetting simply destroys this reference. It's similar to this piece of code:
$foo = 42; // create variable with value
$bar = &$foo; // create reference to $foo
$bar++; // increment $foo via reference
unset($bar); // destroy reference
var_dump($bar); // NULL
var_dump($foo); // 43
Another way to put it is that doing global $foo is just a shorthand for doing $foo = &$GLOBALS['foo'], e.g. the first example can be rewritten to
function increment_foo()
{
$foo = &$GLOBALS['foo'];
$foo++;
unset($foo);
var_dump($foo); // NULL
}
$foo = 42;
increment_foo();
var_dump($foo); // 43
Maybe that makes it more obvious that you are only destroying the reference, e.g. you are destroying what points to $foo, but not $foo itself.
Lets say we have function:
function foo() {
return "bar";
}
Is it possible to add some filter to foo() function, for example to make it returning double value like "barbar" without changing the function itself.
So we would have:
foo(); //returns "bar"
function filter($&val) {
$val = $val . $val;
}
add_filter_to_function('foo','filter');
foo(); //returns "barbar"
And then anywhere foo() is used, it would return filtered value without changing code that calls foo() to something like foo() . foo() and without changing the function itself
In PHP, there is a RunKit extension (runkit_function_redefine() in particular for your question) which allow you to manipulate with code's objects (such as function or classes) on the fly.
But I think you're doing something wrong if you need to change your function's code on that way - so may be you should reconsider your goal and resolve your original problem with another tools.
If you need to call your function with some parameters in some special cases, you can use something like:
function foo($x, $y)
{
//do stuff
}
function bar($x, $y, $z)
{
//do stuff with $z?
foo($x, $y);
}
and use bar() instead of foo() then - in certain places (which you need to adjust)
You cannot internally change the return value of a function, if it's static.
If you had foo($var), you could change the state of $var, and everytime you call foo($var) lately, you would recieve the new value, but in your case it's almost not possible.
You have to call the other function everytime you need double value:
function foo() {
return 'bar';
}
function filter($func) {
return $func.$func;
}
echo filter(foo());
Turn your function into an object method and then the add_filter_to_function would add the filter to the object.
Then when you called the function it would be able to use the filters that have been assigned to the object the function belongs to.
You could simply concatenate the value on itself:
$val = foo();
$val .= $val;
or if your function really needs to have a double value returned, then you should probably look at refactoring your foo() function, because it doesn't seem to do what you want.
Either that, or accept one of the other answers that tells you to wrap foo() around another function.
I have been told that a class cannot be defined within a class in PHP. However, in my own example this seems to work which has me confused:
class_test.php:
require('class_1.php');
new class_1
//Need $missing_variable here.
class_1.php
class class_1{
public function function_1(){
function callback_function(){
echo "A Callback";
$missing_variable = "Where Did I Go?";
}
require('class_2.php');
new class_2('callback_function');
}
public function __construct(){
$this->function_1();
}
}
class_2.php
class class_2{
public function __construct($callback){
echo "Hello World - ";
call_user_func($callback);
}
}
Loading class_test.php prints out
Hello World - A Callback
Question: How do I define $missing_variable such that I can get it where I need it?
In case anyone in the future has a similar problem, however unlikely that may be, I want to link to the codepad from below that shows the $missing_variable echo'd from outside the classes:
http://codepad.org/tRk0XWG7
Thanks again everyone.
Note: This is a follow up.
You can declare a class within a function. That's known as conditional declaration, i.e. only if the function is called will the class be declared. It doesn't make much of a difference then whether you include a file with the class declaration or if you type out the code inside the function.
This does not mean however that the classes share any sort of scope or data. Only the declaration is conditionally nested, it still has the same functionality and scope as explained before.
Your confusion about the callback can be explained by the same thing. When class_1::function_1 is executed the first time, the function callback_function is being defined. This is a regular global function that can be called from anywhere. It's not bound to the class in any way. You will also notice that you cannot execute class_1::function_1 a second time, PHP will complain that callback_function already exists when you're trying to declare it again.
As for the comment in the source code //How do I declare this variable so that it is available where I need it?: You don't. That variable is a local variable inside a function. It's only in scope inside the function. You can return its value from the function like any other return value if you want to. (You could make it global, but for the love of god don't!) If you need that value somewhere else, don't declare it as a variable inside a function, because only the function can access it then.
You would return $missing_variable in a few places. See below. (This isn't the only way to do it, mind you)
http://codepad.org/tf08Vgdx
<?
class class_2{
public function __construct($callback){
echo "Hello World - ";
$missing = $callback();
$this->missing = $missing;
}
}
class class_1{
public function function_1(){
function callback_function(){
echo "A Callback. ";
$missing_variable = "Where Did I Go?";
return $missing_variable;
}
$class2 = new class_2('callback_function');
return $class2->missing;
}
public function __construct(){
$this->missing = $this->function_1();
}
}
$class = new class_1();
echo $class->missing;
I have a function that searches for a string inside a text file. I want to use the same function to assign all lines to an array in case I am going to replace that string. So I will read the input file only once.
I have the search function working but I do not know how to deal with the array thing.
the code is something like that (I made the code sample much simpler,so please ignore the search function that actually isn't below)
function read_ini($config_file_name,$string){
$config_file = file($config_file_name);
foreach($config_file as $line) {
return_string = trim(substr($line,0,15));
$some_global_array = $line'
}
}
echo read_ini('config.ini','database.db')
if ($replaced) {file_put_contents('config.ini', $some_global_array);}
http://php.net/parse_ini_file
I know it doesn't answer the question, but it quite possibly removes the need for even having to ask.
The deal with globals, though, is that they must be defined at the top of the function as globals, or else they're considered part of the function's scope.
function write_global() {
global $foo;
$foo = 'bar';
}
write_global();
echo $foo; // bar
I hava a function that looks something like this:
require("config.php");
function displayGta()
{
(... lots of code...)
$car = $car_park[3];
}
and a config.php that look something like this:
<?php
$car_park = array ("Mercedes 540 K.", "Chevrolet Coupe.", "Chrysler Imperial.", "Ford Model T.", "Hudson Super.", "Packard Sedan.", "Pontiac Landau.", "Duryea.");
(...)
?>
Why do I get Notice: Undefined variable: car_park ?
Try adding
global $car_park;
in your function. When you include the definition of $car_park, it is creating a global variable, and to access that from within a function, you must declare it as global, or access it through the $GLOBALS superglobal.
See the manual page on variable scope for more information.
Even though Paul describes what's going on I'll try to explain again.
When you create a variable it belongs to a particular scope. A scope is an area where a variable can be used.
For instance if I was to do this
$some_var = 1;
function some_fun()
{
echo $some_var;
}
the variable is not allowed within the function because it was not created inside the function. For it to work inside a function you must use the global keyword so the below example would work
$some_var = 1;
function some_fun()
{
global $some_var; //Call the variable into the function scope!
echo $some_var;
}
This is vice versa so you can't do the following
function init()
{
$some_var = true;
}
init();
if($some_var) // this is not defined.
{
}
There are a few ways around this but the simplest one of all is using $GLOBALS array which is allowed anywhere within the script as they're special variables.
So
$GLOBALS['config'] = array(
'Some Car' => 22
);
function do_something()
{
echo $GLOBALS['config']['some Car']; //works
}
Also make sure your server has Register globals turned off in your INI for security.
http://www.php.net/manual/en/security.globals.php
You could try to proxy it into your function, like:
function foo($bar){
(code)
$car = $bar[3];
(code)
}
Then when you call it:
echo foo($bar);
I had the same issue and have been tearing my hair out over it - nothing worked, absolutely nothing - until in desperation I just copied the contents of config.php into a new file and saved it as config2.php (without changing anything in its contents at all), changed the require_once('config.php'); to require_once('config2.php'); and it just started working.