How to access constants none static way - php

if a constant is defined in class like this:
class Example
{
const MIN_VALUE = 0.0; // RIGHT - Works INSIDE of a class definition.
}
it is possible to access the constant like this:
Example::MIN_VALUE
but if you do this:
class Sample {
protected $example;
public function __construct(Example $example){
$this->example = $example;
}
public function dummyAccessToExampleConstant(){
//doesn't work -> syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
if($this->example::MIN_VALUE === 0.0){
}
//this works
$tmpExample = $this->example;
if($tmpExample::MIN_VALUE === 1){
}
}
}
Can somebody explain me the reason of this behaviour ?
Is there a good reason or is it just a language construct that prevents the access with "::"
Is there a way how to access a constant with "$this"

This is one of those unfortunate shortcomings of PHP's parser. This will work:
$example = $this->example;
$min = $example::MIN_VALUE;
This won't:
$min = $this->example::MIN_VALUE;
Edit:
This issue is documented in PHP bug #63789: https://bugs.php.net/bug.php?id=63789
It has been fixed, but you will have to wait until PHP's next major release (7).

It is a class constant. There is no need (and indeed no means) whatsoever to access it in an instance-based way.
You should just access it as Example::MIN_VALUE to eliminate any confusion.
PHP > 5.3 allows access via an instance as you have shown (i.e. $class_instance::CLASS_CONSTANT) but this is still not to be confused with a property of that instance which can be accessed via -> (if public of course).

Is there a way how to access a constant with "$this"
You don't need to access a constant with $this, because $this refers to the current instanciated object of a class. constants can be accessed without instantiating an object.
Is there a good reason or is it just a language construct ...
A constant, as it's name implies, it's a constant value, meaning the value of that variable won't change during execution, that's why you don't need to instantiate an object to access its value.
Hope it's clear !

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?

PHP: Access static function / method with object property

While I understand that static methods can be invoked through a variety of approaches, such as:
A::staticFunction();
OR
$class = 'A';
$class::staticFunction();
OR
$a = new A(); // Assume class has been defined elsewhere
$a->staticFunction();
However, could someone please explain why the following won't work, and if possible, how to make this work (without resorting to the solution provided):
// Assume object $b has been defined & instantiated elsewhere
$b->funcName::staticFunction(); // Where funcName contains the string 'A'
This produces the following PHP parse error:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
Typical working solution (follows second approach) (preferably avoid if possible):
// Assume object $b has been defined & instantiated elsewhere
$funcName = $b->funcName; // Where funcName contains the string 'A'
$funcName::staticFunction();
The :: operator is used to refer to a non-instanced class. That means you're referencing either static methods or variables, or const. The hallmark of static methods is that they cannot work with your instance. They are, essentially, stand-alone functions and cannot use $this to refer back to the instance of your class.
As such, you cannot refer to a static method by referencing the instance. You need to use
self::function();
or
$this->function();
While the latter makes it look like it might be part of the instance, it's included for completeness only.

php array in class

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.

PHP5 Class scope quirks

Hey php gurus. I'm running into some bizarre class scope problems that clearly have to do with some quirk in php. Can anyone tell me what out-of-the-ordinary situations might give the following error...
Fatal error: Cannot access self:: when no class scope is active in MyClass.php on line 5
Now, obviously if I were to use self:: outside of the class, I'd get errors... but I'm not. Here is a simplified version of the situation...
//file1
class MyClass{
public static function search($args=array()){
$results = MyDbObject::getQueryResults("some query");
$ordered_results = self::stack($results); //Error occurs here
return $ordered_results;
}
public static function stack($args){
//Sort the results
return $ordered_results;
}
}
//file 2
include_once("MyClass.php");
$args = array('search_term'=>"Jimmy Hoffa");
$results = MyClass::search($args);
given this setup how can I get the error above? Here is what I've found so far...
MyClass::search($args) //does not give the error (usually)
call_user_func("MyClass::search"); // this gives the error!
Any other situations?
If I understand correctly, you are looking for Late Static Binding. This feature requires PHP version 5.3 at least.
You're not passing any parameters, but your method is looking for them. Try
call_user_func("MyClass::search", $args);
This works in php 5.3.1, but call_user_func("MyClass::search"); doesn't
Try this:
call_user_func(array('MyClass', 'search'));
See also example #4 on http://php.net/call_user_func
Your code seems fine. If there's something wrong with it, I must be missing the problem. It appears that your call to self:: is totally within the scope of a class! And a static scope, specifically, which is what self:: is for.
From the 3rd Edition of PHP Objects Patterns and Practice (an awesome book):
To access a static method or property from within the same class
(rather than from a child), I would use the self keyword. self is to
classes what the $this pseudo-variable is to objects. So from outside
the StaticExample class, I access the $aNum property using its class
name:
StaticExample::$aNum;
From within the StaticExample class I can use the self keyword:
class StaticExample {`
static public $aNum = 0;
static public function sayHello() {
self::$aNum++;
print "hello (".self::$aNum.")\n";
}
}
So, I am not sure why this code was failing. Perhaps a PHP bug? I came upon this error when actually trying to use self:: outside of the scope of a class-- my error looked like this:
public static function get_names() {
$machine_names = self::get_machine_names();
return array_map(function ($machine_name) {
$service_settings = self::get_settings_by_machine_name($machine_name);
return $service_settings . $machine_name;
},
$machine_names
);
}
So, I get the error because I use self:: within the scope of the closure. To fix the error, I could make that call to self::get_settings_by_machine_name() before the closure, and pass the results to the closure's scope with use.
Not sure what was happening in your code.

PHP passing a class name becomes a string when passed to a function

Here's what I want to do:
public function all($model) {
$query = 'SELECT ' . implode(', ', $model::$fields) ....;
}
Called like this:
$thing->all(Account);
I get this error:
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /home/mark/public_html/*/account.php on line 15
When inspecting $model with var_dump it turns out its a string. In the the first example if I change $model to Account on the $query line it works fine.
How can a take a string and turn it back into a class?
Edit: Updated example and title to reflect the problem isn't with self.
Solution: Since I'm not using PHP5.3, I had to resort to using eval() to get what I wanted. Thanks everybody!
Classes are not first-class citizens in PHP, as such they may not be stored in variables, passed as function arguments, or returned from functions.
However, PHP will let you simulate a first-class citizen by using a string containing the name of the class, in certain situations:
$class = "Account";
$instance = new $class(); // You can create instances
call_user_func(array($class, 'frobnicate')); // You can call static functions
That's about all in PHP < 5.3. However, with PHP 5.3, you can also:
$class::frobnicate(); // cleanly call static functions
$fields = $class::$fields; // access static variables
I have also experienced receiving such Fatal Error: Class 'MyClass' not found when you're class has a specific namespace, then it's probably the namespacing. You need to also mention the namespace in your String variable.
$class = "App\MyClass"; // mention the namespace too
$instance = new $class();
See Wikipedia on the scope resolution operator. Especially see the section on PHP and Hebrew.
You cannot use self this way : it can only be used in a static context (i.e. inside a static method) to point to the class -- and not its name.
If you are working with non-static methods (seems you are), you should use $this, instead of self.
Actually, before PHP 5.3, you cannot use a static method/data with a "dynamic" (i.e contained in a variable) class name -- see the examples on the page Static Keyword : they only work with PHP 5.3, for that kind of manipulation.
Which means a portion of code like this one :
class ClassA {
public static $data = 'glop';
}
$className = 'ClassA';
var_dump($className::$data);
Will not work with PHP < 5.3
I find this similar line works in my Laravel app:
$thing->all(new Account);
Try '$this' instead of self.
Self does work this way in PHP. PHP thinks it encounters an unknown constant, which it can't find, and then it assumes it's a string containing 'self'.
Edit: Can you post the class and the code where you instantiate the object?

Categories