How does string interpolation work in this scenario?
i'm not sure if i'm making a syntax error or not.
i'm trying to get the amount of items in this return
return "Your collection exists of {count($this->movies)} movies.";
when i try this it says:
"PHP Warning: Array to string conversion"
The string interpolation rules are described thoroughly in the PHP manual. Importantly, there are two main styles:
One with plain variables in the string, like "the $adjective apple", which also supports some expressions like $foo->bar in "the $foo->bar apple"
One with curly brackets, which supports more complex expressions, like {$foo->bar()}, but the expression must start with a $
When PHP sees your string:
it first sees {count(, but because the character after { isn't $, it doesn't mean anything special
it then sees the $this->movies, which is valid for the first syntax, so it tries to output $this->movies as a string
because $this->movies is an array, you get a Warning and the string "Array" is used
The result is that the string will always say "Your collection exists of {count(Array} movies.".
There is no interpolation syntax currently that supports function calls like count(), so you'll have to use concatenation or an intermediate variable:
return "Your collection exists of " . count($this->movies) . " movies.";
or
$movieCount = count($this->movies);
return "Your collection exists of {$movieCount} movies.";
or
$movieCount = count($this->movies);
return "Your collection exists of $movieCount movies.";
you can try following line
return "Your collection exists of {".count($this->movies)."} movies.";
You can call a PHP var inside a string which is wrapped by double quoutes. But it is not possible with a function. 2 possible ways to do it:
$this->movies = ['lethal weapon 1','lethal weapon 9'];
$count = count($this->movies);
return "Your collection exists of $count movies.";
or
$this->movies = ['austin powers 1','austin powers 2'];
return "Your collection exists of " . count($this->movies) . " movies.";
Related
I understand the usage of complex (curly) syntax within a string, but I don't understand it's purpose outside of a string.
I just found this code in CakePHP that I cannot understand:
// $class is a string containg a class name
${$class} =& new $class($settings);
If somebody could help me understand why is used here, and what is the difference between this and:
$class =& new $class($settings);
Thank you.
Easiest way to understand this is by example:
class FooBar { }
// This is an ordinary string.
$nameOfClass = "FooBar";
// Make a variable called (in this case) "FooBar", which is the
// value of the variable $nameOfClass.
${$nameOfClass} = new $nameOfClass();
if(isset($FooBar))
echo "A variable called FooBar exists and its class name is " . get_class($FooBar);
else
echo "No variable called FooBar exists.";
Using ${$something} or $$something. is referred to in PHP as a "variable variable".
So in this case, a new variable called $FooBar is created and the variable $nameOfClass is still just a string.
An example where the usage of the complex (curly) syntax outside of a string would be necessary is when forming a variable name out of an expression, consisting of more than just one variable. Consider the following code:
$first_name="John";
$last_name="Doe";
$array=['first','last'];
foreach ($array as $element) {
echo ${$element.'_name'}.' ';
}
In the code above the echo statement will output the value of the variable $first_name during the first loop, and the value of the variable $last_name during the second loop. If you were to remove the curly brackets the echo statement would try to output the value of the variable $first during the first loop and the value of the variable $last during the second loop. But since these variables were not defined the code would return an error.
The first example creates a dynamically named variable (name is the value of the class variable), the other overwrites the value of the class variable.
I can make out the difference between
echo "{$var1}someString" // here the variable is $var1
echo "$var1someString" // here the variable is $var1someString
The question is why to use {}? It works only with {}. It does not work with (). What is so special about { }?
The curly braces {} are used in that way to identify variables within strings:
echo "{$var1}someString"
If you look at:
echo "$var1someString"
PHP can't possibly determine that you wanted to echo $var1, it's going to take all of it as the variable name.
You could concatenate your variables instead:
echo $var1 . "someString"
It doesn't work for () simply because the PHP designers choose {}.
you expained it yourself. thats simply the syntax php uses for this - nothing more. to quote the documentation:
Complex (curly) 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 {$
According to the documentation of string, the curly part is called complex syntax. It basically allows you to use complex expressions inside string.
Example from the documentation:
<?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()}";
?>
Here {} define that variable within these are not a simple string so php pic up that variable value instead of assuming that as a simple string.
I am querying a psql database through PHP to get an array of boolean values where indexes are userids, e.g. userconfirm bool[]. When I do something like:
$query = "select userconfirm from calendar where id = '%s'";
$result = $this->db->query($query, 2);
var_dump($result['userconfirm']);
I get:
array(1) { [0]=> array(1) { ["userconfirm"]=> string(20) "[256:258]={t,NULL,t}" } }
Which is to say I get a string where the array should be. Ok, parsing this could probably be done, if I studied up on PHP, but this feels wrong. Surely there's a way to get the array directly?
Main question is: How do I get this array to PHP directly?
Secondary question: Is this a suitable format for keeping track of user attendance? Is there a better way?
(Re-posted from a comment by request)
Glancing at the documentation, it doesn't appear as though there's a way to directly interpolate a PostgreSQL array to an array in PHP. However, if the position of your vector represents a user id, you might be better off restructuring your data to columns with user_id and attended (the latter of which should be a boolean datatype).
PHP's native PostgreSQL driver does not support advanced data-types. In fact, it doesn't even properly support integers, booleans or anything else! (cite: As stated here under "Return Values", all values are returned as strings, NOT their correct data type: http://www.php.net/manual/en/function.pg-fetch-assoc.php)
To help battle this problem, you may want to check out PHPG, a PHP library designed to specifically transform all returned PostgreSQL values to native PHP data-types. Supports arrays for any data-type, Hstores, Geometric data-types, and more:
Numeric / Integers
If you're a numeric[] or integer[] data type which does NOT have the possibility of containing NULL values, then you can simply remove the leading and trailing curly brackets, and explode the string into an array using the comma delimiter: https://github.com/JDBurnZ/PHPG
<?php
$pg_intarr = '{1,2,3,4,5}';
$vals = substr($pg_intarr, 1, -1); // Remove curly brackets
$vals = explode(',',$vals); // Returns: array(1,2,3,4,5)
Strings
However, the problem becomes much more complex when dealing with string-based data types such as character[], character varying[] or text[] and here is why: If the value of an array contains a space or some other special character, then PostgreSQL returns that particular value encapsulated in double quotes. If the value is a single word with no special characters, then that value is returned with no quotes whatsoever.
Here is an example character varying[] value returned from PostgreSQL:
{val1,"val 2",val3,"val-4","val,4"}
The challenge here is:
Can't explicitly explode on "," because not all strings are double-quoted.
Can't explicitly explode on , because a value may contain a comma such as val,4
The only method I was able to derive after MONTHS of encountering this problem over and over again was to take the string provided by PostgreSQL, and perform a subsequent query to UNNEST the array into a result set, which is then read and transformed into a native PHP array:
$grab_vals = pg_query("SELECT UNNEST('" . pg_escape_string('{val1,"val 2",val3,"val-4","val,4"}') . "') AS value");
$grab_vals = pg_fetch_all($grab_vals);
$array_vals = array();
foreach($grab_vals as $val) {
$array_vals[] = $grab_vals['value'];
}
Booleans
In regards to boolean[] values, you could most likely take the same approach as suggested for integers. However because you also anticipate NULL values, we have the added task of mapping the string value NULL to PHP's native NULL data-type:
function pgBool2Php($string) {
if($string == 't') {
return True;
} else if($string == 'f') {
return False;
} else if($string == 'NULL') {
return Null;
} else {
raise new Exception('Mal-formed PostgreSQL Boolean encountered. Expecting value of "t", "f" or "NULL", encountered "' . $string . '"');
}
}
$pg_intarr = '{t,NULL,t,f}';
$vals = substr($pg_intarr, 1, -1); // Remove curly brackets
$vals = explode(',',$vals); // Returns: array('t','NULL','t','f')
$vals = array_map('pgBool2Php', $vals); // Returns: array(True, Null, True, False)
heres my pg_parse function on github
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,
);
}
}