Here is a minimal test case I've isolated:
<?php
class What {
public $foo = range(0,5);
}
?>
I have no idea why this produces an error:
PHP Parse error: syntax error, unexpected '(', expecting ',' or ';' in TestCase.php on line 4
Using array() works.
Using PHP 5.3.3 (bundled with OS X).
You can only assign constant values in that context. You'll have to initialize your $foo in a constructor if you want to use the return value of a function.
<?php
class What {
public $foo;
public function __construct() {
$this->foo = range(0,5);
}
}
?>
BTW: As others have pointed out, array() is not a function. It's a language construct.
Array isn't a function, it's a language construct. That's why it's allowed.
Class member variables are called "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.
http://www.php.net/manual/en/language.oop5.properties.php
Check this link as a similar problem was sent and had been solved :-
http://www.phpbuilder.com/board/showthread.php?t=10366062
Also you can see the examples of using range() function in PHP.Net Manual although I think the problem may be in the variable $foo and public keyword as you there may be a type mismatch or a conflict beteen the version of the PHP function and your running PHP version.
I hope this answer helps you..
Related
I know it is possible to declare the type of function parameters, function return, and class attributes. (as demonstrated below)
class HasString {
private string $value;
public function getValue() : string
{
return $value;
}
public function setAttribute(string $arg0)
{
$this->value = $arg0;
}
}
However, the following will not work.
// Tested in PHP 7.4.1
string $localVar = "value"; // Parse error: syntax error, unexpected '$localVar' (T_VARIABLE) in php shell code on line 1
Does php has a syntax that I can use to explicitly declare the type of a local variable?
This would be useful to catch bugs where a variable receives an unexpected value, and to help the IDE identify the variable type when dealing with mixed or unspecified function returns.
You can using typecasting to force a variable into a type like so:
$string = (string) 3;
You'll find $string is now the string: "3".
If you only want to allow one type (and not have any conversion/casting) the simple answer is: in PHP you cannot really do this as PHP is a weakly typed language. There are some workaround that you can read more about it in this question.
I think to just type cast your variable is a bit risky as unexpected behaviour might occur.
If you cast an int to a string that might work in a lot of cases but could also lead to not so obvious errors.
What you are looking for are PHPDoc Annotations as there is unfortunately no way to do what you do with the class properties on the local variables. You can learn more about these here https://www.phpdoc.org/ and here https://phpstan.org/writing-php-code/phpdocs-basics
But if you are using any framework it would already come with those.
Or your IDE also just supports them like for example Phpstorm or Eclipse.
Code example
public function foo(): void {
/* #var string */
$localVar;
// ... do other stuff
}
After swapping some of my non-static vars to static vars, I ended up with some expressions similar to the one here. This throws a syntax error, but I can't figure out why.
Class Bar {
public static $name = "bar";
}
Class Foo {
public function getParent(){
$this->parentClass = new Bar();
return $this;
}
}
$foo = (new Foo())->getParent();
echo ($foo->parentClass)::$name; //this line is throwing a syntax error
//output:
PHP Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
If I assign the object to a variable, then it doesn't throw the error:
$class = $foo->parentClass;
echo $class::$name;
//outputs "bar";
I could imagine possibly running into some unintended order of operations issues, but can't figure out why it's a syntax error, and I'm wondering if there is a way to do this in a single one line expression. (Since this issue was caused by a mass find/replace, it would be nice to keep it in one line)
It's kinda ugly, but if you really need a one-liner:
echo get_class_vars(get_class($foo->parentClass))["name"];
Inspired by this answer
DEMO
In fact this is only possible as of PHP 7.0. The changed behaviour is not well documentated. I think it's more of a bugfix than a new feature.
However the closest solution to a "one-liner" (working in 5.6) seems to be this one:
$bar = (new Foo())->getParent()->parentClass;
echo $bar::$name;
Maybe that is not what you tried to achieve.
The important thing is that the static class is only accessable by putting it into a single variable first.
I recommend a migration to PHP7 urgently.
When using something like
class MyClass
{
public static function myFunction()
{
static::myOtherFunction();
}
private static function myOtherFunction()
{
…
}
}
the PHP parser will complain
Parse error: syntax error, unexpected T_STATIC in ….php on line …
in older PHP versions. I couldn't find a reference though, what the minimum PHP version would be to use the static keyword like that.
It's because you are using a version of PHP that is older than PHP 5.3, which means you can't use late static bindings as it doesn't recognize static::myOtherFunction().
It's 5.3.0
As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value cannot be a keyword (e.g. self, parent and static).
via http://php.net/manual/en/language.oop5.static.php
Can some one explain why this doesn't work:
private static $bundles = array(
'page-builder' => array(
'Freya\\Bundle\\PageBuilder' => self::$baseDir . '/freya-bundle-pagebuilder/Freya/Bundle/PageBuilder'
);
);
self::$baseDir is __DIR__. I thought at run time PHP would evaluate this and save it out as path/to/some/dir/freya- ....
The exact error is:
Parse error: syntax error, unexpected '$baseDir' (T_VARIABLE), expecting identifier (T_STRING) or class (T_CLASS) in /vagrant/local-dev/content/mu-plugins/Freya-MU/bundles/BundleLoader.php on line 51
Line 51, is: 'Freya\\Bundle\\PageBuilder' => self::$baseDir . '/freya-bundle-pagebuilder/Freya/Bundle/PageBuilder'
So ... What am I missing and whats the proper way to do this?
PHP Version: 5.5
PHP does not allow this. PHP properties may be initialized to constant values, but only with constant values that are available at compile time. From the manual:
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.
Whatever value your static property $baseDir holds is simply not available until the class definition is actually executed (i.e. runtime).
You can get around this to a degree by using a class constant:
class AClass {
const MY_CONSTANT = 42;
protected $property = self::MY_CONSTANT;
}
Class constants are evaluated at compile time, which is what you need to do. Note however that you cannot do any other manipulations (e.g. initialize $property to be self::MY_CONSTANT * 3)
I would suggest leaving self::$baseDir completely out of your property, and either inject it in during construction or whenever your property is actually being used.
You can't use a variable when declaring a property in a class. Check out the invalid property declarations in the PHP manual.
<?php
class SimpleClass
{
// invalid property declarations:
public $var1 = 'hello ' . 'world';
public $var2 = <<<EOD
hello world
EOD;
public $var3 = 1+2;
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
This is because PHP doesn't execute any code when parsing/compiling your class.
Just in addition to the other answers really: PHP 5.5 doesn't allow expressions, including concatenation, in default value definitions, but 5.6 does. (http://php.net/manual/en/migration56.new-features.php)
So, basically, either upgrade your PHP version or set the value of $bundles from a method. There is no problem with your array otherwise.
While working with Laravel framework, more specific - Form macros, I stumbled upon a weird error.
At first, I thought it's something wrong with Laravel, but then I took everything out of context:
<?php
// placeholder function that takes variable as reference
$function = function(&$reference)
{
// append to variable
$reference = $reference . ':' . __METHOD__;
};
// test with straight call
$variable = 'something';
$function($variable);
echo $variable;
// test with call_user_func(), that gets called in Laravels case
$variable = 'something'; // reset
call_user_func($function, $variable);
echo $variable;
While the first call to $function executes properly, the second try with call_user_func(), produces (excerpt from Codepad):
Warning: Parameter 1 to {closure}() expected to be a reference, value given
PHP Warning: Parameter 1 to {closure}() expected to be a reference, value given
Fiddle: Codepad # Viper-7
While writing this, I thought about call_user_func_array(): fiddle here, but the same error is produced.
Have I got something wrong about references or is this a bug with PHP?
I would call this a bug with PHP, although it's technically a bug with call_user_func. The documentation does mention this, but perhaps not in a very enlightening way:
Note that the parameters for call_user_func() are not passed by
reference.
It would be perhaps clearer to say that the arguments to call_user_func() are not passed by reference (but note that technically it's not necessary to say anything at all; this information is also embedded in the function signature).
In any case, this means is that when call_user_func finally gets to invoking its target callable, the ZVAL (PHP engine internal data structure for all types of values) for the argument being passed is not marked as "being-a-reference"; the closure checks this at runtime and complains because its signature says that the argument must be a reference.
In PHP < 5.4.0 it is possible to work around this by using call-time pass by reference:
call_user_func($function, &$variable);
but this produces an E_DEPRECATED warning because call-time pass by reference is a deprecated feature, and will flat out cause a fatal error in PHP 5.4 because the feature has been removed completely.
Conclusion: there is no good way to use call_user_func in this manner.
This works:
call_user_func_array($function, array(&$variable));
I used this code
<?php
$myfunction = function &($arg=3)
{
$arg = $arg * 2;
return $arg;
};
echo $myfunction();
?>
Worked like a charm. :)
What happens if you do this?
call_user_func($function, &$variable);