ReflectionClass::getDefaultProperties() and class constants - php

I am using Reflection against the following class:
class Constant {
const CONSTANT = 3;
public $test1 = 'CONSTANT';
public $test2 = CONSTANT;
}
When using ReflectionClass::getDefaultProperties(); I get the following notice:
PHP Notice: Use of undefined constant CONSTANT - assumed 'CONSTANT'
on this line of code:
$defaultValues = $reflectionClass->getDefaultProperties();
First, I wonder why I get the notice here (I mean, I can't anticipate/avoid the notice even though the code is 100% correct)?
And second, when using var_export($defaultValues[3]), it outputs 'CONSTANT' which is normal because it has been casted to string.
So, how can I output CONSTANT instead of 'CONSTANT' for $test2 and still output a quote-delimited string for $test1?
Edit: I get CONSTANT for both cases ($test1 and $test2) but because of that I can't differentiate between them. I want to be able to know: that is a string, or that is the name of a constant.

why I get the notice here?
because you mean self::CONSTANT but tried to use global CONSTANT, e.g. your code assumes
const CONSTANT = 3; // global constant
class Constant {
const CONSTANT = 3; // class constant
public $test1 = 'CONSTANT';
public $test2 = CONSTANT; // refers to global constant
}
but you wanted to do this:
class Constant {
const CONSTANT = 3;
public $test1 = 'CONSTANT';
public $test2 = self::CONSTANT; // self indicated class scope
}
With the latter, this
$reflectionClass = new ReflectionClass('Constant');
var_dump( $reflectionClass->getDefaultProperties() );
will give
array(2) {
["test1"]=>
string(8) "CONSTANT"
["test2"]=>
int(3)
}
Is there a way to get ["test2"] => self::CONSTANT via Reflection? No. The Reflection API will evaluate the constant. If you want self::CONSTANT you'd have to try some of the 3rd party static reflection APIs.
And obviously, if you want 'CONSTANT', write "'CONSTANT'".
Regarding EDIT:
I get CONSTANT for both cases ($test1 and $test2) but because of that I can't differentiate between them. I want to be able to know: that is a string, or that is the name of a constant.
$foo = CONSTANT means assign the constant value to the foo property. It does not mean assign the constant itself. By assigning the value to a property, it no longer is a constant value. It's mutable. The "name of a constant" is represented as a string. You can use ReflectionClass::hasConstant to check whether that string happens to also be the name of a defined constant in the class or use defined for global constants.

Since you use CONSTANT for the value of $test2 and do not define it before it will throw the "undefined constant" error. Do you want to use the class constant CONSTANT as value for the public $test2? Then use public $test2 = self::CONSTANT. Otherwise define CONSTANT as constant before the class.
Please note that PHP casts all unknown constants as strings with the value of the name of the unknown constant.

Related

"Access to undeclared static property: App\FieldCategory::$fieldCategories"

I'm trying to get value of static variable that is defined in a FieldCategory model.But i'm getting error if i try to access the constant from a crontroller.
Here is code
$fieldCategories = FieldCategory::find(1)->first()->constants;
$test=FieldCategory::$fieldCategories;
$fieldCategories contains a value that is the name of a constant declared in model.But its giving the following error
"Access to undeclared static property: App\FieldCategory::$fieldCategories"
If you want to use the value of $fieldCategories as the constant name, you need to use
echo constant("FieldCategory::$fieldCategories");
With FieldCategory::$fieldCategories PHP will think you are trying to access a static property, which obviously is not a constant.
Example:
class Foo {
const BAR = 42;
}
$prop = 'BAR';
echo constant("Foo::$prop");
See http://php.net/manual/en/function.constant.php
Can you please check this solution I hope it will work for you.
$data=constant("App\FieldCategory::{$fieldCategories}");

Cannot initialize an uninitialized variable inside a class method

I have just started practicing OO programming using PHP. Recently I have encountered a problem.
I am trying to declare a variable inside a class, but leaving it uninitialized. Later inside a method of the class when I try to initialize the variable it shows the following errors:
Undefined variable: a in C:\wamp\www\sample.php on line 6
Fatal error: Cannot access empty property in C:\wamp\www\sample.php on line 6
Here is the code that I am trying to execute:
<?php
class Sample{
public $a;
function call($b){
$this->$a = $b;
echo $a;
}
}
$sam = new Sample();
$sam->call(5);
?>
How do I fix this?
In the function call, $a does not exist. Only $this->a (without $ before the a), which is the property of your "sam" object, and $b, which is an input parameter.
Plus when you set the property, you must not use $a. Use $this->a.
If you would have a variable which contains a property name of the class, you should use $this->$a, which would mean $this->asdf, if $a = 'asdf';
The correct syntax is $this->a, not $this->$a.

error when using variable class name and static method

Running PHP 5.4, so I wasn't expecting this, but I'm encountering the following error:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
Assume you have a variable of stdClass setup as follows:
$this->variable = new stdClass();
$this->variable->other = array('class' => 'helloworld');
Now, assume you want to access a static method of class helloworld:
// Standard call
$x = helloworld::my_static_method();
// Call with variable class name
$x = $this->variable->other['class']::my_static_method();
When calling the above using the variable class name, I receive the parsing error. What's odd, is that if I do the following, no error is presented:
$class = $this->variable->other['class'];
$x = $class::my_static_method();
To me this seems very odd, can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
The PHP parser does not support such a syntax, and that's merely all. This is because the parser has grown historically. I can't give more reason than that.
It will be that with PHP 7 you can see some changes on these syntax details working more into your expected direction Uniform Variable Syntax:
($variable->other['class'])::my_static_method();
But until then, you can go around that with the help of call_user_func:
call_user_func([$variable->other['class'], 'my_static_method']);
call_user_func($variable->other['class'] . '::my_static_method');
Or as you wrote your own, by creating a variable:
$class = $variable->other['class'];
$class::my_static_method();
Or even a variable that looks like something different:
${(int)!${0}=$variable->other['class']}::my_static_method();
Related Material:
Interpolation (double quoted string) of Associative Arrays in PHP
This doesn't work ($this->variable->other['class']::my_static_method()) as it's essentially using a string as the class name directly. It works when you assign it to a variable first, as it's then being evaluated out as the class name instead.
You can also look into using ReflectionMethod invocation in order to call the method, in which case you wouldn't have to store the class name in a variable before using it. Here's the docs on that: http://php.net/manual/en/class.reflectionmethod.php and on the invoke method (you pass in NULL to indicate a static method) http://php.net/manual/en/reflectionmethod.invoke.php
Here are a couple examples of ways to invoke your function:
class helloworld{
public static function my_static_method($i = 0){
echo "Here: ".$i;
}
}
class Foo{
private $variable;
public function __construct(){
//Create a new class
$this->variable = new stdClass();
//Create a new property of the class, storing an array
$this->variable->other = array('class' => 'helloworld');
//Call function statically
$x = helloworld::my_static_method(1); //Outputs: "Here: 1"
//Store class name in a variable before use
$class = $this->variable->other['class'];
$y = $class::my_static_method(2); //Outputs: "Here: 2"
//Using a ReflectionMethod, you can call the function this way, too
$z = new ReflectionMethod($this->variable->other['class'], 'my_static_method');
$z->invoke(null, 3); //Outputs: "Here: 3"
}
}
//Instantiate new Foo class
new Foo();

constant vs properties in php?

I just don't get it,
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
class MyClass
{
public $constant = 'constant value';
function showConstant() {
echo $this->constant . "\n";
}
}
Whats the main difference? Its just same as defining vars, isn't it?
Constants are constant (wow, who would have thought of this?) They do not require a class instance. Thus, you can write MyClass::CONSTANT, e.g. PDO::FETCH_ASSOC. A property on the other hand needs a class, so you would need to write $obj = new MyClass; $obj->constant.
Furthermore there are static properties, they don't need an instance either (MyClass::$constant). Here again the difference is, that MyClass::$constant may be changed, but MyClass::CONSTANT may not.)
So, use a constant whenever you have a scalar, non-expression value, that won't be changed. It is faster than a property, it doesn't pollute the property namespace and it is more understandable to anyone who reads your code.
By defining a const value inside a class, you make sure it won't be changed intentionally or unintentionally.
Well, if I do $myClass->constant = "some other value" (given $myClass is an instance of MyClass) in the latter example, then the value is no longer constant. There you have the difference. The value of a constant can not be changed, because... it is constant.

if i define something in a class, how do i call in within the class?

i have something like
define("__ROOT_PATH__", "http://{$_SERVER['HTTP_HOST']}/admin");
within a class. how do i call it from within functions is it with a cologn? i tried looking it up on google but nothing.
thanks
The function define() is intended for global constants, so you just use the string __ROOT_PATH__ (I would recommend using another naming scheme, though. Constants starting with two underscores are reserved by PHP for their magic constants)
define('__ROOT_PATH__', 'Constant String');
echo __ROOT_PATH__;
If you want to declare a class constant, use the const keyword:
class Test {
const ROOT_PATH = 'Constant string';
}
echo Test::ROOT_PATH;
There is one problem though: The class constants are evaluated while your script is being parsed, so you cannot use other variables within these constants (so your example will not work). Using define() works, as it is treated like any other function and the constant value can be defined dynamically.
EDIT:
As PCheese pointed out, you can access class constants using the keyword self, instead of the class name from within the class:
class Test {
const ROOT_PATH = 'Constant string';
public function foo() {
echo self::ROOT_PATH;
}
}
# You must use the class' name outside its scope:
echo Test::ROOT_PATH;
Using define will define the constant globally, so just refer to it directly in your code:
echo __ROOT_PATH__;
If you want to scope a constant to a class, you need to declare it differently. However, this syntax will not let you declare it dynamically as you did above, using $_SERVER.
<?php
class MyClass {
const MY_CONST = "foo";
public function showConstant() {
echo self::MY_CONST;
}
}
// Example:
echo MyClass::MY_CONST;
$c = new MyClass();
$c->showConstant();
Simply use the name of the constant.
i.e.
echo "Root path is " . __ROOT_PATH__;

Categories