Confused by result of printing associative array with PHP - php

I'm trying to use foreach to print the results of a SQL query from an associative array. I'm trying different things and one works while the other gives an error.
I'm specifically asking about why this portion $row[first_name] gives different results.
This code works:
<?php
include 'connect_db.php';
$stmt = $conn->query("SELECT people.first_name, people.last_name FROM people");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
echo "<form action='/test.php' method='post'>
<input type='text' name='first_name' value=$row[first_name]>
<input type='submit' value='Click'> <br>
</form>";
}
?>
But the following code gives an error saying: Notice: Use of undefined constant first_name - assumed 'first_name'
<?php
include 'connect_db.php';
$stmt = $conn->query("SELECT people.first_name, people.last_name FROM people");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
echo $row[first_name];
}
?>
I'm obviously using $row[first_name] incorrectly in the 2nd example but I can't figure out how.

When using an undefined constant, PHP will automatically assume a string was intended. [sic]
PHP assumes that you mean the name of the constant itself, just as if
you called it as a string
Example: https://3v4l.org/C7PgT
As noted in the PHP 7.x, it will result in an ERROR as opposed to a warning in future versions, so its use should be avoided in favor of using quoted strings
Why $foo[bar] is wrong: [sic]
Always use quotes around a string literal array index. For example,
$foo['bar'] is correct, while $foo[bar] is not.
The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes).
if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.
This does not mean to always quote the key. Do not quote keys which are constants or variables, as this will prevent PHP from interpreting them.
When you used it within a double-quoted context ("$var"), PHP's lexer automatically used the text within the brackets ($var[text]) as a string.
Also PHP's lexer has issues when using array or objects within double quotes.
echo "value=$row['first_name']"; //results in a syntax error
Example: https://3v4l.org/K6fUd
To resolve this issue you would need to wrap your array with curly-brackets
echo "value={$row['first_name']}";
Excample: https://3v4l.org/aQ1sJ
Instead I highly suggest conforming to single quotes for all PHP output to save you from having to read between different syntax and HTML syntax uniformity.
foreach ($results as $row) {
echo '<form action="/test.php" method="post">
<input type="text" name="first_name" value="' . $row['first_name'] . '">
<input type="submit" value="Click"><br>
</form>';
}
Alternatively using HEREDOC or NOWDOC depending on desired output.
foreach ($rows as $row) {
echo <<<EOT
value="{$row['first_name']}"
EOT;
}
Example (including HEREDOC): https://3v4l.org/7K5ap
My preferred method is to ensure all HTML syntax is output directly or to the output buffer. As it allows for most IDE's, such as PHPStorm, to automatically distinguish it as HTML and not PHP code, to ensure HTML syntax is valid and matches with other tags.
<?php foreach ($results as $row) { ?>
<form action="/test.php" method="post">
<input type="text" name="first_name" value="<?php echo $row['first_name']; ?>">
<input type="submit" value="Click"><br>
</form>
<?php } ?>

The keys in an associative array returned from MySQL are strings - you need to quote them:
echo $row['first_name'];
# Here ---^----------^

Related

PHP object class not getting the submit field value

When I print the $letter variable, I am not getting the correct value. It always coming 0.
index.php
<form method="get" class="txtweb-form" action="index.php">
Guess a letter: <input type="text" name="txtweb-message" />
<input type="submit" value="submit" name="guess" />
</form>
<?php
$params = (object) $_REQUEST;
//print_r($params);
if (isset($params->guess)) {
$letter = $params->txtweb-message;
echo $letter;exit;
}
?>
You need to probably use _ instead of - in input name. - is not a valid character in PHP variable of property names.
What is actually happening is this:
$letter = $params->txtweb - message; // a subtraction operation
You end up subtracting an unset constant message from an unset object property $params->txtweb. Thus you get 0.
You can keep - in input name but you should use $_REQUEST['txtweb-message'] or $_GET['txtweb-message'] (without casting to object) to retrieve the value.
There really is no reason whatsoever to cast the superglobal array to an object, and this is what introduced your issue.
An additional note here. You really should be developing with error reporting turned on. That operation shown above would have resulted in two warnings showing up, which could have helped you understand what is happening.
why are you casting into an object?
wouldn't treating it as an array be easier like
<?php
$params = $_REQUEST;
if (isset($params["guess"])) {
$letter = $params["txtweb-message"];
echo $letter;exit;
}
?>

Values from private fields isn't displayed

I'm using private fields for the name attributes in forms instead of hard coding the values. However, by some reason the values isn't fetched from the private fields and put into the name attributes, and I just can't figure out why.
<?php
namespace View;
class UserView {
private $checkBox = "check[]";
private $submitRemove = "submitRemove";
public function ShowUsers() {
$userNameArray = array("foo", "bar", "hallo", "world");
$userIdArray = array(1, 2, 3);
$users = "";
$nrOfUsers = count($userNameArray);
// Name attribute of input fields created is left blank
for ($i = 0; $i < $nrOfUsers; $i++) {
$users .= "<label for='$userIdArray[$i]'>
$userNameArray[$i]
<input type='checkbox' name='$this->checkBox' value='$userIdArray[$i]' /><br/>
</label>";
}
$userList = "<div class='userList'>
<form id='form3' method='post' action=''>
<fieldset>
<p>Existing users</p>
$users
<input type='submit' id='$this->submitRemove' name='$this->submitRemove' Value='Ta bort' /> // name attribute is left blank
</fieldset>
</form>
</div>";
return $userList;
}
For "complex elements", such as arrays or attributes of an object, you can't call them just like a variable in a double-quoted string.
You have to escape them with braces:
<?php echo "This is a complex attribute: {$this->checkBox}"; ?>
or you can remove them from the quoted string:
<?php echo "This is a complex attribute: " . $this->checkBox; ?>
BTW, double quoted strings aren't recommended due to performance issues. Using simple quoted strings is better, it avoid to PHP to "read" the string to verify if there's a variable to display.
BTW2, to make your code more readable, a convention in PHP says that private attributes have to start by an underscore. You should rename $checkBox and $submitRemove to $_checkBox and $_submitrRemove.
BTW3, if those 2 variables aren't intented to change, you should consider to declare them as static variables. It'll prevent to have multiple copies of those variables inside each of instatiated objects.
There is nothing wrong with the posted code. I think you are overwriting $submitRemove somewhere in another method.

heredoc format and its implementation

i wrote the following code...
<?php
$conn=mysql_connect("localhost","","");
if($conn)
echo "connection established";
mysql_select_db("moviesite");
$que="select * from movie";
$result=mysql_query($que,$conn);
?>
<html>
<title>movie database</title>
<body>
<table border=1 align=center>
<th colspan=2>
PEOPLE<a href='movie.php?action=add & id='>[ADD]</a>
</th>
<?php
$ta_row=<<<eod
<tr>
<td>
$mov_name
</td>
<td>
<a href='movie.php?action=edit & id=$mov_id'>[EDIT]</a>
<a href='movie.php?action=delete & id=$mov_id'>[DELETE]</a>
<td>
</tr>
eod;
while($row=mysql_fetch_array($result))
{
$mov_id=$row["id"];
$mov_name=$row["name"];
echo $ta_row;
}
?>
now the above code didnt print the name or the id of the movie(the fields were blank)...so i cut and paste $ta_row inside the while loop after the definition of $mov_id and $mov_name...this sorted out all problems...but my question is why did the code fail earlier...as it is i was outputting ta_row after defining $mov_id and $mov_name so if $ta_row is just a string its content variables should have got changed...why didnt they change?
Because a heredoc is just like any other string - it's value is fixed when you declare it. If the variables $mov_id and $mov_name weren't set when you declared $ta_row, you can't use them in $ta_row.
If you want to do something like you tried to do in the first place, you would have to use something like str_replace() or sprintf() - replace place-holders in the original string with the actual values you want to display.
Consider this:
$myVar = "Some string containing a $var";
$var = 'Variable';
echo $myVar;
// Outputs: Some string containing a
Now this:
$var = 'Variable';
$myVar = "Some string containing a $var";
echo $myVar;
// Outputs: Some string containing a Variable
...Heredocs behave exactly like a double-quoted string (from this point of view, at least).
Alternatively you could do this:
$myVar = 'Some string containing a $var';
$var = 'Variable';
echo $myVar;
// Outputs: Some string containing a $var
echo str_replace('$var',$var,$myVar);
// Outputs: Some string containing a Variable
...because $myVar is now single-quoted, $var appears in it literally. Then when you run str_replace(), it is replaced with the value of $var, instead of the literal string.
It's probably worth you re-reading this.
It didn't work when you had it before the loop because it was trying to use the value of the variables $mov_id and $mov_name as they existed right then. Since they weren't defined at that point in the code, there was nothing to add in there. After that, $ta_row was simply a variable that contained a string, and only a string -- no variables, of the HTML.
If you'd like to move it out of the loop, use some placeholders like ##MOV_ID## and ##MOV_NAME## then you can just
echo str_replace(array('##MOV_ID##', '##MOV_NAME##', array($mov_id, $mov_name), $ta_row);
to get the desired result

Access object attribute with variable?

Not sure if the title is exactly what i want to do. Below is my working code.
mysql_select_db($_POST[database]);
$table_list = mysql_query('SHOW TABLES');
$tables_in_db = "Tables_in_" . $_POST[database];
while ($row = mysql_fetch_object($table_list)) {
echo "<tr>
<td class='pageBody'>" . $row->$tables_in_db . "</td>
</tr>";
}
Is it possible to remove line 4 and access the object attribute with $row->Tables_in_{$_POST[database]} in some manner? I've tried a couple different ways including various placing of quotes and curly braces, i had to resort to assigning the whole attribute to the variable $tables_in_db and then use that variable to access the attribute.
You have the right idea, just not the proper syntax. Variable properties can either take the form of a single variable ($a->$b) or some other expression that returns a string containing the name of the property ($a->{'b'}).
$row->{'Tables_in_' . $_POST['database']}
Aside: using one of the other mysql_fetch_* functions, knowing the column name would become irrelevant. For example, mysql_fetch_array() or mysql_fetch_row() and accessing the $row[0] item.

Curly braces in string in PHP

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,
);
}
}

Categories