class example()
{
function shout($var)
{
echo 'shout'.$var;
}
function whisper($var, $bool)
{
if($bool)
{
echo $var;
}
}
}
$obj = new example();
if($var)
{
$func = $obj->shout();
}else
{
$func = $obj->whisper();
}
I want to prepare the function variable first for later use instead of putting conditions in a loop. Is there a possible way to do it?
You can call methods by name:
if ($var) {
$fn = 'shout';
} else {
$fn = 'whisper';
}
$obj->$fn();
You can put the function name in a string:
if($var)
{
$func = 'shout';
}else
{
$func = 'whisper';
}
Later on:
$obj->$func
You can also use a callback:
if($var)
{
$func = array($obj, 'shout');
}else
{
$func = array($obj, 'whisper');
}
Later:
call_user_func($func);
or:
call_user_func_array($func, $args);
Related
I want to have a function and then use it multiple times with different parameters.
For example:
<?php
class Test {
var $test;
public function func($val) {
$this->test = $val;
}
public function buildFunc() {
if(!empty($this->test)) {
$ret = $this->test;
}
return $ret;
}
}
?>
Then on calling page:
$test = new Test;
$test->func("test1");
$test->func("test2");
echo $test->buildFunc();
Then it prints test2 on the screen. And I want it to print out both of them.
Either create 2 instances of your object;
$test1 = new Test;
$test1->func("test1");
$test2 = new Test;
$test2->func("test2");
echo $test1->buildFunc();
echo $test2->buildFunc();
Or make test an array;
class Test {
var $test = array();
public function func($val) {
$this->test[] = $val;
}
public function buildFunc() {
return print_r($this->test, true);
}
}
May be you mean that you want to store all values? Then use an array:
public function func($val) {
$this->test[] = $val;
}
public function buildFunc() {
return $this->test
}
And then work with the result as with an array.
Well.. your code does exactly what are you telling it to do. Consider situation when you have no OOP:
$str = 'test 1';
$str = 'test 2';
echo $str; //prints test 2
So you need to echo them separately as if it wont be an OOP situation.
$test = new Test;
$test->func("test1");
echo $test->buildFunc();
$test->func("test2");
echo $test->buildFunc();
When calling the method create 2 instances of the test object.
$test = new Test;
$test->func("test1");
echo $test->buildFunc();
$test2 = new Test;
$test2->func("test2");
echo $test2->buildFunc();
if you dont want to create 2 instances you have to make a array instead.
How about create a constructor and initialize the value of test and concat the second value.
<?php
class Test {
var $test;
public function __construct($init){
$this->test = $init;
}
public function func($val) {
$this->test .= $val;
return $this;
}
public function buildFunc() {
if(!empty($this->test)) {
$ret = $this->test;
}
return $ret;
}
}
$test = new Test("test1");
$test->func("test2");
echo $test->buildFunc();
?>
When you say both do you mean something like
test1test2
or do you want
test1
test2
For the first option you can just append the string:
<?php
class Test {
var $test;
public function func($val) {
$this->test = $test . $val; <-- add val to the end
}
public function buildFunc() {
if(!empty($this->test)) {
$ret = $this->test;
}
return $ret;
}
}
?>
For the second:
<?php
class Test {
var $test = array();
public function func($val) {
$this->test[] = $val; <-- add val to
}
public function buildFunc() {
if(!empty($this->test)) {
foreach($test as $item){
echo $item . "<br/>";
}
}
}
}
?>
Push the variables to an array
<?php
class Test {
var $test;
public function __construct(){
$this->test=array();//Declare $test as an array
}
public function func($val) {
$this->test[]=$val;//Push to array
}
public function buildFunc() {
if(!empty($this->test)) {
$ret = implode(",",$this->test);
}
return $ret;
}
}
?>
Someone asked for an event handler that registeres variable changes in this question: PHP how to detect the change of variable?
I tried to develop a quick class with PHP's magic functions __get and __set. This works until I pass the member into a normal function by reference, it does not trigger the event anymore.
Is this a bug, or something that is not possible, or do I just miss something?
<?php
header("content-type: text/plain");
class WatchVar {
private $data = array();
private $org = array();
private $callbacks = array();
public function __set($name, $value) {
if (!array_key_exists($name, $this->data)) {
$this->org[$name] = $value;
} else {
//variable gets changed again!
$this->triggerChangedEvent($name, $value);
}
$this->data[$name] = $value;
}
public function &__get($name) {
if (array_key_exists($name, $this->data)) {
if ($this->data[$name] != $this->org[$name]) {
//variable has changed, return original
//return $this->org[$name];
//or return new state:
return $this->data[$name];
} else {
//variable has not changed
return $this->data[$name];
}
}
}
public function addCallback($name, $lambdaFunc) {
$this->callbacks[$name] = $lambdaFunc;
}
protected function triggerChangedEvent($name, $value) {
//$this->data[$name] has been changed!
//callback call like:
call_user_func($this->callbacks[$name], $value);
}
}
$test = new WatchVar;
$test->addCallback('xxx', function($newValue) { echo "xxx has changed to {$newValue}\n"; });
$test->xxx = "aaa";
echo $test->xxx . "\n";
//output: aaa
$test->xxx = "bbb";
//output: xxx has changed to bbb
echo $test->xxx . "\n";
//output bbb
function messyFunction(&$var) {
$var = "test";
}
messyFunction($test->xxx);
//output: nothing, why?
Altering this code it works:
function messyFunction(&$var) {
$var->xxx = "test";
}
messyFunction($test);
//output: xxx has changed to test
//output: nothing, why?
Even passed by reference, the function only recieves a clone of the member variable instead of the instance + magic functions.
which is the best way to "prepare/store a function call"* for to, in a later point, actually execute it?
(* with an undetermined number of parameters)
what I have now:
function addCall($className, [$parameter [, $parameter ...]])
{
$this->calls[] = func_get_args();
}
then I'll do:
foreach($this->calls as $args)
{
$r = new ReflectionClass(array_shift($args));
$instances[] = $r->newInstanceArgs($args);
}
which doesn't look very OOP to me, including the "undetermined number of parameters" characteristic
how can I improve my code?
thank you in advance
You might be interested in the Command pattern.
How you implement it is up to you - or the framework you're using.
But those patterns usually stack up. So have a good read of the "surrounding" patterns, too, to be able to make a good choice regarding the actual implementation (or choosing an existing library).
completely informal:
<?php
function foo($a, $b) {
return 'foo#'.($a+$b);
}
function bar($a,$b,$c) {
return 'bar#'.($a-$b+$c);
}
$cmds = array();
$cmds[] = function() { return foo(1,2); };
$cmds[] = function() { return bar(1,2,3); };
$cmds[] = function() { return bar(5,6,7); };
$cmds[] = function() { return foo(9,7); };
$s = new stdClass; $s->x = 8; $s->y = 8;
$cmds[] = function() use($s) { return foo($s->x,$s->y); };
// somewhere else....
foreach($cmds as $c) {
echo $c(), "\n";
}
or something like
<?php
interface ICommand {
public function /* bool */ Execute();
}
class Foo implements ICommand {
public function __construct($id) {
$this->id = $id;
}
public function Execute() {
echo "I'm Foo ({$this->id})\n";
return true;
}
}
class Bar implements ICommand {
public function __construct($id) {
$this->id = $id;
}
public function Execute() {
echo "I'm Bar ({$this->id})\n";
return true;
}
}
$queueCommands = new SplPriorityQueue();
$queueCommands->insert(new Foo('lowPrio'), 1);
$queueCommands->insert(new Foo('midPrio'), 2);
$queueCommands->insert(new Foo('highPrio'), 3);
$queueCommands->insert(new Bar('lowPrio'), 1);
$queueCommands->insert(new Bar('midPrio'), 2);
$queueCommands->insert(new Bar('highPrio'), 3);
// somewhere else....
foreach( $queueCommands as $cmd ) {
if ( !$cmd->execute() ) {
// ...
}
}
or something else ...
I am trying to build a function that will call another function.
For example, if I have an array full of function names to call, is it possible to call a function for every array value without writing it in a script?
Example:
function email($val=NULL) {
if($val)
$this->_email = $val;
else
return $this->_email;
}
function fname($val=NULL) {
if($val)
$this->_fname = $val;
else
return $this->_fname;
}
For email, fname, etc.
But I want to have it like:
function contr_val($key,$val) {
function $key($val=NULL) {
if($val)
$this->_$key = $val;
else
return $this->_$key;
}
function $key($val="hallo");
}
And call it with:
contr_val("email", "test")
You're really trying to create member variables dynamically and retrieve their values. This is what __get() and __set() are for.
Here's how you could use it:
class TestClass {
var $data = array();
public function __set($n, $v) { $this->data[$n] = $v; }
public function __get($n) {
return (isset($this->data[$n]) ? $this->data[$n] : null);
}
public function contr_val($k, $v = NULL) {
if ($v)
$this->$k = $v;
else
return $this->$k;
}
};
$sherp = new TestClass;
$sherp->contr_val("Herp", "Derp");
echo "Herp is: " . $sherp->contr_val("Herp") . "\n";
echo "Narp is: " . $sherp->contr_val("Narp") . "\n";
Something like this:
/*
Input: $val - any value
$varname - the variable name, for instance: _email
*/
function checkValue($val=NULL, $varname) {
if($val)
$this->$var = $val;
else
return $this->$var;
}
checkValue("hello", "_email");
checkValue("hello2", "_name");
If you are doing this for a class, consider using PHP's magic methods __get() and
__set().
In an array full of function names, this calls every function that exists.
ghoti#pc:~$ cat functest.php
#!/usr/local/bin/php
<?php
function one() { print "one\n"; }
function two() { print "two\n"; }
function three() { print "three\n"; }
$a=array( "one", "two", "three", "four" );
foreach ($a as $item) {
if (function_exists($item)) {
$item();
} else {
print "No such function: $item\n";
}
}
ghoti#pc:~$ ./functest.php
one
two
three
No such function: four
ghoti#pc:~$
You need to check if the function exists or not:
function contr_val($key,$val) {
if (!function_exists($key)) {
function $key($val=NULL) {
if ($val)
$this->_$key = $val;
}
}
else {
return $this->_$key;
}
}
I want to be able to call a function, that will set one or more local variables in the calling function. For instance:
function someFunc () {
loadTranslatedStrings($LOCALS, "spanish");
echo $hello; // prints "hola";
}
function loadTranslatedStrings (&$callerLocals, $lang) {
if ($lang == 'spanish')
$callerLocals['hello'] = 'hola';
else if ($lang == 'french')
$callerLocals['hello'] = 'bonjour';
else
$callerLocals['hello'] = 'hello';
}
(I'm guessing it is impossible to do this, but might as well ask...)
You could do this...
function someFunc () {
loadTranslatedStrings($lang, "spanish");
extract($lang);
echo $hello; // prints "hola";
}
CodePad.
The closest I think you could get is by using extract:
function someFunc()
{
extract(loadStrings('french'));
echo $hello;
}
function loadStrings($lang)
{
switch($lang)
{
case 'spanish':
return array('hello' => 'hola');
case 'french':
return array('hello' => 'bonjour');
}
}
You can do that using $GLOBALS: $GLOBALS['hello'] = 'hola';