I have the following test code:
namespace Test {
const ONE = 50;
class A {
const TWO = 5;
public function pA($string) {
return $string;
}
}
$a = new A();
print $a->pA($a::TWO);
print "This is a string: {$a->pA($a::TWO)}";
print "This is a namespace constant: " . ONE;
print "This is a namespace constant: " . \Test\ONE;
}
All of these examples work, but it's not what I'm looking for.
Can I use string composition to represent the constant like in the first two examples? I've tried many combinations like "${\Test\B}" or "${B}" or "${\B}" but, so far, no luck.
Maybe it isn't possible and I'm overdoing it, but anyway... is there a way to do that?
This will not work. You can use $variables, functions or object method calls in double quoted string but not constants. Refer to the PHP string parsing documentation. You'll find many useful examples.
Related
I've recently worked on some code in which I had to dynamically call a method inside a class.
The solution I ended up using was 2 lines, because the "dynamic" part was only a small section of the actual method name that I needed to call.
This is the solution I ended up using:
$pull = "pull_{$type}_day";
$day = $download->$pull();
Originally, I tried to make this a single line, but it did not work. In a technical sense, why does the above code work but the below code does not?
$day = $download->"pull_{$type}_day"();
If you use a string or part of a string as a method (or property) you need to surround it in {} like this:
#property
echo $foo->{"bar"};
#method call
echo $foo->{"bar"}();
So if you need a variable in the string part, this follows the same rules as any normal string.
echo $foo->{"bar".$bar}();
echo $foo->{'bar'.$bar.'bar'}();
echo $foo->{"bar{$bar}bar"}();
And so on. Here is a full example
class foo{
function pull_1_day(){
echo "bar";
}
}
$a = 1;
(new foo)->{"pull_{$a}_day"}();
Outputs
bar
Sandbox
This follows in the same way PHP allows you to use a string as a variable such as this:
$foo = 'bar';
echo ${"foo"};
Outputs
bar
Sandbox
Same kind of syntax.
Why not use call_user_func()?
I find it easier to read and parse.
Assuming you have:
class pull {
public function pull_foo_day () {
echo "hello";
}
}
$pull = new pull();
$type = "foo";
You can simply do:
call_user_func([$pull, "pull_{$type}_day"]);
Outputs:
hello
See it working here.
I was reading source of OpenCart and I ran into such expression below. Could someone explain it to me:
$quote = $this->{'model_shipping_' . $result['code']}->getQuote($shipping_address);
In the statement, there is a weird code part that is
$this->{'model_shipping_' . $result['code']}
which has {} and I wonder what that is? It looks an object to me but I am not really sure.
Curly braces are used to denote string or variable interpolation in PHP. It allows you to create 'variable functions', which can allow you to call a function without explicitly knowing what it actually is.
Using this, you can create a property on an object almost like you would an array:
$property_name = 'foo';
$object->{$property_name} = 'bar';
// same as $object->foo = 'bar';
Or you can call one of a set of methods, if you have some sort of REST API class:
$allowed_methods = ('get', 'post', 'put', 'delete');
$method = strtolower($_SERVER['REQUEST_METHOD']); // eg, 'POST'
if (in_array($method, $allowed_methods)) {
return $this->{$method}();
// return $this->post();
}
It's also used in strings to more easily identify interpolation, if you want to:
$hello = 'Hello';
$result = "{$hello} world";
Of course these are simplifications. The purpose of your example code is to run one of a number of functions depending on the value of $result['code'].
The name of the property is computed during runtime from two strings
Say, $result['code'] is 'abc', the accessed property will be
$this->model_shipping_abc
This is also helpful, if you have weird characters in your property or method names.
Otherwise there would be no way to distinguish between the following:
class A {
public $f = 'f';
public $func = 'uiae';
}
$a = new A();
echo $a->f . 'unc'; // "func"
echo $a->{'f' . 'unc'}; // "uiae"
Curly braces are used to explicitly specify the end of a variable
name.
https://stackoverflow.com/a/1147942/680578
http://php.net/manual/en/language.types.string.php#language.types.string.parsing.complex
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
Everyone knows in PHP you can do this:
$m = "my string is {$string}";
But is taht possibile with function too? Like:
$m = "my string is {getStringValue()}";
The string expansion in {$..} goes a bit beyond just being able to execute functions. I for example used gettext with that. But you can also use tricks like that:
$html = "htmlentities"; // any callback function
// or just: $html = function($s){ return $s; }
print "even allows expressions {$html(2+3*5+rand(2,17))} here";
That's possible because PHP allows any variable expression there in order to support the simple object notation case:
print "this isn't just a {$obj->prop} string variable";
And for example I'm utilizing an object which implements ArrayAccess, where even this is a method invocation:
print "Makes some things {$_GET->ascii->html['input']} simpler";
We had a few such topics on SO, but for the life of me I can't find a good reference ...
This is not possible (and it wouldn't be very readable too, especially if the function had parameters).
You could use sprintf:
$m = sprintf("my string is %s", getStringValue());
Only variable names are expanded
http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double
With concatenation, If I understand well what you're trying to do:
$m = "my string is {".getStringValue()."}";
What is the meaning of { } (curly braces) in string literals in PHP?
This is the complex (curly) syntax for string interpolation. From the manual:
Complex (curly) syntax
This isn't called complex because the syntax is complex, but because
it allows for the use of complex expressions.
Any scalar variable, array element or object property with a string
representation can be included via this syntax. Simply write the
expression the same way as it would appear outside the string, and
then wrap it in { and }. Since { can not be escaped, this syntax
will only be recognised when the $ immediately follows the {. Use
{\$ to get a literal {$. Some examples to make it clear:
<?php
// Show all errors
error_reporting(E_ALL);
$great = 'fantastic';
// Won't work, outputs: This is { fantastic}
echo "This is { $great}";
// Works, outputs: This is fantastic
echo "This is {$great}";
echo "This is ${great}";
// Works
echo "This square is {$square->width}00 centimeters broad.";
// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";
// Works
echo "This works: {$arr[4][3]}";
// This is wrong for the same reason as $foo[bar] is wrong outside a string.
// In other words, it will still work, but only because PHP first looks for a
// constant named foo; an error of level E_NOTICE (undefined constant) will be
// thrown.
echo "This is wrong: {$arr[foo][3]}";
// Works. When using multi-dimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][3]}";
// Works.
echo "This works: " . $arr['foo'][3];
echo "This works too: {$obj->values[3]->name}";
echo "This is the value of the var named $name: {${$name}}";
echo "This is the value of the var named by the return value of getName(): {${getName()}}";
echo "This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}";
// Won't work, outputs: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}";
?>
Often, this syntax is unnecessary. For example, this:
$a = 'abcd';
$out = "$a $a"; // "abcd abcd";
behaves exactly the same as this:
$out = "{$a} {$a}"; // same
So the curly braces are unnecessary. But this:
$out = "$aefgh";
will, depending on your error level, either not work or produce an error because there's no variable named $aefgh, so you need to do:
$out = "${a}efgh"; // or
$out = "{$a}efgh";
As for me, curly braces serve as a substitution for concatenation, they are quicker to type and code looks cleaner. Remember to use double quotes (" ") as their content is parsed by PHP, because in single quotes (' ') you'll get the literal name of variable provided:
<?php
$a = '12345';
// This works:
echo "qwe{$a}rty"; // qwe12345rty, using braces
echo "qwe" . $a . "rty"; // qwe12345rty, concatenation used
// Does not work:
echo 'qwe{$a}rty'; // qwe{$a}rty, single quotes are not parsed
echo "qwe$arty"; // qwe, because $a became $arty, which is undefined
?>
Example:
$number = 4;
print "You have the {$number}th edition book";
//output: "You have the 4th edition book";
Without curly braces PHP would try to find a variable named $numberth, that doesn't exist!
I've also found it useful to access object attributes where the attribute names vary by some iterator. For example, I have used the pattern below for a set of time periods: hour, day, month.
$periods=array('hour', 'day', 'month');
foreach ($periods as $period)
{
$this->{'value_'.$period}=1;
}
This same pattern can also be used to access class methods. Just build up the method name in the same manner, using strings and string variables.
You could easily argue to just use an array for the value storage by period. If this application were PHP only, I would agree. I use this pattern when the class attributes map to fields in a database table. While it is possible to store arrays in a database using serialization, it is inefficient, and pointless if the individual fields must be indexed. I often add an array of the field names, keyed by the iterator, for the best of both worlds.
class timevalues
{
// Database table values:
public $value_hour; // maps to values.value_hour
public $value_day; // maps to values.value_day
public $value_month; // maps to values.value_month
public $values=array();
public function __construct()
{
$this->value_hour=0;
$this->value_day=0;
$this->value_month=0;
$this->values=array(
'hour'=>$this->value_hour,
'day'=>$this->value_day,
'month'=>$this->value_month,
);
}
}