I am trying to store some validation functions inside a static configuration array. Storing functions in array seems to work, however, when I put the same code inside a class, it fails. Anyone know what's going on?
$functions = array(
'function1' => function($echo) {
echo $echo;
}
);
$functions['function1']("hello world");
// Works
//----------
class A {
public static $functions = array(
'function1' => function($echo) {
echo $echo;
}
);
}
A::$functions['function1']("hello world");
//Parse error: syntax error, unexpected 'function' (T_FUNCTION)
When I run this using PHP 7 (PHP 5 will also error out), I am getting an error that basically says expressions when instantiating class variables is not allowed. This is how this will work instead:
$functions = array(
'function1' => function($echo) {
echo $echo;
}
);
$functions['function1']("hello world");
// Works
//----------
class A {
public static $functions = [];
}
A::$functions['function1'] = function($echo) {
echo $echo;
};
A::$functions['function1']("hello world");
http://php.net/manual/en/language.oop5.properties.php
Class member variables are called "properties". You may also see them
referred to using other terms such as "attributes" or "fields", but
for the purposes of this reference we will use "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.
Related
I want to pass informations to a template:
public function do(array $p)
{
extract($p);
unset($p);
ob_start();
require('view.php');
return ob_get_clean();
}
$object->do([
'a' => 1
]);
view.php
<?php
var_dump(get_declared_vars());
this way the dump will output a => 1 and the $this object, but I dont want to see $this. How to nullify it?
I tried this...
<?php
class forJohn {
public function test (array $p) {
extract($p);
unset( $p );
ob_start();
require( 'view.php' );
return ob_get_clean();
}
}
$object = new forJohn;
echo $object->test( ['a' => 1] );
View.php
<?php
var_dump(get_defined_vars());
Interestingly, this results in
array (size=1)
'a' => int 1
Now I have had to use get_defined_vars() as I don't have access to your get_declared_vars(). Might be that is the answer!
From the manual
The pseudo-variable $this is available when a 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 variable is added automatically and it's very useful when trying to access the classes variables from it's method.
<?php
class SimpleClass
{
// property declaration
public $var = 'a default value';
// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
Why this is bothering you, I don't know, but you can remove this by using:
$declared_vars = get_declared_vars();
unset($declared_vars["this"]);
var_dump($declared_vars);
(This is not tested because my php version doesn't have the get_declared_vars() function, but if it returns an array, this is the path and may need only a few changes.
I am trying to access a static class member variable in an array.
My Code (index.php):
<?php
class Foo
{
public static $staticVar = 'test';
}
class Bar
{
public $someArray = array(
Foo::$staticVar
);
}
$cls = new Bar();
var_dump($cls->someArray);
?>
On PHP-7.0 I get this error:
PHP Fatal error: Constant expression contains invalid operations in
/var/www/html/index.php on line 12
On PHP-5.6 I get this error:
PHP Parse error: syntax error, unexpected '$staticVar' (T_VARIABLE),
expecting identifier (T_STRING) or class (T_CLASS) in
/var/www/html/index.php on line 11
I just want to have the string "test" in my array.
It´s strange that when I 'echo' out the variable it works as expected:
echo Foo::$staticVar // prints 'test'
I´m new to PHP and I can´t figure out what I´m doing wrong.
Unfortunately, you can't refer to another variable or class in the initial declaration of a class property. It's just a limitation of the language as it stands. The general workaround is to initialise the property in the constructor, e.g.
class Bar
{
public $someArray = array();
public function __construct()
{
$this->someArray = array(
Foo::$staticVar
);
}
}
On a vaguely related note, PHP 5.6 did at least make some vague headway in allowing you to define constants as basic expressions, see https://3v4l.org/6TDZV
The following PHP code results in an error: unexpected T_FUNCTION on the line starting with "say". I'm using PHP version 5.3.6 so lambdas should be supported, but it's not working. I don't know if the "use" clause is valid in this context either, but removing it does not resolve the problem. Is something wrong with my syntax? Note: $this->backend is defined in the constructor as $this->backend = fopen("bar.txt","w+");
class Foo
{
private $backend;
private $commands = array(
0 => array(
"say" => function($msg) use($this->backend) { fwrite($this->backend,$msg); }
)
);
}
Specific to PHP 5.3.x
First off, it's not possible to assign lambdas as default property values (lambdas are not considered a constant expression). So it is not possible to make that assignment directly; you would need to do it inside the constructor.
Secondly, in PHP 5.3.x you cannot use $this inside a lambda. The typical workaround is to make a copy of $this and capture that, as in:
$that = $this;
$func = function() use($that) { ... };
However this way it's not possible to access non-public members of $that from inside the lambda at all, so the technique cannot be used directly in your case.
What you should probably do is store $this->backend in a local variable inside the constructor and use that variable inside the lambda. Both the store and the capture can be done by value or by reference, depending on if you want any modifications to propagate outside the lambda and the possibility that the value of $this->backend may change before the lambda is invoked:
public function __construct() {
$backend = $this->backend;
$this->commands = array(
'say' => function($msg) use($backend) { fwrite($backend, $msg); }
);
}
Later PHP versions
Starting from PHP 5.4.0 you can implicitly use $this inside a lambda defined within a class method:
public function __construct() {
$this->commands = array(
'say' => function($msg) { fwrite($this->backend, $msg); }
);
}
The restriction that lambdas cannot be assigned as default property values still stands.
The problem is
use($this->backend)
$this doesn't exist yet in your class blueprint, so you absolutely can't specify it as this point.
What you're trying to do may be impossible to do inside an anonymous function, as it's not a member of the class as such, and hence doesn't get the $this variable.
You may have to do this in a proper member function of Foo, or pass $this as a parameter.
You cannot define properties in classes directly from variables or as lambda;
// these are incorrect
private $foo = $bar
private $callback = function() ...
// correct
define("BAR", "The bar!");
class A {
private $foo = BAR;
private $commands = array();
...
public function __construct() {
$this->commands[0] = function() ...
I'm using constants for my error messages inside the Views, and I want to be able to use variables inside them for easier management.
Most of my constants looks like this:
const SUCCESSFULLY_REGISTERED = "<p class='success'>Registration successful!.</p>";
What I want to do is to use a variable for the css class, so that it's easier to change them all in one place. This is what I've tried:
const SUCCESSFULLY_REGISTERED = "<p class='$this->cssClassSuccess'>Registration successful!.</p><p>Log in with the username and password you registered with.</p>";
By some reason that doesn't work and raises the error message below. Why is that and how can this be done in a way that works?
Parse error: syntax error, unexpected '"' in .../View/RegisterView.php on line 15
This is not possible if you define a constant.
Manual: "The value must be a constant expression, not (for example) a variable, a property, a result of a mathematical operation,
or a function call."
Constant Manual php.net
Constant Expression
This won't work because constants (as the name implies) need to be constant, but you can work around it with printf().
Example:
const SUCCESSFULLY_REGISTERED = '<p class="%s">Registration successful blah blah blah!</p>'
And then in your view script:
printf(SUCCESSFULLY_REGISTERED, $this->cssClassSuccess);
The %s in the constant will be replaced with the value of $this->cssClassSuccess
Manual: As of PHP 5.3.0, it's possible to reference the class using a variable.
Check the following class below:
<?php
class A{
function __construct($v)
{
define("MyConstant",$v);
echo "MyConstant is ". MyConstant;
}
}
$a = new A("hello"); //will print MyConstant is hello
?>
In the code above we are assigning the value of a variable ($v) to constant MyConstant. It will not give an error and the result of running this function will be MyConstant is hello
However, suppose you added a new line like so:
$a = new A("hello"); //will print MyConstant is hello
$b = new A("New Value"); //will generate Constant MyConstant already defined notice..
Here the line $b = new A("New Value"); will throw a notice stating: Notice: Constant MyConstant already defined. This is because constants defined within a class are pseudo-class-constants, similar to being static variables in terms of the context to which the scope is bound. And since constants cannot be changed, and their scope is bound to the class, calling the error line above is essentially trying to "redefine" the constant, which as you know will result in the aforementioned error.
Having said that remember that if you use define to create a constant inside a class it is not a pure class constant - you cannot call it as A::MyConstant. At the same time if you had done const AnotherConstant = "Hey"; in Class A you can call it as A::AnotherConstant. However when using const to create a constant you cannot set its value to a variable.
I hope this gives a better clarity on how dynamic variables can and cannot be assigned to a constant.
The only way that you can dynamically generate a constant is using the define function like below. But as another answer pointed out, this won't be a class level constant.
define('SUCCESSFULLY_REGISTERED', "<p class='$this->cssClassSuccess'>Registration successful!.</p><p>Log in with the username and password you registered with.</p>");
The constant from that point forward can be referred to with SUCCESSFULL_REGISTERED and will be immutable.
Problem: Cast custom messages and pass variables for easier management
Solution: use a Decorator pattern
interface HtmlElementInterface {
public function getText();
public function render();
}
class DivDecorator implements HtmlElementInterface {
protected $innerHtml;
protected $class;
public function __construct($class = null, $innerHtml = null) {
$this->innerHtml = $innerHtml;
$this->class = $class;
}
public function getText() {
return $this->text;
}
public function render() {
return "<div class='{$this->class}'>" . $this->innerHtml . "</div>";
}
}
$message = "Error in the app";
$div = new DivDecorator("myclass", $message);
echo $div->render();
I have a class look like below:
<?php
class theGodFather {
public function do() {
echo "the movie is nice";
}
}
$obj = new theGodFather;
echo $theGodFather->do;
When run I got the error: syntax error, unexpected T_DO, expecting T_STRING in /Applications/XAMPP/xamppfiles/htdocs/test/classes.php on line 3
what could I possibly did wrong?
You cannot use keywords as names for functions/classes/methods and constants, do is one. You can use them as variable names, however.
"do" is a keyword (can be used in a do while loop). Also you're echoing a function that returns nothing, but echoes something in it.
Rename the "do" function to "echoFunction" or whatever name you choose and then
change this:
$obj = new theGodFather;
echo $theGodFather->do;
to:
$obj = new theGodFather;
$obj->echoFunction();
The reason you wouldn't call $theGodFather->echoFunction because theGodFather is a class definition, while $obj is an actual instance of the class. You can have static methods in PHP that you can call without creating a new instance.
you have use do function in class "do" is a keyword of php and you cannot use keyword in function or class
try this
class theGodFather
{
// property declaration
public $var = 'a default value';
// method declaration
public function displayVar() {
echo 'a default value';
}
}
$obj = new theGodFather();
//print_r($obj);
echo $obj->displayVar();
do is a keyword, therefore the interpreter gets very very confused. :(
Choose a different function name and it works!