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.
Related
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.
Alright so I think this may be extremely basic, but it has me stumped nonetheless. Before I get to my question, let me demonstrate the concept my question is based on with this working example:
<?php
$a = 'Stack';
$b = $a.' Overflow';
echo $b; // Result: "Stack Overflow"
?>
In the above example, $b is defined as the combination of $a and ' Overflow'.
Now, let's assume I want to do the same thing as above except I don't want to use global variables. I want to use classes. This is how I have attempted to achieve that:
<?php
class ClassName {
public $a = 'Stack';
public $b = $this->a.' Overflow'; // This gives me: "Parse error: syntax error, unexpected '$this'"
}
$instantiate = new ClassName;
echo $instantiate->$b; // Desired result: "Stack Overflow"
?>
As stated, this attempt results in an error. To me, this attempt seems logical, but I guess PHP doesn't think so.
Question: Is this possible, and if so, how do I go about achieving the desired result? Also, if you could explain why my attempt has failed (logically), that would be a bonus.
I've searched and researched for hours on end trying to find an answer or figure this out on my own, but for the life of me, I cannot find anyone or anything that even touches on this (including other Stack Overflow threads). I can't even find anywhere saying it's impossible or anything of the sort either.
I'm a PHP novice, so I may need more explanation than others, but any kind of help or general guidance would be much appreciated. Thank you.
You cannot use $this when defining the class because it refers to a concrete object context which becomes available after instantiation. You can use a constructor for that kinds of stuff.
class ClassName
{
public $a = 'Stack';
public $b = "";
function __construct()
{
$this->b = $this->a.' Overflow';
}
}
$instantiate = new ClassName;
echo $instantiate->b;
Quoting from the PHP Docs about defining class properties
They are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration. 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.
(my emphasis)
Concatenation cannot be evaluated at compile time, only at run time.
If you need to do this, then define the initial value for the property in the constructor
This would throw a syntax error because you are using $this in a scope that it is not allowed to:
The pseudo-variable $this is available inside any class method when that method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object).
This means, even if you wanted you won't be able to do what you want to do because of such restriction. This is a common restriction that is in many programming languages, properties have to be initialized to static values. To solve your issue you can do any of the following:
In your constructor, create those variables.
Create the second variable on its own, and create a method that concatenates the two.
Create a magic method to do it for you.
The same restriction holds true for static class properties.
Why is not possible to initialize a property to a function when you declare the property in php? The following snippit results in a Parse error: syntax error, unexpected T_FUNCTION
<?php
class AssignAnonFunction {
private $someFunc = function() {
echo "Will Not work";
};
}
?>
Yet you can initialize a property to a string, number or other data types?
Edit:
But I can assign a function to a property in the __construct() method. The following does work:
<?php
class AssignAnonFunctionInConstructor {
private $someFunc;
public function __construct() {
$this->someFunc = function() {
echo "Does Work";
};
}
}
?>
Because it is not implemented in PHP.
http://www.php.net/manual/en/language.oop5.properties.php. Quote:
They (properties) are defined by using one of the
keywords public, protected, or
private, followed by a normal variable
declaration. 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.
You cannot initialize properties like this, functions are not constant values. Hence my original answer "it is not implemented".
Why is it not implemented? That I can only guess - it probably is quite a complex task and nobody has stepped up to implement it. And/or there may not be enough demand for a feature like that.
Closures do not exist in PHP until PHP 5.3 (the latest version). Make sure you have PHP 5.3 if you want to do this.
In earlier versions, you can sort of duplicate this functionality with the create_function() function, somewhat like this:
$someFunc = create_function($args,$code);
$someFunc();
Where $args is a string formatted like "$x,$y,$z" and $code is a string of your PHP code.
why does this not work ?
class Test{
private $vars = array('ALL' => 0,
'ONE' => 1);
private $var = $vars['ALL']; // this does not work
function __construct(){
$this->var = $vars['ALL']; // this does work
}
}
code example here: http://codepad.org/QSjHMDij
why is the array not accessible in the statement
private $var = $vars['ALL']; // this does not work
Probably because you can't access $this during the initialization of the class prior to the constructor getting called (which is implied when you tried to do it in the definition for $var.) Some languages (like C#) will let you do it, but I think PHP is one that will not.
Neither "works" in the way you intend. You are not allowed to use variables when declaring instance members (hence the unexpected T_VARIABLE error). In the constructor you are referencing a local variable named $vars which does not exist, meaning you're setting $this->var to NULL.
Access the instance member by doing $this->vars. You can only do this in the constructor.
When declaring members (variables), you can't assign array key values of other members, it causes a parse error.
For example, you're thinking (wrong) that $vars['ALL'] is referring to your private $var - which it is not - it also causes a parse error. There's no way for PHP to know that when you say:
private $var = $vars['ALL'];
that you're actually saying "I want value of $this->vars['ALL'] to be assigned to $this->var", at least not the way you wrote it. That's why you do that from within a function, where you can easily manipulate members, such as you did from the constructor.
You should declare members, their visibility and set some default values (like you did for $var), but you shouldn't point them to other members' values, it's simply - wrong and luckily - it doesn't work :)
You're trying to assign a value to a variable which is designed to be part of an object, rather than the class. What you want is static variables.
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.