is there a better way to call an anonymous function inside a class? Here is a simple example that clearifies what I mean.
class foo
{
private $call_back_1 = null;
private $call_back_2 = null;
function __construct($func1, $func2)
{
$this->call_back_1 = func1;
$this->call_back_2 = func2;
}
function provokeCallBacks()
{
//this does not work, and gives an error
$this->call_back_1();
//I would like to avoid this
$method = $this->call_back_2;
$method();
}
}
$call1 = function(){ echo "inside call 1"};
$call2 = function(){ echo "inside call 2"};
$test = new foo(call1, call2);
$test->provokeCallBacks();
* Update 1: Please ignore any syntax error as I have written this on the fly for demo puposes. *
Inside foo:provokeCallBacks, I am trying to call the anonymous functions how ever the first way does not works and gives an error. The second one works but it's a bit stupid that I have to use a temp variable called "$method" to make the call.
I want to know if there exists a better way to call the anonymous function.
call_user_func($this->call_back_1);
No, it's not possible to call an anonymous function via $this.
Another options is;
call_user_func($this->call_back_1);
Being PHP loosely typed, it can't do like {$this -> callback}(); you have to store it in a temp variable or to use call_user_func() either.
EDIT - consider something like this:
class Lambdas
{
protected $double;
protected $triple;
public function __construct($double, $triple)
{
$this -> double = $double;
$this -> triple = $triple;
}
public function __call($name, $arguments)
{
if( is_callable($this -> {$name}) ){
return call_user_func_array($this -> {$name}, $arguments);
}
}
}
$lambdas = new Lambdas(
function($a){ return $a * 2;},
function($a){ return $a * 3;}
);
echo $lambdas -> double(2); // prints 4
echo $lambdas -> triple(2); // prints 6
Dirty and dangerous, but you might succeed using eval..
class foo
{
private $call_back_1 = null;
private $call_back_2 = null;
function __construct($func1, $func2)
{
$this->call_back_1 = func1;
$this->call_back_2 = func2;
}
function provokeCallBacks()
{
eval($this->call_back_1);
eval($this->call_back_2);
}
}
call1 = 'echo "inside call 1"';
call2 = 'echo "inside call 2"';
$test = foo(call1, call2);
$test->provokeCallBacks();
I know your question has been answered but you can try changing your approch ..
class Foo {
private $calls = array();
function __set($key, $value) {
$this->calls[$key] = $value;
}
function __call($name, $arg) {
if (array_key_exists($name, $this->calls)) {
$this->calls[$name]();
}
}
function __all() {
foreach ( $this->calls as $call ) {
$call();
}
}
}
$test = new Foo();
$test->A = function () {
echo "inside call 1";
};
$test->B = function () {
echo "inside call 2";
};
$test->A(); // inside call 1
$test->B(); // inside call 2
$test->__all(); // inside call 1 & inside call 2
Related
I don't know what is this call system.
For example:
$a = SameClass::fnc1()->fnc2('input')->fnc2();
and we can see this method in jQuery:
$("#selector").parent().css('left',5).fadeOut(1500);
I don't have any idea to write this codes structure in PHP.
You just need to return object from a function
For example
class First
{
public function funcFirst()
{
$obj = new Second;
return $obj;
}
}
class Second
{
public function funcSecond($message)
{
return $message;
}
}
$first = new First;
$message = "Hello";
$result = $first->funcFirst()->funcSecond($message); // 'Hello'
I have a question close to this:
How to create constructor with optional parameters?
It is clear that we can make optional params like this:
function myFunction($param='hello')
but I want to use it in a class's method with $this->something instead of 'hello', it looks like this:
public function myFunction($param=$this->property)
but I get a:
Parse error: syntax error, unexpected '$this'
Is it possible to get it?
you need to set to null and check afterward
class example {
private $something = "something";
public function myFunction($a = null)
{
if($a === null)
$a = $this->something;
// more code goes here
return $a;
}
}
$test = new example();
print $test->myFunction();
// prints "something"
print $test->myFunction("hello");
// prints "hello"
You can do it like this
$Obj = new myclass();
class myclass{
var $data = 'tested';
function __construct(){
$this->testFunction();
}
public function testFunction($param = null){
if( $param == '' || $param == null){
$param = $this->data;
}
echo $param;
}
}
My class is like this:
<?php
class ExampleClass{
private $example_property = false;
public function __construct(){
$this->example_property = function() {
$this->example_property = 1;
return $this->example_property;
};
}
public function get_example_property(){
return $this->example_property;
}
}
$example = new ExampleClass();
echo $example->get_example_property();
Property $example_property must be false until you call it, then, the first time it is called, I want to assign 1 to it. What's wrong with my code?
Error: Error Object of class Closure could not be converted to string on line number 20.
I just tried to play a little bit with your code.
To make it possible, you'll have to find out, whether your variable is a function (defined in your __construct) or the number set by this function
<?php
class ExampleClass{
private $example_property = false;
public function __construct(){
$this->example_property = function() {
$this->example_property = 1;
return $this->example_property;
};
}
public function get_example_property(){
$func = $this->example_property;
if(is_object($func) && get_class($func)=='Closure'){
return $func();
}
return $func;
}
}
$example = new ExampleClass();
echo $example->get_example_property(); //returning 1
echo $example->get_example_property(); //returning 1 again
But anyway, I don't see any sense in doing this.
The typical solution would be something like this:
class ExampleClass{
private $example_property = false;
public function __construct(){
//usually initializing properties goes here.
//$this->example_property = 1;
}
public function get_example_property(){
// I think you want a value to be initialzed only if needed.
// so then it can go here.
if(!$this->example_property) {
$this->example_property = 1; //initialize it, if needed
}
return $this->example_property;
}
}
$example = new ExampleClass();
echo $example->get_example_property(); //returning 1
echo $example->get_example_property(); //returning 1 again
i have something like this:
class foo
{
//code
}
$var = new foo();
$var->newVariable = 1; // create foo->newVariable
$var->otherVariable = "hello, im a variable"; //create foo->otherVariable
i can get in class foo a list of all variables defined outside by user (newVariable, otherVariable,etc)? Like this:
class foo
{
public function getUserDefined()
{
// code
}
}
$var = new foo();
$var->newVariable = 1; // create foo->newVariable
$var->otherVariable = "hello, im a variable"; //create foo->otherVariable
var_dump($var->getUserDefined()); // returns array ("newVariable","otherVariable");
Thanks!.
Yes, using get_object_vars() and get_class_vars():
class A {
var $hello = 'world';
}
$a = new A();
$a->another = 'variable';
echo var_dump(get_object_vars($a));
echo '<hr />';
// Then, you can strip off default properties using get_class_vars('A');
$b = get_object_vars($a);
$c = get_class_vars('A');
foreach ($b as $key => $value) {
if (!array_key_exists($key,$c)) echo $key . ' => ' . $value . '<br />';
}
What is your goal? Imo it's not very good practice (unless you really know what you are doing). Maybe it's good idea consider create some class property like "$parameters" and then create setter and getter for this and use it in this way:
class foo {
private $variables;
public function addVariable($key, $value) {
$this->variables[$key] = $value;
}
public function getVariable($key) {
return $this->variables[$key];
}
public function hasVariable($key) {
return isset($this->variables[$key]);
}
(...)
}
$var = new foo();
$var->addVariable('newVariable', 1);
$var->addVariable('otherVariable', "hello, im a variable");
And then you can use it whatever you want, for example get defined variable:
$var->getVariable('otherVariable');
To check if some var is already defined:
$var->hasVariable('someVariable')
get_class_vars() http://php.net/manual/en/function.get-class-vars.php
You question is not clear though.
$var->newVariable = 1;
there are two possible contex of above expression
1) you are accessing class public variables.
like
class foo
{
public $foo;
public function method()
{
//code
}
}
$obj_foo = new foo();
$obj_foo->foo = 'class variable';
OR
2) you are defining class variable runtime using _get and _set
class foo
{
public $foo;
public $array = array();
public function method()
{
//code
}
public function __get()
{
//some code
}
public function __set()
{
// some code
}
}
$obj_foo = new foo();
$obj_foo->bar= 'define class variable outside the class';
so in which context your question is talking about?
How can i pass a class as a parameter in my function
So far i've tried
$sc = new SampleClass();
SampleFunction($sc);
function SampleFunction(&$refClass)
{
echo $refClass->getValue();
}
this is a simplified example of what im doing.. i actually have to do complex procedures inside this sample function. I'm not getting any response from the sample function. What am i doing wrong? thank you
UPDATE
char.php
class Charss {
var $name=0;
var $hp=500;
var $spd=10;
var $rtime=10;
var $dmg=10;
function __construct( $name, $hp, $spd, $rtime , $dmg) {
$this->name = $name;
$this->hp = $hp;
$this->spd = $spd;
$this->rtime = $rtime;
$this->dmg = $dmg;
}
function get_name() {
return $this->name;
}
function set_name($new_name) {
$this->name = $new_name;
}
function get_hp() {
return $this->hp;
}
function set_hp($new_hp) {
$this->hp = $new_hp;
}
function get_spd() {
return $this->spd;
}
function set_spd($new_spd) {
$this->spd = $new_spd;
}
function get_rtime() {
return $this->rtime;
}
function set_rtime($new_rtime) {
$this->rtime = $new_rtime;
}
function get_dmg() {
return $this->get_dmg;
}
function set_dmg($new_dmg) {
$this->dmg = $new_dmg;
}
}
myclass.php
require("char.php");
class Person {
function try_process()
{
$chr1 = new Charss("Player1",500,3,0,50);
$chr2 = new Charss("Player2",500,6,0,70);
while ($chr1->get_hp() > 0 && $chr2->get_hp() > 0)
{
$sth = min($chr1->get_rtime(), $chr2->get_rtime());
if ($chr1->get_rtime() == 0 && $chr2->get_rtime() > 0)
{
exit;
Fight($chr1,$chr2);
$chr1->set_rtime($chr1->get_spd());
}
elseif ($chr2->get_rtime() == 0 && $chr1->get_rtime() > 0)
{
Fight($chr2,$chr1);
$chr2->set_rtime($chr2->get_spd());
}
else
{
Fight($chr1,$chr2); #having trouble with this
$chr1->set_rtime($chr1->get_spd());
}
$chr1->set_rtime($chr1->get_rtime() - $sth);
$chr2->set_rtime($chr2->get_rtime() - $sth);
}
}
function Fight($atk,$def)
{
$def->set_hp($def->get_hp() - $atk->get_dmg());
echo $atk->get_name() . " attacked " . $def->get_name() . " for " . $atk->get_dmg() . " damage";
}
}
so im calling the function try_process on button click
What you're actually doing there is passing an object, not a class.
$sc = new SampleClass();
creates an instance of SampleClass, aka an object.
I assume there's some error being thrown elsewhere as what you have is correct.
I tested the following code and got the expected output:
class SampleClass
{
public function getValue()
{
return 4;
}
}
$sc = new SampleClass();
SampleFunction($sc);
function SampleFunction(&$refClass)
{
echo $refClass->getValue();
}
Output: 4
If you provide more details of your actual code we might be able to determine the problem.
I can't see anything wrong with your code
using &$refClass is however is not recommended and I guess willbe removed from future iteration of PHP version
but here is an example
class objects are passed as reference I suppose so no need of '&'
http://ideone.com/GbmUy
Why is the function argument a reference? Probably shouldn't be.
Other than that, there's nothing wrong with you posted, so the error is likely within SampleClass.
Others have answered pretty well, but this is a silly little example to show you how to modify the class (either by calling a property setter, or setting public properties directly)
class foo {
private $member1;
public $member2;
public function __construct($member1,$member2) {
$this->member1=$member1;
$this->member2=$member2;
}
public function SetMember1($value) {
$this->member1 = $value;
}
public function GetMember1() {
return $this->member1;
}
}
function SetMembers(foo $obj, $member1, $member2) {
// Call a setter
$obj->SetMember1($member1);
// Set a member variable directly
$obj->member2 = $member2;
}
$obj = new foo('default member 1', 'default member 2');
echo "member1 (before): {$obj->GetMember1()}\n";
echo "member2 (before): {$obj->member2}\n";
// Change values
SetMembers($obj, 'new member1', 'new member2');
echo "member1 (after): {$obj->GetMember1()}\n";
echo "member2 (after): {$obj->member2}\n";
This will output:
member1 (before): default member 1
member2 (before): default member 2
member1 (after): new member1
member2 (after): new member2