PHP - Referencing constants in separate class - php

I am new to php so please bear with me here.
I have created a class that holds a number of constants that need to be available globally to the app I am developing. However, I don't know how I can load or reference them from another class. Ideally, I would like to load in or reference the class with the constants as an array and then be able to loop through the constants to perform operations with them. Here is the structure of my constant class:
<?php
class MyConstClass {
const CONST_1 = "blah";
const CONST_2 = "blahblah";
const CONST_3 = "blahblahblah";
}
?>
Answers greatly appreciated.

Elaborate on the array concept, but just to access the constant:
echo MyConstClass::CONST_1;

If your class file is included then you can simply access values of constants like #AbraCadaver showed:
MyConstClass::CONST_1
If you want an array of constant values then I'm afraid you'll have to manually define it like this:
$constants = array(
MyConstClass::CONST_1,
MyConstClass::CONST_2,
MyConstClass::CONST_3,
);
foreach ($constants as $constant) {
// do something with $constant value
// ...
}
Or alternatively you can use reflection to list constants in a class:
$reflection = new \ReflectionClass('MyConstClass');
$constants = $reflection->getConstants();
foreach ($constants as $name => $value) {
// do something with $constant value
// ...
}
However, remember that reflection is always slow.

Related

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();

PHP Object References?

I've read up about PHP variable references but I'm not 100% and was hoping someone could help.
If I have a class like the following:
class Item
{
public $value;
}
I then have an array of those items in a variable - lets call that $items. All I did was new Item()...and $items[] = $newItem;.
Now, I want to populate another array but it filters the original array based on its value. So like the following:
foreach($items as $key => $value)
{
$filteredItems[] = &value;
}
Now, I have ANOTHER variable that iterates over that filtered list and does something like so:
$theItem = $filteredItems[10];
$theItem->value = 100;
Now this is where I'm confused. Do I need to set $theItem to &filteredItems[10]; (reference) or will it just know that the value in the array is a reference type and $theItem also becomes a reference to that same item? I'm after that last set of $theItem->value = 100; changes the very original object stored in the $items list.
In PHP 5 objects are always passed around by their "handle" for lack of better word. This means if you do this:
$a = new Item();
$a->value = 1;
$b = $a;
$b->value++;
echo $a->value;
The value of 2 is echoed. Why? Because the handle of the object is copied from $a to $b and they both point to the same object. This isn't a reference in terms of using &, but behaves similarly enough to the point that people generally call it the same thing... even though it's not.
So you do not need any use of references in your code. Usually in PHP, you never need to use references when using objects.
With respect to objects, you really only notice references if you do this (assign a new value to the variable itself):
function foo(Item &$a)
{
$a = null;
}
$b = new Item();
foo($b);
var_dump($b);
This results in NULL, which wouldn't happen without a reference. But again, this is not typical usage, so you can really forget about using references with objects.
(And of course the use of a function isn't necessary here to illustrate the point, but that's the most typical place you'll see them in the "real world.")
It's like this:
foreach($items as $key => &$value) {
$filteredItems[] = $value;
}
The point where you give the original instance into a different scope is where you put the &.
Same is for functions:
function myFunction(&$variable) { }
Example:
<?php
class test {
public $testVar;
public function __construct() {
$this->testVar = "1";
}
}
function changeByReference(&$obj) {
$obj->testVar = "2";
}
$instance = new test();
// Prints 1
echo $instance->testVar, PHP_EOL;
changeByReference($instance);
// Prints 2
echo $instance->testVar, PHP_EOL;
Read more about it here: http://php.net/manual/en/language.oop5.references.php
If you want to copy an instance, use clone - php.net/clone
The easiest way to get it is when you know the difference between these: class, object and instance. (I'd explain it more at this point but it would only confuse you more because my english is not accurate enough for now to explain the details enough.)

PHP: Is code like this possible?

I'm trying to have a user-defined list of game-maps. Because I don't know how many maps will be in the array at design time, I'm trying to dynamically create new variables to contain them. Is this even possible? Here's my failed attempt:
<?php
$maplist=array("map1.aamap.xml","map2.aamap.xml"); //edit this list with your maps
$rounds = 3; //times to play each map
/*======No need to edit below========*/
global $last; //store the last played map
class Map
{
public $difficulty;
public $played; //amount of times played
}
foreach($maplist as $i => $element)
{
$element = $map[$i];
$map[$i] = new Map();
}
//snipped other code here
$map[$i]->$played = $x++; //increment the times played counter <-- FAILS HERE
?>
Parser says: Fatal error: Cannot access empty property
Is something like this even feasible in this manner?
There are some errors in your code:
<?php
$maplist=array("map1.aamap.xml","map2.aamap.xml"); //edit this list with your maps
$rounds = 3; //times to play each map
/*======No need to edit below========*/
global $last; //store the last played map
Since you are on the global scope here, not inside a function, there is no need for global.
class Map
{
public $difficulty;
public $played; //amount of times played
}
foreach($maplist as $i => $element)
{
$element = $map[$i];
Is some code missing here? You are not using $element within the loop, so this assignment is not needed.
$map[$i] = new Map();
}
//snipped other code here
$map[$i]->$played = $x++; //increment the times played counter <-- FAILS HERE
The syntax to access a member variable is $object->variable, not $object->$variable. The latter one will evaluate $variable and use the value as variable name (E.g., if $variable = "foo", this will try to access $object->foo).
Use $map[$i]->played = $x++; instead.
When accessing the properties of a class, you don't want to use the $ in front of the property name itself.
Replace $map[$i]->$played = $x++; with $map[$i]->played = $x++; to solve the Fatal error: Cannot access empty property error.
You could override the magic methods to provide dynamic properties if you wish:
public function __get($name)
{
...
}
public function __set($name, $value)
{
...
}
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
Within each of these functions you could store the data in some internal array structure.
You don't have to use the $ when accessing properties of an instance. Simple use $map[$i]->played. Have a look on the OOP basics.

How do I implement a constant explicitly defining multiple values in PHP?

define('VAR_1', 'Some info 01');
define('VAR_2', 'Some info 02');
define('VAR_3', 'Some info 03');
define('VAR_4', 'Some info 04');
define('VAR_5', 'Some info 05');
define('VAR_6', 'Some info 06');
define('VAR_7', 'Some info 07');
I usually namespace my constants, if I've got many of them, in a class like so:
class Foo {
const Bar = 1;
const Baz = 2;
public static $array = array(1,2,3);
}
echo Foo::Bar; # Accessing the constants
print_r(Foo:$array);
Putting an Array in a constant is not possible for class constants, and I don't think it is a good practice putting them in global constants either, if it is even possible (not sure). Maybe you should tell us what you are trying to accomplish, maybe there is a better way to do it.
Oh, and please don't do something like this:
for($x=0; x<10; $x++) {
define('VAR_' . $x, 'Information #' . $x);
}
Which has been suggested here, but IMHO this is absolutely not how constant are supposed to be used.
You can use an array and a loop to accomplish this.
Do you mean you want a single constant with multiple values stored internally?
You can set an array as a constant:
define('VAR', array('Some info 01','Some info 02',...));
In this way, VAR[0] == 'Some info 01', VAR[1] == 'Some info 02', etc.
Is this what you wanted?
You can't define constants with arrays. Thanks to #wiseguy for reminding me.
as already stated it is advised that you encapsulate your constants so that it does not overflow your root scope, try create a class and set your constants in that, such as:
final abstract class Constants
{
const FOO = 'a';
const BAR = 1;
const ZED = 'c';
}
And then simply use like use like so:
echo Constants::FOO;
You should not really be using constants for storing arrays, which is why it has not been allowed within the PHP core.
but im not here to question your motives so if you want to store arrays within a constants then you can do so by transforming into a string, such as
define('MY_ARRAY',serialize(array(1 => 'foo')));
and then run unserialize to get it back into an array

Can a PHP object instance know its name?

If I have code like this:
class Person {
$age;
$height;
$more_stuff_about_the_person;
function about() {
return /* Can I get the person's name? */;
}
}
$John = new Person();
$Peter = new Person();
print $John->about(); // Print "John".
print $Peter->about(); // Print "Peter".
Is it possible to print the person's name, stored as the variable name, from the method?
As it's not standard procedure, I'm guessing it's a bad idea.
I've looked it up and I can't find anything about it.
No. Objects can have multiple names, or no names. What would happen here:
$John = new Person();
$Richie = $John; // $John and $Richie now both refer to the same object.
print $Richie->about();
or here:
function f($person)
{
print $person->about();
}
f(new Person());
If the objects need to know their own names, then they need to explicitly store their names as member variables (like $age and $height).
Eje211, you're trying to use variables in very bizarre ways. Variables are simply data holders. Your application should never care about the name of the variables, but rather the values contained within them.
The standard way to accomplish this - as has been mentioned already, is to give the Person class a 'name' property.
Just to re-iterate, do not rely on variable names to determine the output/functionality of your application.
User defined variables names should be treated as totally transparent to the PHP compiler (or any compiler for that matter). The objects you create are just references to memory that point to the real object. Their name has no meaning. Name is a member of person.
You can, however, get the variables you want with get_defined_vars()
foreach (get_defined_vars() as $key => $val) {
if ($val instanceof Person) {
echo $key;
}
}
This should absolutely not be done, however, and the object would still need to know the order in which the variables were stored. No idea how you would calculate that.
This example might be helpful currently there is no method that tells you the object name you have to specify yourself like in the code below:
class Person {
public $age=0;
public $height=0;
public $objPerson='';
function about($objPerson,$age,$height) {
return
'Person Object Name: '.$objPerson.'<br>'.
'Age: '.$age.'<br>'.
'height: '.$height.'ft<br><hr>';
}
}
$John = new Person();
$Peter = new Person();
print $John->about('John',25,'5.5');
print $Peter->about('Peter',34,'6.0');

Categories