Basically what I want to do is this
class A {
public $prop = new stdClass;
}
And PHP is telling me I can't do this:
PHP Parse error: syntax error, unexpected 'new' (T_NEW) in - on line ##
What's up with that? I know that you basically can't assign a function's return value to a property in initialization, but can someone explain why is that, like the technical stuff. Thanks in advance!
Try to use class constructor:
class A {
public $prop;
public function __construct(){
$this->prop = new stdClass;
}
}
PHP manual says:
Declaration of properties 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.
class variables must be initialized with static values, e.g.
public $prop = 7; // ok
public $prop = 7+7; // ok - can be evaluated at compile time
public $prop = new stdClass; // bad, dynamic result.
public $prop = get_some_value(); //also bad, dynamic result not available at compile time
Related
I have the following code in my User class:
class User {
public int $id = 0;
public string $code;
public string $name;
}
When assigning $code from the database, I need to find out what type the var is before I can assign it, so I use gettype(), in the __construct function for User:
foreach($data as $key => $val) {
settype($val, gettype($this->$key));
$this->$key = $val;
}
However it returns this error:
Fatal error: Uncaught Error: Typed property User::$code must not be accessed before initialization
I understand what the error message means.
Is there a way to find out the casted type of the variable before its been set?
I'm not sure what exactly you are attempting to do, and without knowing more about the whole thing I won't risk an opinion about the logic of it.
Putting that aside, using gettype() on an uninitialized typed property won't work, because the property has effectively no value at that point.
But, since the property is typed, you could get the property defined type via reflection:
class User {
public int $id = 0;
public string $code;
public string $name;
public function __construct() {
$reflect = new ReflectionClass($this);
$props = $reflect->getProperties();
foreach ($props as $prop) {
echo $prop->getType()->getName(), "\n";
}
}
}
new User();
The above would output:
int
string
string
Doing this on the fly seems like a lot of overhead, so please make sure that there is no better tool at your disposal. Doing this kind of thing on the __construct() method does not look very wise at first sight, but of course I do not know your specific constraints.
If you create a variable as
$foo;
then it is null until it is successfully initialized, so it has no type.
If it is a typed property, then it is simply uninitialized, not null. The rest of my answer contains some experiments conducted based on the information received in the comment-section. So, a variable or property is null before it is initialized, with the exception of typed properties, which are simply uninitialized.
In the comment section it was suggested that the uninitialized variable does not equal to null. So I have written this test code:
<?php
$foo;
echo var_dump($foo === null);
and executed it
It gives a warning and evaluates to true, so the uninitialized variable was indeed null.
Since yivi pointed out that the question refers to a property, I have conducted another experiment:
<?php
class Foo {
public $foo;
public function __construct() {
echo var_dump($this->foo === null);
}
}
new Foo();
and the result is
Braking my head over this.
I’m trying to assign a date() function to a property of foo() class like that.
class Foo{
public $dt = date("F-d-Y H:j:s");
function today(){} //just some empty method
};
$g = new Foo();
echo $g->dt;
I get Parse error: syntax error, unexpected '(', expecting ',' or ';' //this is date() line
I also tried that.
class Foo{
public $dt;
function today(){
echo $this->dt = date("F-d-Y H:j:s");
}
};
$g = new Foo();
$g->today();
No errors and everything works fine. So, seems to me, that we can't assign date() to a class property directly.
Please point me to a right direction. Thanks in advance.
If you provide an initialization of a class property, it has to be a constant, not a function call. If you want to compute the initial value, do it in the class constructor method.
class Foo {
public $dt;
function __construct() {
$this->dt = date("F-d-Y H:j:s");
}
}
$g = new Foo();
echo $g->dt;
From the PHP 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.
i have this code:
protected $val = Zend_Registry::get('values');
Whenever I put this piece of code I get:
Parse error: syntax error, unexpected '(', expecting ',' or ';' in ...
Why is it happening?
You cannot use a function call or other dynamic expression to initialize a class property. It can only be a constant or atomic value. If you need to initialize it with a function call, you must do this instead inside the constructor.
protected $val = NULL;
public function __construct() {
$this->val = Zend_Registry::get('values');
}
From the docs:
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 can not use the return-value of a function for the initial value of a class-variable.
You can however set it in the constructor of the class.
class Myclass{
protected $val;
public function __construct(){
$this->val = Zend_Registry::get('values');
}
}
Because that looks like a class variable and you cant assign data to a class variable like that.
See here http://www.php.net/manual/en/language.oop5.properties.php
You could do it like this.
class something {
protected $_val;
public function __construct()
{
$this->_val = Zend_Registry::get('values');
}
}
I'd like to do something like this:
public static function createDynamic(){
$mydynamicvar = 'module';
self::$mydynamicvar = $value;
}
and be able to access the property from within the class with
$value = self::$module;
I don't know exactly why you would want to do this, but this works. You have to access the dynamic 'variables' like a function because there is no __getStatic() magic method in PHP yet.
class myclass{
static $myvariablearray = array();
public static function createDynamic($variable, $value){
self::$myvariablearray[$variable] = $value;
}
public static function __callstatic($name, $arguments){
return self::$myvariablearray[$name];
}
}
myclass::createDynamic('module', 'test');
echo myclass::module();
static variables must be part of the class definition, so you can't create them dynamically. Not even with Reflection:
chuck at manchuck dot com 2 years ago
It is important to note that calling ReflectionClass::setStaticPropertyValue will not allow you to add new static properties to a class.
But this looks very much like a XY Problem. You probably don't really want to add static properties to a PHP class at runtime; you have some use case that could be fulfilled also that way. Or that way would be the fastest way, were it available, to fulfill some use case. There well might be other ways.
Actually the use cases below are yet again possible solutions to some higher level problem. It might be worth it to reexamine the high level problem and refactor/rethink it in different terms, maybe skipping the need of meddling with static properties altogether.
I want a dictionary of properties inside my class.
trait HasDictionary {
private static $keyValueDictionary = [ ];
public static function propget($name) {
if (!array_key_exists($name, static::$keyValueDictionary) {
return null;
}
return static::$keyValueDictionary[$name];
}
public static function propset($name, $value) {
if (array_key_exists($name, static::$keyValueDictionary) {
$prev = static::$keyValueDictionary[$name];
} else {
$prev = null;
}
static::$keyValueDictionary[$name] = $value;
return $prev;
}
}
class MyClass
{
use Traits\HasDictionary;
...$a = self::propget('something');
self::propset('something', 'some value');
}
I want to associate some values to a class, or: I want a dictionary of properties inside some one else's class.
This actually happened to me and I found this question while investigating ways of doing it. I needed to see, in point B of my workflow, in which point ("A") a given class had been defined, and by what other part of code. In the end I stored that information into an array fed by my autoloader, and ended up being able to also store the debug_backtrace() at the moment of class first loading.
// Solution: store values somewhere else that you control.
class ClassPropertySingletonMap {
use Traits\HasDictionary; // same as before
public static function setClassProp($className, $prop, $value) {
return self::propset("{$className}::{$prop}", $value);
}
public static function getClassProp($className, $prop) {
return self::propget("{$className}::{$prop}");
}
}
// Instead of
// $a = SomeClass::$someName;
// SomeClass::$someName = $b;
// we'll use
// $a = ClassPropertySingletonMap::getClassProp('SomeClass','someName');
// ClassPropertySingletonMap::setClassProp('SomeClass','someName', $b);
I want to change, not create, an existing property of a class.
// Use Reflection. The property is assumed private, for were it public
// you could do it as Class::$property = $whatever;
function setPrivateStaticProperty($class, $property, $value) {
$reflector = new \ReflectionClass($class);
$reflector->getProperty($property)->setAccessible(true);
$reflector->setStaticPropertyValue($property, $value);
$reflector->getProperty($property)->setAccessible(false);
}
Static properties must be defined in the class definition. Therefore, real static properties cannot be created dynamically like regular properties.
For example, if you run this:
<?php
class MyClass
{
public static function createDynamic()
{
$mydynamicvar = 'module';
self::$mydynamicvar = $value;
}
}
MyClass::createDynamic();
var_dump(MyClass::$mydynamicvar);
var_dump(MyClass::$module);
...you'll get this error
Fatal error: Access to undeclared static property: MyClass::$mydynamicvar test.php on line 8
Notice how the error occurs on line 8 when trying to set the property instead of line 14 or 15 (as you might expect if you were simply doing it wrong and dynamically creating static properties was actually possible).
A related problem that IS possible (in PHP 5.4.0 and up) is to include various separate groups of static variable or constant declarations and group them together into one class declaration.
Here is an example:
trait Added1 // This can be located in one Include file
{
static
$x="hello"; // Can declare more variables here
}
trait Added2 // This can be located in another Include file
{
static
$y="world"; // Can declare more variables here
}
class G // Global constant and variable declarations class
{
use Added1, Added2; // Combines all variable declarations
}
echo G::$x." ".G::$y; // Shows "hello world" on the web page
I have built a class in PHP and I must declare a class variable as an object. Everytime I want to declare an empty object I use:
$var=new stdClass;
But if I use it to declare a class variable as
class foo
{
var $bar=new stdClass;
}
a parse error occurs. Is there a way to do this or must I declare the class variable as an object in the constructor function?
PS: I'm using PHP 4.
You can only declare static values this way for class members, i.e. ints, strings, bools, arrays and so on. You can't do anything that involves processing of any kind, like calling functions or creating objects.
You'll have to do it in the constructor.
Relevant manual section:
In PHP 4, only constant initializers for var variables are allowed. To initialize variables with non-constant values, you need an initialization function which is called automatically when an object is being constructed from the class. Such a function is called a constructor (see below).
Classes and Objects (PHP 4). A good read everytime!
You should not create your object here.
You should better write setter and getter
<?php
class foo
{
var $bar = null;
function foo($object = null)
{
$this->setBar($object);
}
function setBar($object = null)
{
if (null === $object)
{
$this->bar = new stdClass();
return $this;
}
$this->bar = $object;
return $this;
}
}
By the way, you should use PHP5 to work with OOP, which is more flexible...