how to backtrace default function arguments? - php

function backtrace() {
var_dump(debug_backtrace());
}
function echosth($what = 'default text') {
echo $what;
backtrace();
}
echosth('another text'); //argument is shown
// ["args"]=> array(1) {[0]=>&string(12) "another text"}
echosth(); //it appears as function has none arguments ["args"]=>array(0) {}
Is there any way to get to default value of parent function ?

Yes, through the PHP reflection class's getDefaultValue.
function foo($test, $bar = 'baz')
{
echo $test . $bar;
}
$function = new ReflectionFunction('foo');
foreach ($function->getParameters() as $param) {
echo 'Name: ' . $param->getName() . PHP_EOL;
if ($param->isOptional()) {
echo 'Default value: ' . $param->getDefaultValue() . PHP_EOL;
}
echo PHP_EOL;
}
Since you know about debug_backtrace, you should be able to get the name of the calling function and run it through that loop.

Using Reflection
http://php.net/manual/en/reflectionparameter.getdefaultvalue.php

Related

Static keyword doesn't work inside PHP generator function

It seems that the static keyword does not work inside generator functions?
In PHP 5.5:
function static_fn () {
static $p = 0;
echo "\nstatic_fn: p = " . $p . "\n" ;
$p++;
}
echo "calling static_fn()\n";
static_fn();
echo "calling static_fn()\n";
static_fn();
function static_gen() {
static $p = 0;
echo "\nstatic_gen: p = " . $p . "\n" ;
yield $p;
}
echo "calling static_gen()\n";
foreach(static_gen() as $stuff) {
echo $stuff . "\n";
}
echo "calling static_gen()\n";
foreach(static_gen() as $stuff) {
echo $stuff . "\n";
}
I get the result
calling static_fn()
static_fn: p = 0
calling static_fn()
static_fn: p = 1
calling static_gen()
static_gen: p = 0
0
calling static_gen()
static_gen: p = 0
0
That is, the static keyword worked successfully for the static_fn function which returned 0 and 1 from consecutive calls, but it did not work for the static_gen function where it was reinitialised to 0 in each call.
Does anyone know why this is so, and how one might work around it to replicate static variables in a generator?
Try this:
function static_gen() {
static $p = 0; #initialised
while ($p < 10) { #yield while $p is smaller than 10
$p++; #increased
echo "\nstatic_gen: p = " . $p . "\n" ;
yield $p; #yield value
}
}
That will work.
Sidenote: A generator function must yield values as long as values are given. So the function must provide it in one or a other way.
Just like #JustOnUnderMillions have commented above, static vars aren't shared among functions.
Static variables has scope per function.
Moreover, generators is not aimed to do what you've did (okay, maybe you are just testing something :)).
Anyway you could change you static_gen() to:
function static_gen()
{
static $p = 0;
echo "\nstatic_gen: p = " . $p . "\n";
yield $p++;
}
But again, it's is so weird.

pushing string into empty array gives warning

I created empty array and pushing val into it.
$var = array();
function printTag($tags) {
foreach($tags as $t) {
echo $t['token'] . "/" . $t['tag'] . " ";
if($t['tag'] == 'NN' OR $t['tag']== 'JJ'){
array_push($var, $t['token']) ;
}
}
echo "\n";
}
code looks fine for me but gives error:
array_push() expects parameter 1 to be array, null given in /var/www/html/postag/poscall.php on line 9
what is wrong here?
entire code:
<?php
// little helper function to print the results
include ("postag.php");
$var = array();
function printTag($tags) {
foreach($tags as $t) {
echo $t['token'] . "/" . $t['tag'] . " ";
if($t['tag'] == 'NN' OR $t['tag']== 'JJ'){
array_push($var, $t['token']) ;
}
}
echo "\n";
}
$tagger = new PosTagger('lexicon.txt');
$tags = $tagger->tag('The quick brown fox jumped over the lazy dog. this is really yummy and excellent pizza I have seen have really in love it it');
printTag($tags);
?>
Your $var = array(); statement is outside the function and out of the scope of the function. Put that inside the function and it'll remove the warning
function printTag($tags) {
$var = array();
foreach($tags as $t) {
echo $t['token'] . "/" . $t['tag'] . " ";
if($t['tag'] == 'NN' OR $t['tag']== 'JJ'){
array_push($var, $t['token']) ;
}
}
echo "\n";
}
The problem in your case is that $var is not in the scope of your function, so it gets implicitly declared as null (and this raises a notice too).
That said, this seems like a good case array_reduce():
$var = array_reduce($tags, function(&$result, $t) {
if (in_array($t['tag'], ['NN', 'JJ'])) {
$result[] = $t['token'];
}
// you could do some output here as well
return $result;
}, []);
It filters and maps at the same time and the return value is the array you want.
Alternatively, just declare $var inside the function and return it:
function printTag(array $tags)
{
$var = [];
foreach($tags as $t) {
// ...
}
return $var;
}
// ...
$var = printTag($tags);

Get variable name of object inside the object php

I'm wondering if this was possible and I could not find a way to do it so I ask. How can I get the name of the variable where in a instance of a class is present.
Pseudo code:
class test{
public $my_var_name = '';
function __construct(){
//the object says: Humm I am wondering what's the variable name I am stored in?
$this->my_var_name = get_varname_of_current_object();
}
}
$instance1 = new test();
$instance2 = new test();
$boeh = new test();
echo $instance1->my_var_name . ' ';
echo $instance2->my_var_name . ' ';
echo $boeh->my_var_name . ' ';
The output would be like:
instance1 instance2 boeh
Why! Well I just wanna know its possible.
I have no idea why, but here you go.
<?php
class Foo {
public function getAssignedVariable() {
$hash = function($object) {
return spl_object_hash($object);
};
$self = $hash($this);
foreach ($GLOBALS as $key => $value) {
if ($value instanceof Foo && $self == $hash($value)) {
return $key;
}
}
}
}
$a = new Foo;
$b = new Foo;
echo '$' . $a->getAssignedVariable(), PHP_EOL; // $a
echo '$' . $b->getAssignedVariable(), PHP_EOL; // $b
I created this code trying to answer for How to get name of a initializer variable inside a class in PHP
But it is already closed and referenced to this question,
just another variant easy to read, and I hope I didn't break any basic concept oh php development:
class Example
{
public function someMethod()
{
$vars = $GLOBALS;
$vname = FALSE;
$ref = &$this;
foreach($vars as $key => $val) {
if( ($val) === ($ref)) {
$vname = $key;
break;
}
}
return $vname;
}
}
$abc= new Example;
$def= new Example;
echo $abc->someMethod();
echo $def->someMethod();
I can't find a good reason to do that.
Anyways, one way you can do (but again it has no use as far as i can imagine) this is by passing the instance name as a constructor's parameter, like this:
$my_instance = new test("my_instance");

PHP: How to instantiate a class with arguments from within another class

I am in a situations where i need to instantiate a class with arguments from within an instance of another class.
Here is the prototype:
//test.php
class test
{
function __construct($a, $b, $c)
{
echo $a . '<br />';
echo $b . '<br />';
echo $c . '<br />';
}
}
Now, i need to instantiate above class using below class's cls function:
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
// this is where the problem might be, i need to pass as many arguments as test class has.
$class_instance = new $file_name($args);
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}
Now when i try to create an instance of test class while passing arguments to it:
$myclass = new myclass;
$test = $myclass->cls('test', array('a1', 'b2', 'c3'));
It gives error:
Missing argument 1 and 2; only first argument is passed.
This works fine if i instantiate a class which has no arguments in it's constructor function.
For experienced PHP developers, above should not be much of a problem. Please help.
Thanks
you need Reflection http://php.net/manual/en/class.reflectionclass.php
if(count($args) == 0)
$obj = new $className;
else {
$r = new ReflectionClass($className);
$obj = $r->newInstanceArgs($args);
}
You can:
1) Modify test class to accept an array, which contains the data you wish to pass.
//test.php
class test
{
function __construct($a)
{
echo $a[0] . '<br />';
echo $a[1] . '<br />';
echo $a[2] . '<br />';
}
}
2) initiate using a user method instead of the constructor and call it using the call_user_func_array() function.
//test.php
class test
{
function __construct()
{
}
public function init($a, $b, $c){
echo $a . '<br />';
echo $b . '<br />';
echo $c . '<br />';
}
}
In your main class:
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
// this is where the problem might be, i need to pass as many arguments as test class has.
$class_instance = new $file_name($args);
call_user_func_array(array($class_instance,'init'), $args);
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}
http://www.php.net/manual/en/function.call-user-func-array.php
Lastly, you can leave your constructor params blank and use func_get_args().
//test.php
class test
{
function __construct()
{
$a = func_get_args();
echo $a[0] . '<br />';
echo $a[1] . '<br />';
echo $a[2] . '<br />';
}
}
http://sg.php.net/manual/en/function.func-get-args.php
You could use call_user_func_array() I believe.
or you could leave the arguments list of the constructor, and then inside the constructor use this
$args = func_get_args();
class textProperty
{
public $start;
public $end;
function textProperty($start, $end)
{
$this->start = $start;
$this->end = $end;
}
}
$object = new textProperty($start, $end);
don't work?
The easiest way I have found:
if ($depCount === 0) {
$instance = new $clazz();
} elseif ($depCount === 1) {
$instance = new $clazz($depInstances[0]);
} elseif ($depCount === 2) {
$instance = new $clazz($depInstances[0], $depInstances[1]);
} elseif ($depCount === 3) {
$instance = new $clazz($depInstances[0], $depInstances[1], $depInstances[2]);
}
Sorry a bit raw, but you should understand the idea.
We're in 2019 now and we have php7 now... and we have the spread-operator (...) .
We can now simply call
<?php
class myclass
{
function cls($file_name, $args = array())
{
include $file_name . ".php";
if (isset($args))
{
$class_instance = new $file_name(...$args); // <-- notice the spread operator
}
else
{
$class_instance = new $file_name();
}
return $class_instance;
}
}

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