Is there any way to enforce parameter order? - php

I have the following function...
function myFunction($arg1 = '', arg2 = '') {
return 'My args: ' . $arg1 . ' & ' . $arg2;
}
... which I call with the data retrieved from GET in...
$arg1 = retrieve($_GET, 'arg1'); // custom function
$arg2 = retrieve($_GET, 'arg2'); // retrieves array value or empty string
$result = myFunction($arg1, $arg2);
... but ...
echo ($result === 'My args: ' . $arg1 . ' & ' . $arg2); // Why is this false?
Given that arg1 results in an empty string, but arg2 does not, why is the value of arg2 considered arg1 once it's been passed on to the function?
I'm a newbie to PHP, I'm most used to Java, and the introduction of optional parameters plus a mix of paradigms, etc confuses me.
TLDR; Why is arg1 not empty when called as myFunction('', $arg2);
EDIT: Posted code is made-up; actual code can be found here -> http://pastie.org/8623944#7
EDIT2: Testing code again, it was a typo on my part; I was reassigning $arg1 the value of $arg2 BEFORE passing it to the function. My bad.

Your function does not return the string, but echoes it, so the === will never be true
try
function myFunction($arg1 = '', arg2 = '') {
return 'My args: ' . $arg1 . ' & ' . $arg2;
}

Related

Can I use PHP anonymous function as an argument, without assigning the function to a variable?

Does PHP allow the use of an anonymous function as one of the arguments during concatenation?
If so, what is the proper syntax?
For example, here's an example of what I want to get to work:
$final_text = $some_initial_string . function ($array_of_strings)
{
$out = '';
foreach ($array_of_strings as $this_particular_string)
{
$out .= $this_particular_string;
}
return $out;
};
Note: the below is expected to work for PHP Version 7.x but does not work on PHP Version 5.6 (For 5.6, first assign the anonymous function to a variable)
/*
* Strings before & after
*/
$table_heading_text = "HEADING";
$table_bottom_text = "BOTTOM";
/*
* Use the function this way
*/
echo $table_heading_text . (function (array $array_of_strings)
{
$out = '';
foreach ($array_of_strings as $this_particular_string)
{
$out .= $this_particular_string;
}
return $out;
})(array(
"hi",
"mom"
)) . $table_bottom_text;
In short ...
function must return some value that can be converted to text
function definition must be enclosed in parenthesis ( ... )
Don't forget to have calling arguments after the function definition
Examples:
echo "BEFORE" . (function ($x){return $x;})(" - MIDDLE - ") . "AFTER";
echo "BEFORE" . (function (){return " - MIDDLE - ";})() . "AFTER";
Also, using implode() may be better for this particular task.

PHP resources cannot be identified from backtrace (call stack)

I'm writing PHP method to pretty-print callstack with params. Reason for this is it will be used as an output of a public API (in debug mode) so it must not display everything and only display save information.
I would like to see something like this:
Config->saveToFile(resource: file) in config.php::456
Config->backup('config.bak') in config.php::123
But when I call debug_backtrace() and parse the args value, I cannot use methods gettype(), is_resource() and get_resource_type() because it always say the variable is of unknown type:
Config->saveToFile(Unknown type: Resource id #99) in config.php::456
Config->backup('config.bak') in config.php::123
Code used to parse args is:
public static function getTrace() {
$trace = debug_backtrace();
$output = [];
foreach ($trace as $call) {
$name = $call['class'] . $call['type'] . $call['function']
//actual code checks for various situations
$args = [];
foreach ($call['args'] as $arg) {
$args[] = self::toString($arg);
}
$name .= '(' . join(', ', $args) . ')';
$output[] = $name . ' in ' . basename($call['file']) . '::' . $call['line'];
}
return $output;
}
protected static function toString($mixed) {
//process known types - arrays, objects, strings, etc.
//...
if (is_resource($mixed)) {
return 'resource: ' . get_resource_type($mixed);
}
return gettype($mixed) . ': ' . $mixed;
}
Even when I use code by diz at ysagoon dot com listed under debug_backtrace documentation, which utilize gettype() and check for resource, in my case it returns Config->saveToFile(Unknown).
When I use the methods in code where the resource is created, it correctly returns its type.
Is there a limit or reason why resources are not identified from backtrace? Something I should enable in PHP configuration? I haven't found anything about this in PHP documentation nor Google.
System:
XAMPP 3.2.2
Apache/2.4.17 (Win32)
PHP/5.6.15
Windows 10 Pro x64 Anniversary edition 1607 (10.0.14393)
So the problem is that resources can be identified as a resource only while they are opened. After you close the resource, it is no more identified by methods gettype(), is_resource() and get_resource_type() as a resource and instead change to unknown type.
$f = fopen('tmp', 'w');
echo gettype($f); //= 'resource'
fclose($f);
echo gettype($f); //= 'Unknown type'
To print closed resources in backtrace I've created two methods to remember resources while they are still opened:
protected $resources = [];
public function traceResourceParams() {
$trace = debug_backtrace();
$args = [];
foreach ($trace as $call) {
foreach ($call['args'] as $arg) {
if (is_resource($arg) && !array_key_exists(intval($arg), $this->resources)) {
$this->resources[intval($arg)] = self::toString($arg);
}
}
}
}
public function traceNamedResource($resource, $name) {
if (is_resource($resource)) {
$this->resources[intval($resource)] = '{' . get_resource_type($resource) . ': ' . $name . '}';
}
}
And updated my toString method to check for stored resources:
protected static function toString($mixed) {
//process known types - arrays, objects, strings, etc.
//...
if (is_resource($mixed)) {
return 'resource: ' . get_resource_type($mixed);
}
//closed resources does not evaluate as resource
//but still convert to resource id using intval()
//so we can match them to previously evaluated resources
$val = intval($mixed);
if ($val && array_key_exists($val, self::getInstance()->resources)) {
return self::getInstance()->resources[$val];
}
return gettype($mixed) . ': ' . $mixed;
}
So now I can store the resource when it is created:
$f = fopen('tmp', 'w');
$debug->traceNamedResource($f, 'tmp');
fclose($f);
Or when it is passed as a parameter:
protected function saveToFile($file) {
$debug->traceResourceParams()
//... work with file
fclose($file);
}

PHP array runs function and pass variable to it

I am coding a bot for a game and I am now coding the handlers I want to call my array so it runs the function.
$handlers = array(
"x" => function()
);
function function($m)
{
echo "Var: " . $m . "\n";
}
When I call handlers I tried it like this:
$handlers("x");
So how can I pass the variable to the function.
What you need is the call_user_func function. Besides, in your $handlers array, the name of the function must be in quotation marks and you can not use the reserved keyword function as the name of the function! and you may access the array element using [] operator:
$handlers = array(
"x" => '_function'
);
function _function($m)
{
echo "Var: " . $m . "\n";
}
call_user_func($handlers['x'], "hello :)");
For completeness, you can do it this way as well:
$handlers = array(
"x" => 'test'
);
function test($m) {
echo "Var: " . $m . "\n";
}
$handlers['x']("testing...");

How to simulate args inside a php file?

PHP file.php arg1 arg2
Now I want to hardcode arg1 and arg2 into file.php,how to do it?
I never tried it, but the arguments are contained in a certain array $argv. So you have to set those entries if you want to hardcode them:
$argc = 3; // number of arguments + 1
$argv[0] = 'file.php'; // contains script name
$argv[1] = 'arg1';
$argv[2] = 'arg2';
$argv is a reserved variable.
But note that the first two parameter that you specify via command line will always be overwritten by arg1 and arg2.
Instead, if you need these values always in your script you should define them as normal variables at the top of your script:
$var1 = 'arg1';
$var2 = 'arg2';
or even as constants:
define('CONST1', 'arg1');
define('CONST2', 'arg2');
If you only want to provide arg1, arg2 as parameter via the command line, then you can just access them via $argv[1] and $argv[2], no need to mess with $argv;
you would use argv() inside your php script to get the arguments
foreach ($argv as $args){
print $args."\n";
}
element 0 contains the script name. the rest are the arguments.
You want to test how many arguments to the function, then do something accordingly.
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs<br />\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "<br />\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
}
}
foo(1, 2, 3);

function functionName(if clause here) possible?

function getTemplate($tpl if ($vars) echo ", $vars";)...function
Is this possible somehow?
The above wont work.
Thanks
Optional arguments with default values
It looks like you want an optional argument, which you can accomplish by defining a default value in the function definition:
function getTemplate($tpl, $vars=null)
{
}
You can call this function as getTemplate($foo) or getTemplate($foo,$bar). See the PHP manual page on function arguments for more details.
Variable numbers of arguments
It's also possible to write functions which take a variable number of arguments, but you need to use func_num_args, func_get_arg and func_get_args functions to get at them. Here's an example from the manual
<?php
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs<br />\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "<br />\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
}
}
foo(1, 2, 3);
?>
Calling a function with a variable number of parameters
To round off this answer even more, suppose you'd build an array of 1..n values and wanted to pass it to the foo() function defined above? You'd use call_user_func_array
$values=(1,2,3,4);
call_user_func_array('foo', $values);
This is the equivalent of calling
foo(1,2,3,4);
What's so bad about
function getTemplate($tpl, $vars=null) {}
?
if ($vars) { getTemplate($tpl, $vars); }
else {{ getTemplate($tpl, null); }
(semi-pseudo code)
Or:
getTemplate($tpl, ($vars)?$vars:null); // not sure
getTemplate($tpl, (!empty($vars))?$vars:null);
Also, if you would like a technique similar to echo:
$code = "getTemplate($pl";
if ( $vars ) { $code = $code . ", $vars);"; }
else { $code = $code . ");"; }
$ret = eval($code);
Although this is usually considered bad practice (never say never).
Please note that all code sent to eval will be executed directly. So don't put user input in an eval() call.

Categories