How to Call a Closure That Is a Class Variable

How to call a closure that is a class variable?

In PHP, methods and properties are in a separate namespace (you can have a method and a property with the same name), and whether you are accessing a property or a method depends of the syntax you are using to do so.

$expr->something() is a method call, so PHP will search something in the class' list of methods.

$expr->something is a property fetch, so PHP will search something in the class' list of properties.

$myInstance->lambda(); is parsed as a method call, so PHP searches for a method named lambda in your class, but there is no such method (hence the Call to undefined method error).

So you have to use the fetch property syntax to fetch the lambda, and then call it.

  • Since PHP 7.0, you can do this with ($obj->lambda)():

    ($obj->lambda)();

    The parentheses make sure that PHP parses ($obj->lambda) as fetch the property named lambda. Then, () calls the result of fetching the property.

  • or you can do this with ->lambda->__invoke():

    $myInstance = new MyClass();
    $myInstance->lambda->__invoke();

    __invoke is one of PHP's magic methods. When an object implements this method, it becomes invokable: it can be called using the $var() syntax. Anonymous functions are instances of Closure, which implements __invoke.

  • Or assign it to a local variable:

    $lambda = $myInstance->lambda;
    $lambda();
  • Or call it using call_user_func:

    call_user_func($myInstance->lambda);

    call_user_func can call any callable, including anonymous functions.

  • Alternatively, if this is a common pattern in your code, you can setup a __call method to forward calls to your lambda:

    class MyClass
    {
    private $lambda;

    public function __construct()
    {
    $this->lambda = function() {
    echo "Hello world!\n";
    };
    }

    public function __call($name, $args)
    {
    return call_user_func_array($this->$name, $args);
    }
    }

    Now this works:

    $myInstance = new MyClass();
    $myInstance->lambda();

    Since PHP 5.4 you can even do that in a trait:

    trait LambdasAsMethods
    {
    public function __call($name, $args)
    {
    return call_user_func_array($this->$name, $args);
    }
    }

    class MyClass
    {
    use LambdasAsMethods;

    private $lambda;

    public function __construct()
    {
    $this->lambda = function() {
    echo "Hello World!\n";
    };
    }
    }

    $myInstance = new MyClass();
    $myInstance->lambda();

How to access a class's variable inside a closure?

If you need to use global variable/method in closure put self. before your variable/method

So you can replace this

saleOrder = saleEdited

with

self.saleOrder = saleEdited

but it looks that problem is also somewhere else. You just need to pass saleOrder from first to second ViewController where you edit it and then pass data back to first view controller

So, first delete unneccessary code from ViewControllerData:

let funcReturnFromEdit = { (saleEdited : SaleOrder) -> () in
saleOrder = saleEdited // I can't do this.
}

and to fix completion handler in ViewControllerEdit replace

var funcReturn = { (SaleOrder) -> Void in {} }

with

var funcReturn : ((SaleOrder) -> ())?

also edit your endEditions method because funcReturn is optional

func endEditions() {
funcReturn?(saleOrderToEdit)
}

Now just in your ViewControllerData fix prepare method to set what should be done when user call funcReturn from ViewControllerEdit

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueEditOrder" {
let editVc = segue.destination as! ViewControllerEdit
if let saleOrderToPass = saleOrder {
editVc.saleOrderToEdit = saleOrderToPass
editVc.funcReturn = { saleEdited in
self.saleOrder = saleEdited //This code is executed when you call funcReturn?(saleOrderToEdit) from ViewControllerEdit
}
}
}
}

How do I bind a closure to a static class variable in PHP?

  • Change your property to be static static $closure;
  • Wrap your callable in brackets (self::$closure)(2);

http://sandbox.onlinephpfunctions.com/code/d41490759cac39b8459e396b3acf99bf22c65a68

<?php

class A
{
static $closure;

public static function myFunc($input): string
{
$output = $input . ' is Number';
return $output;
}

public static function closure(): Closure
{
return function ($input) {
return self::myFunc($input);
};
}

public static function run()
{
$closure = self::closure();
echo $closure(1); // 1 is Number

self::$closure = $closure;

// Wrap your callable in brackets
echo (self::$closure)(2);
}
}

A::run();

How to invoke a PHP closure which is assigned to a class variable?

You need to use __invoke() to call a closure with the $foo() syntax.

A simple example:

class MyClass {
public static $closure;

function myFunction() {
self::$closure = function($a) { echo $a; };
self::$closure->__invoke(123);
}
}

$class = new MyClass;
$class->myFunction();

This will print out 123 :)

PHP: Using globally defined closure in a class method

Because $this->globalfunction is a variable, not a method, you need to wrap it in parentheses to force PHP to evaluate $this->globalfunction before attempting to call it as a function i.e.

function testFunc(){
($this->globalFunction)('a');
}

Output:

works a

Demo on 3v4l.org

How to access a class variable inside a closure in nodejs?

You can use an arrow function, this will preserve the reference to 'this' of run() inside the callback

const { EventEmitter } = require("events");

const b = new EventEmitter()

class A {
constructor() {
this.a = "hello i am a"
}
run() {
b.on("event", (data) => {
console.log(this.a)
})
}
}

const classA = new A();

classA.run()

b.emit("event");

Swift: Closure as a init argument in a class variable

Here is as close as I could get to what you wanted by fiddling around in a playground. I had to change the types to match what you were passing to Calculator

class Calculator {
private let estimateChanged:() -> Void

init(_ estimateChanged:() -> Void) {
self.estimateChanged = estimateChanged
}
}

class AnotherClass {
lazy var callback: () -> Void = { [unowned self] in
self.loadEstimate()
}
var calculator: Calculator?

// viewDidLoad in the case of a view controller
init() {
calculator = Calculator(callback)
}

func loadEstimate() {}
}

It is obviously not exactly what you wanted but it compiles. There seem to be issues when trying to refer to self in an un-initialized object (even when it seems you should be able to because you specify lazy and weak or unowned etc)

Creation of a closure as class variable in constructor of Eloquent Model

Override setAttribute and getAttribute on your model:

protected $closures = [];

public function setAttribute($key, $value)
{
if ($value instanceof \Closure)
{
$this->setClosureProperty($key, $value);
}

parent::setAttribute($key, $value);
}

public function getAttribute($key)
{
if (array_key_exists($key, $this->closures)
{
return $this->closures[$key];
}

return parent::getAttribute($key);
}

public function setClosureProperty($key, \Closure $value)
{
$this->closures[$key] = $value;
}

This way the cloures won't be saved in the attributes array, thus won't be saved and cast to string.



Related Topics



Leave a reply



Submit