Passing an object property into a closure in PHP - php

I am trying to pass an object property into a closure (that's within a method of that object), like so:
class Entity extends ControllerBase {
private $view;
private $events;
public function print($tid) {
self::loadView($tid);
self::loopView();
return (new StreamedResponse(function() use ($this->events){
...
}
}
}
The $events property gets instantiated in the loopView() method. This seems like it should work to me, but I get this error:
ParseError: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ',' or ')' in ...
It seems to be saying it doesn't expect there to be an object referenced in use. I don't know why this isn't valid, and after some googling, I couldn't find anything referencing my specific problem.
In PHP 7.1.7, is it possible to do this, and if so, what is the correct syntax?

You can just use $this->events in the closure without a use statement.
See "Automatic Binding of $this" in the anonymous function documentation.
As of PHP 5.4.0, when declared in the context of a class, the current class is automatically bound to it, making $this available inside of the function's scope.
For example: https://3v4l.org/gYdHp
As far as the reason for the parse error, if we disregard the specific $this case,
function() use ($object->property) { ...
doesn't work because use passes variables from the parent scope into the closure, and
$object->property is not a variable, it is an expression.
If you need to refer to an object property inside a closure, you either need to use the entire object, or assign the property to another variable you can use. But in this case you don't have to worry about that since $this is special.

Related

PHP assigning $this variable to another name

I am sure I've seen once example of assigning $this to another variable, single-letter to make the code typing quicker.
class Dclass {
private $d = $this;
}
But it's not working, is throwing me an error :
Fatal error: Constant expression contains invalid operations in ..
Okay, so from the another post How to handle class variable without $this?
"$this is only available inside functions within the class." #FrankerZ
So this kind of assignment should be done inside the class constructor, or other function?

using functions inside constructors php

In an effort to keep my code clean, I am attempting to replace a whole bunch of code in my constructor with a function. I believe I am calling the function correctly but i'm not able to assign values to the variables as intended.
public function __construct($docID) {
self::getDocumentInfo($docID);
self::getTranscriptionInfo($docID);
}
private static function getTranscriptionInfo($docID) {
$this->documentTranscription = 5;
}
Im getting an error "PHP Fatal error: Using $this when not in object context in ...". This is simplified for postings purpose, but would it be better just have a very large constructor and skip the functions all together? Or is their a better way to assign values?
A static method is not a part of the class instance. The static keyword means the method can be called within your class but it won't have any of the instance variables.
Remove the static keyword and change this:
self::getDocumentInfo($docID);
self::getTranscriptionInfo($docID);
to this:
$this->getDocumentInfo($docID);
$this->getTranscriptionInfo($docID);
Using $this means it will be calling it within the right instance context.
Some info the static keyword (added emphasis in italics):
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static cannot be accessed with an instantiated class object (though a static method can).
Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
Source
http://php.net/manual/en/language.oop5.static.php

Php Array Elements Referenced From Another Array Inside a Class

Inside a class I have 2 associative arrays. I am trying to call elements from one array to be used in another (kind of master) array.
I would like to ask whether the following can be done, or can't, or what I'm doing so wrong;
Please note, the arrays are examples.
class ProductData {
private $texture = [0=>'Cream', 1=>'Powder', 2=>'Liquid', 3=>'Paste', 4=>'Solid'];
private $food = ['type'=>'Pasta', 'info'=>[1=>'750gm', 2=>'$4.50', 3=>$this->texture[4]],
'type'=>'Soup', 'info'=>[1=>'500ml', 2=>'$7.60', 3=>$this->texture[2]]];
// Constructor, Function(s) to access the $food array...
}
Well I have found out the hard way that this cannot be done. I receive a syntax error;
syntax error unexpected '$this' (T_VARIABLE).
If I replace the $this with $texture, I receive the same error;
syntax error unexpected '$texture' (T_VARIABLE).
I'm thinking that this cannot be done, or I'm doing something very wrong, or both.
If this can be done, any assistance is very much appreciated.
Thanks,
njc
class ProductData {
private $texture;
private $food;
function __construct(){
$this->texture = [0=>'Cream', 1=>'Powder', 2=>'Liquid', 3=>'Paste', 4=>'Solid'];
$this->food = ['type'=>'Pasta', 'info'=>[1=>'750gm', 2=>'$4.50', 3=>$this->texture[4]],
'type'=>'Soup', 'info'=>[1=>'500ml', 2=>'$7.60', 3=>$this->texture[2]]];
//other construct stuff
}
}
You can only use constant values to define property values outside class methods. So in your case, you cannot use the $this variable, as it references the current object instance.
You should move the initialisation to the __construct (which is really what is meant to be for)
Check out the documentation:
This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.

What is $this->?

What I think I know so far:
so $this-> is to access a function/var outside its own function/var ?
but how does $this-> know if its a function or a variable ?
why we refer to a var like this $this->data instead of this $this->$data ?
$this refers to the current object that a method has been invoked on. It knows if it's a function if there is a pair of parentheses at the end. We use the former syntax because $this->$data means look at the field whose name is $data; e.g. $this->foo if $data == 'foo'
$this is the variable referring to the object that you are currently inside. $this-> will access either a method or field in the current object.
As for why is it $this->data and not $this->$data, that's just a syntax quirk. You'd have to ask the PHP language designers. It's probably because the latter wouldn't make much sense for a method.
If this looks like Greek to you, then you may want to head over to the PHP manual's section on classes and objects and read up.
$this represents the instance of a given object, from the context of within the object.
I would say, knowing whether you're accessing a method or property is your responsibility. Read documentation. If you're calling an object method using this, it uses the expected syntax of $this->method($args); and properties (member variables) use the expected syntax of $this->var = 'value';
It's a pretty long subject, but in sort, $this is a pointer to an instance. $this->data refers to the data variable of a particular instance(this instance). It is $this->data and not $this->$data just because of convention.

Zend and static class properties

I'm trying to assign a value to a static class property when defining it:
namespace Base;
abstract class Skeleton {
protected static $entityManager = \Zend_Registry::get("EntityManager");
...
}
When I try to execute this code I get this error:
Parse error: syntax error, unexpected '(', expecting ',' or ';' in /var/www/
somewhere/application/models/Base/Skeleton.php on line 6
If I just assign a simple string value to it:
protected static $entityManager = "string";
Everyting is fine. Am I doing something PHP can't handle? If so, how to solve this?
You can't put code that needs executing as a class variable, static or not.
Think about it, at which point does Zend_Registry::get("EntityManager") get executed, it can't be executed when the class is created because you have set it as static.
Even if it was not static, when does Zend_Registry::get("EntityManager") get run? When the object is instantiated or once? It needs to be put in a function inside the class.
Class properties may not depend on data that has to be evaluated at runtime:
[Class member variables] may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
Add a setter and set the value during bootstrap.

Categories