I have a PHP file which contains associative arrays. I have them all in one file for ease of editing/updating. For example:
$ass_first = array( "title"=>"Title",
"first_name"=>"First Name",
"surname"=>"Surname",
"phone"=>"Phone Number",
"email"=>"Email Address",
"add1"=>"House Name/Number",
"add2"=>"Street",
"add3"=>"Town",
"add4"=>"City",
"add5"=>"Post Code"
);
In another file, I have functions which are passed variables, which in turn call other functions.
For example I have a function which is called to create a table containing form inputs. Inside this function, there is a test to see what form input is needed and the necessary function is called.
function create_table($titles, $id) { //$titles is the relevant array from lists.php, $id is the id of the containing div
$select = array('timescale','bus_route','train_stat'); //'select' id list
foreach ($titles as $k=>$v) { //$k is the database/id/name $v is the description text
if (in_array($k,$select)){
select_box($k,$v);
}
else if //input is a text area
text_box($k,$v);
}
else{ //input is a checkbox
check_box($k,$v);
}
}
}
Inside these three 'nestled functions' I want to refer to some arrays contained in the lists.php file.
I want to know the best way to add these arrays to the functions scope. I have been told variable variables arent neccessarily the best way to go, neither is declaring global variables. I cant think of any other way to do it!
Also passing them as a variable into the functions isnt really an option because the three different nestled functions need a different set of arrays meaning three sets of arrays will be passed but only one would be used at any one time!
You can pass the arrays to your create_table function:
function create_table($titles, $id, $arrays) {
...
}
You can go ahead and use a global variable, maybe add a comment above it saying what file sets the variable:
function create_table($titles, $id) {
//$arrays gets set in lists.php
global $arrays;
...
}
Or you can require your lists.php file like so:
function create_table($titles, $id) {
require 'lists.php';
...
}
Related
This is something of a clean coding question.
After declaring some variables in a parent document, and a require statement:
$My_Variable = 'Something here';
$My_Variable_2 = 'Something else here';
require __DIR__.'/test2.php'; // More stuff will happen to $My_Variable and $My_Variable_2 here...
instead of a raw require statement, I'd like to invoke a clean-syntax function which executes the require statement:
Require_Script($Arguments);
where the Require_Script() function looks something like this:
function Require_Script($Arguments) {
// Some other code here;
require __DIR__.'/test2.php';
}
I note that, unless I'm careful, the variables declared in the parent document (which could be different variables in different contexts) which were going to be manipulated in test2.php (and which were available to that include when I used the raw require statement) are no longer available in test2.php - presumably because the require statement is now in a different scope.
Here's what it looks like in practice. Here are a couple of includes:
test2.php :
$My_Variable .= ' which has been upgraded';
$My_Variable_2 .= ' which has also been upgraded';
test3.php :
$My_Variable .= ' not once but twice.';
$My_Variable_2 .= ' also not just once but twice.';
And here's the Parent Document:
$My_Variable = 'This is my variable';
$My_Variable_2 = 'This is my other variable';
echo '<p>'.$My_Variable.'</p>'; // This is my variable
echo '<p>'.$My_Variable_2.'</p>'; // This is my other variable
***********
***********
require __DIR__.'/test2.php';
echo '<p>'.$My_Variable.'</p>'; // This is my variable which has been upgraded
echo '<p>'.$My_Variable_2.'</p>'; // This is my other variable which has also been upgraded
***********
***********
function My_Require_Function($logicVariables) {
foreach ($logicVariables as $key => $value) {
${$key} = $value;
global ${$key};
}
require __DIR__.'/test3.php';
}
My_Require_Function(['My_Variable' => $My_Variable, 'My_Variable_2' => $My_Variable_2]);
echo '<p>'.$My_Variable.'</p>'; // This is my variable which has been upgraded not once but twice.
echo '<p>'.$My_Variable_2.'</p>'; // This is my other variable which has also been upgraded also not just once but twice.
So, it works. But surely there must be better approaches?
This approach uses:
an over-elaborate associative array parameter
a custom equivalent of extract()
variable variables
(worst of all) global
My question is:
What (much) better alternative approaches exist to enable me to syntactically replace
require __DIR__.'/test2.php'
with a function which incorporates a require statement and looks something like:
Require_Script($Arguments)
I really liked #Barmar's observation in the comments above that:
The include file should define functions, which you call in the parent
script, and pass the variables as parameters.
So I set about thinking of an approach which, rather than simply including some lines of code to modify variables from the parent document, would, instead, include and then run a function instead.
This would require 4 steps:
a function in the parent document which accepts as parameters both the name of the function to be included and an associative array containing the argument values that will be fed to that remote function
the remote function (in the included file) to extract() all variables from the submitted associative array
the remote function (in the included file) to process all those variables and then re-build its own associative array and return that
the parent document to extract() all variables from the returned associative array
This ended up looking like this:
test4.php
function test4($logicVariables) {
extract($logicVariables);
$My_Variable .= ' not once but twice.';
$My_Variable_2 .= ' also not just once but twice.';
return ['My_Variable' => $My_Variable, 'My_Variable_2' => $My_Variable_2];
}
Parent Document:
function My_New_Require_Function($Include_Name, $logicVariables) {
require __DIR__.'/'.$Include_Name.'.php';
return $Include_Name($logicVariables);
}
$My_Variables = ['My_Variable' => $My_Variable, 'My_Variable_2' => $My_Variable_2];
$My_Variables = My_New_Require_Function('test4', $My_Variables);
extract($My_Variables);
In a nutshell this process follows these 7 steps:
Package up variables in Parent Document =>
Submit package of variables to function =>
Unpackage variables inside function =>
Process variables =>
Repackage up processed variables =>
Return Package to Parent Document =>
Unpackage processed variables
The really good news is that this approach works and it doesn't require a custom equivalent of extract() or variable variables or global. (Though it does still require an associative array to be submitted to the function.)
Finally I saw that if the associative array had only one entry (or relatively few entries) I could make the last three lines a lot more concise, by simply rewriting as a single line:
extract(My_New_Require_Function('test4', ['My_Variable' => $My_Variable]));
I have to execute function "one" and function "two" at different places in my code.
I set the function one variables in a dynamic array in order to use them in the function 2 by setting the array as a global variable.
Then, when I call the function two by using the 1st value of the array, I can get the variable of each key.
This works well and it is ok when I have a limited number of arrays...
Now, I'll have to call many function one and I would like to automatize the execution of the function two.
I thought to use a foreach loop for this.
Unless, I am not familiar with foreach structure, I can not find the way to do it.
Thank you for your help.
Etienne
Here is my code :
function one($nom,$a,$b,$c)
{
global $$nom;
$$nom = array($a,$b,$c);
}
function two($nom)
{
global $$nom;
echo ${$nom}[0].'</br>'.${$nom}[2].'</br>';
}
one("D1",10,20,30);
one("D2",100,200,300);
two("D1"); // works but i do not want to write it manually
two("D2"); // I want to use the foreach loop for that
foreach(${$nom} as $value) {
two($nom);
}
I currently have a php function, in which the 1st parameter is a reference to an array and the 2nd parameter is one of its keys,
function fun(&$a, $k) {
......
}
I want to modify the function so that I just need to pass one parameter $a[$k]. Inside the function , $a can be extracted from $a[$k] and then I can call array_search($a[$k], $a) to get $k. Is that possible in PHP?
function fun(&$ak) {
// $ak is from $a[$k]
// a php utility to extract $a from $ak? ...
$k = array_search($ak, $a);
}
Short answer: No, there's no way to "extract" that information, because that information doesn't exist in the scope of your function.
Long answer:
As people have pointed out in the comments, you simply cannot do this. If you have a function like this:
function fun(&$foo) {
...
}
there is no information passed to that function about where $foo came from. It could be a standalone variable, an array element ($bar[1]), an object property ($baz->bingo), or anything else (think SomeClass::$bar->baz[$bingo->boingo]). There's no way to tell.
To verify this, try var_dump($ak); in your function; it won't contain any information about what array or object it's in (or its array index or property name). It's just like any other variable.
I'm writing my own debug functions and I need some help to fix the code below.
I'm trying to print a variable and its name, the file where the variable and the function was declared and the line of the function call. The first part I did, the variable, the variable name, the file and the line is printed correctly.
At the code, a($variable) works good.
The problem is I'd like this function accepts a string too, out of a variable. But PHP returns with a fatal error (PHP Fatal error: Only variables can be passed by reference in ...). At the code, a('text out').
So, how can I fix this code to accept a variable or a string correctly?
code (edited):
function a(&$var){
$backtrace = debug_backtrace();
$call = array_shift($backtrace);
$line = $call['line'];
$file = $call['file'];
echo name($var)."<br>".$var."<br>".$line."<br>".$file;
}
$variable='text in';
a($variable);
a('text out');
I need pass the variable by reference to use this function below (the function get the variable name correctly, works with arrays too):
function name(&$var, $scope=false, $prefix='unique', $suffix='value'){
if($scope) $vals = $scope;
else $vals = $GLOBALS;
$old = $var;
$var = $new = $prefix.rand().$suffix;
$vname = FALSE;
foreach($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
The way your code is currently implementing pass by reference is perfect by design, but also by design cannot be changed to have two a() methods - one accepting a variable by reference and the other as a string-literal.
If the desire to pass a string literal instead of assigning it to a variable first is really needed, I would suggest creating a second convenience method named a_str() that actually accepts a string-literal instead of a variable by reference. This method's sole-purpose would be to relay the variable(s) to the original a() method - thereby declaring a variable to pass by reference.
function a_str($var) {
a($var);
}
The only thing to remember is, use a($variable); when passing by reference and a_str('some text'); when not.
Here is the same convenience-method for your name() function:
function name_str($var, $scope=false, $prefix='unique', $suffix='value'){
return name($var, $scope, $prefix, $suffix);
}
The only way to do what you are asking without writing an additional function like #newfurniturey suggests is plain and simply opening and parsing the file where your function was called as text (e.g. with fopen), using the data from debug_backtrace. This will be expensive in terms of performance, but it might be ok if used only for debugging purposes; and using this method you will no longer need a reference in your function, which means you can freely accept a literal as the parameter.
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