NogDog
Sorry for disturb you. I have a problem when insert pagination. below the error
Fatal error: Uncaught Error: Call to undefined function safe_value() in
NogDog
Sorry for disturb you. I have a problem when insert pagination. below the error
Fatal error: Uncaught Error: Call to undefined function safe_value() in
All that tells me is that somewhere you are trying to call that function in a context where it is not defined; so either you need to define it in that context, or add it to some file that gets included wherever you might need it, or...?
kumerbakul
I think the error might be misleading.
The line
if($value = safe_value($conn, $seardh))
is an assignment.
I believe the code is supposed to be a comparison and so should use the == operator
if($value == safe_value($conn, $seardh))
Try that.
RayPooley think the error might be misleading.
The line
if($value = safe_value($conn, $seardh))
is an assignment.
I believe the code is supposed to be a comparison and so should use the == operator
if($value == safe_value($conn, $seardh))
Try that.
That wouldn't make a difference. The value of the assignment is still either whatever safe_value()
returns, so the if()
statement still takes the same branch. The only difference is that $value
is also assigned the same value, which is a good thing, since it is then used later in the then branch.
Using ==
wouldn't fix anything because now you're comparing the return value of safe_value()
with the value of a variable that doesn't even have a value yet. (You'd get an Undefined variable warning, and take the "safe value" branch only in the situation when safe_value()
returns false.)
And, of course, it wouldn't fix the reported problem that the safe_value
function wasn't even found in the first place.
I do notice another bug, though: safe_value()
will return a falsy value if $_GET[$name]
is '0'
. It may not be relevant in this instance (what does the "time
" column contain if time LIKE '%$value%'
is useful?) but since we're retrieving every record that contains a 1
in the description it would be churlish to not be doing the same for 0
. I think the return value should be checked more carefully:
if(($value = safe_value($conn, $search)) !== false)
or even separate testing-for-content and escaping-for-query into two separate functions.
But yes, like @NogDog says, if your pagination thing is on a different page then you'll need to get the function there as well, preferably by putting it another file and including it on every page you need it. If that's not what you're doing you'll need to explain what you are doing.
Weedpacket
I'm talking about logic.
If the code is performing an assignment when it should be performing a comparison
then the outcome may well be unpredictable.
This is clearly questionable and therefore warrants attention.
if($value = safe_value($conn, $seardh)){
Because the next step in the process depends on the outcome of that statement ie: true or false.
A statement of the nature
if ($x = 88){
echo "true";
} else {
echo "false";
}
is ALWAYS going to evaluate TRUE and therefore the code in the first curly brackets in this case
foreach(['title', 'company', 'category', 'description', 'time'] as $column) {
$wheres[] = "`$column` LIKE '%$value%'";
}
is always going to be executed whether it's logically appropriate or not.
A statement of the nature
if ($x == 88){
echo "true";
} else {
echo "false";
}
will evaluate TRUE OR FALSE depending on whether $x has a value 88 and therefore the code in the
first curly brackets in this case
foreach(['title', 'company', 'category', 'description', 'time'] as $column) {
$wheres[] = "`$column` LIKE '%$value%'";
}
may be executed or it may not depending on the value of $x.
The fact that this block of code is encapsulated within an IF statement suggests that it should only
be executed conditionally.
If this code needs to be executed UNCONDITIONALLY then there's actually no logical reason in having
it subject to an IF condition at all.
RayPooley If you look at the definition of the safe_value()
function you'll see it can return a string and it can also return false
. If it returns false the second branch will be taken and the contents of $value
(which would be false
per the assignment) is ignored. If it returns a non-false value that value will be assigned to $value
and the first branch taken, where $value
is used.
Notice that $value
doesn't get assigned a value otherwise, so trying to compare its value to any other would be a mistake.
In addition to my previous.
Try moving the safe_value() function definition up to the top of the program.
Like this..
<?php
include 'config.php';
function safe_value(mysqli $conn, string $name) {
if(!isset($_GET[$name]) or trim($_GET[$name]) === '') {
return false;
}
// might want to add strtolower() or strtupper to this?
return mysqli_escape_string($conn, trim($_GET[$name]));
}
if(isset($_GET['search'])) {
$wheres = [];
foreach(['title', 'location'] as $search) {
if($value == safe_value($conn, $seardh)) { // something was entered for that search
foreach(['title', 'company', 'category', 'description', 'time'] as $column) {
$wheres[] = "`$column` LIKE '%$value%'";
}
}
}
if(count($wheres)) { // at least one of the search fields was set
$sql = "SELECT * FROM `products` WHERE\n".implode(" OR\n", $wheres)."\nORDER BY id DESC";
// uncomment the following if you want to debug the query:
// die("<pre>$sql</pre>");
$query = mysqli_query($conn, $sql) or die(mysqli_error());
while($items = mysqli_fetch_assoc($query)) {
// do stuff with result
}
} else {
// whatever you want to do if neither search field was supplied
}
?>
Weedpacket
You don't get what I am saying here.
I am talking about the statement ...
if($value = safe_value($conn, $seardh)) {
The IF statement is a CONDITIONAL statement.
It requires a COMPARISON expression that evaluates to a boolean value.
A boolean has two and only two possible values. true or false.
A COMPARISON expression contains COMPARISON operators.
== Equal $x == $y Returns true if $x is equal to $y
=== Identical $x === $y Returns true if $x is equal to $y, and they are of the same type
!= Not equal $x != $y Returns true if $x is not equal to $y
<> Not equal $x <> $y Returns true if $x is not equal to $y
!== Not identical $x !== $y Returns true if $x is not equal to $y, or they are not of the same type
Greater than $x > $y Returns true if $x is greater than $y
< Less than $x < $y Returns true if $x is less than $y
= Greater than or equal to $x >= $y Returns true if $x is greater than or equal to $y
<= Less than or equal to $x <= $y Returns true if $x is less than or equal to $y
<=>
Note that the "=" operator IS NOT IN the COMPARISON operators list.
That's because it is an ASSIGNMENT operator
x = y x = y The left operand gets set to the value of the expression on the right
x += y x = x + y Addition
x -= y x = x - y Subtraction
x *= y x = x * y Multiplication
x /= y x = x / y Division
x %= y x = x % y Modulus
Note that the "=" operator IS IN the ASSIGNMENT operators list.
An ASSIGNMENT returns only ONE value if tested. That would be TRUE. As I demonstrated
in a previous post. An ASSIGNMENT does not return FALSE. It may return an error code
if the data types of the operands are incompatible in a heavily typed environment in which
case the program would abend. But an ASSIGNMENT doesn't return FALSE if the statement
is valid.
The code ...
if($value = safe_value($conn, $seardh)) {
is not a legitimate IF statement.
It doesn't matter what the safe_value() function does. It doesn't matter what the operands
are. It is an ASSIGNMENT expression. Not a COMPARISON expression which is the type of statement
the IF statement requires.
The safe_value() function or what it does is irrelevant. By the way, a function shouldn't be
returning different data types (string or boolean). It should only return one data type.
RayPooley
You don't get what I'm saying.
The if
statement requires an expression that evaluates to a boolean (and if it doesn't get a boolean, it coerces what it does get into one). It does not care if that expression is a comparison or not.
https://www.php.net/manual/en/control-structures.if.php
The simplest yet most accurate way to define an expression is "anything that has a value".
https://www.php.net/manual/en/language.expressions.php
RayPooley An ASSIGNMENT returns only ONE value if tested. That would be TRUE.
No, it does not. It returns the value that was evaluated on the right-hand side.
The value of an assignment expression is the value assigned. That is, the value of "$a = 3" is 3.
https://www.php.net/manual/en/language.operators.assignment.php
RayPooley The safe_value() function or what it does is irrelevant. By the way, a function shouldn't be
returning different data types (string or boolean). It should only return one data type.
Frankly, I agree, but it is a common idiom in PHP with many of its inbuilt functions doing exactly that.
Weedpacket
I'm wasting my time here.
Here's a challenge.
See if you can get this IF statement to return false.
Only two rules.
You can change the initial value of $x.
You can change the assigned value of $x in the IF expression.
$x = 8;
if ($x = 88){
echo "true";
}
else
{
echo "false";
}
then try this one ..
$x = 8;
if ($x == 88){
echo "true";
}
else
{
echo "false";
}
RayPooley See if you can get this IF statement to return false.
More to the point:
$ php -a
Interactive shell
php > $tests = [true, false, 1, 0, 'something', ''];
php > foreach($tests as $test) {
php { if($var = $test) {
php { echo "'true' returned for '$test'\n";
php { } else {
php { echo "'false' returned for '$test'\n";
php { }
php { }
'true' returned for '1' // "...for'1'" because we're type-casting a Boolean to a string
'false' returned for '' // ditto
'true' returned for '1'
'false' returned for '0'
'true' returned for 'something'
'false' returned for ''
php >
That being said, the above is assuming loose-typing is okay in this case. If not, then you may have to do something more specific, such as to test explicitly for an empty string if that's what you care about. In that case you can do both an assignment and a comparison if you want, rather than doing the assignment in a separate line and then your if
statement -- whichever style you prefer.
php >
php > $tests = ['good', ' also okay ', ' ', ''];
php > foreach($tests as $test) {
php { if(($var = trim($test)) === '') {
php { echo "'$test' is empty\n";
php { } else {
php { echo "'$test' is not empty\n";
php { }
php { }
'good' is not empty
' also okay ' is not empty
' ' is empty
'' is empty
php >
NogDog
Not sure what point you are making but it remains the same.
ASSIGNMENT vs COMPARISON.
The assignment expression only ever evaluates to true.
The comparison expression evaluation depends on the comparison operator.
Change the $test values and observer the results.
$var = 10;
$test = 10;
if($var = $test) {
echo "true\n";
} else {
echo "false\n";
}
$var = 10;
$test = 10;
if($var == $test){
echo "true\n";
} else {
echo "false\n";
}
Again,
if ($x = $y) {}
only ever results in true.
Which goes to my main point.
There is no point using an assignment in an IF statement.
Because the whole point of an IF statement is to decide which branch to take in a program.
That requires at least two outcomes from the evaluation of the expression.
With an IF statement those two outcomes are either true or false.
More branch options require a SWITCH statement.
If the expression in the IF statement only produces one outcome then there's no point in using an IF statement.
The code ..
if($value = safe_value($conn, $seardh)) {
is not a legitimate IF statement.
RayPooley ...only ever results in true
Change what you are assigning to the variable to be something that is "false-y", e.g. 0 instead of 8.
$test = 0;
if($var = $test) {
echo "\$var is 'truth-y'\n";
} else {
echo "\$var is false-y\n";
}
This is basically the same as this example in the official PHP site's manual: https://www.php.net/manual/en/pdostatement.fetch.php#example-1079 where you can do a while()
loop that evaluates an assignment -- not a comparison -- with the loop ending when no more rows are returned by the method call, which instead returns false at that point:
<?php
function readDataForwards($dbh) {
$sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY BET';
$stmt = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT)) {
$data = $row[0] . "\t" . $row[1] . "\t" . $row[2] . "\n";
print $data;
}
}
I've been doing this sort of thing for both if()
and while()
structures for a couple decades now, and it continues to work fine for me, in spite of your assertion that it does not.
Here's another problem with using assignments in IF expressions.
Not only does the IF result in a true response all the time, making the
IF pointless, but the value of the variable on the left of the "=" changes.
In this example $var goes from 10 to 15. This is a debugging nightmare.
$var = 10;
$test = 15;
echo "Before IF var = ". $var." test = ".$test."<br />";
if($var = $test) {
echo "Called IF statement<br />";
}
echo "After IF var = ". $var." test = ".$test."<br />";
This produces
Before IF var = 10 test = 15
Called IF statement
After IF var = 15 test = 15
It is pretty clear in the documentation not just for PHP but for other languages
that there is a fundamental difference between the "=" and "==" operators.
It's also very clear what kind of expression an IF statement requires.
Not an assignment. A comparison. That's why it;s called a CONDITIONAL statement.
The fact that you have been writing bad software for decades is no excuse
for writing bad sofware. It tells me that you have never understood
programming and that somehow you have been able to get away with it
for a couple of decades which is an indictment on the industry to be frank.
You appear to have been writing VBScript IF statements for decades.
That's the only language I can think of where the "=" can be used in an IF statement
becuase the interpreter figures out how to treat it from the context of the code.
But nobody who knows what they are doing has tested or reviewed your programs.
PHP is an interpreted, loosely type scripting language.
It is very tolerant of bad programming practices. This is an example.
Sophisticated, heavily typed languages like C# are the opposite.
They are compiled and the compiler forces good programming practices.
For example if you try to use an assignment in an IF statement expression in C# the compiler will
immediately flag it as an error for the reasons I have explained. It's wrong.
RayPooley Here's another problem with using assignments in IF expressions.
Not only does the IF result in a true response all the time, making the
IF pointless
No it doesn't. What it does do is documented and I have already provided (and quoted!) a link to documentation that refutes your statement. Have you even tried any of your code to see what it does do?
$var = 10;
$test = 15;
echo "Before IF var = ". $var." test = ".$test."<br />";
if($var = $test) {
echo "Called IF statement<br />";
}
echo "After IF var = ". $var." test = ".$test."<br />";
Neat. Now do the same test but initialise $test
to 0
.
, but the value of the variable on the left of the "=" changes.
Which is the entire point of using the assignment. That's what the assignment operator is for. That's why it was used. To put the value returned from the function call into the variable.
It is pretty clear in the documentation not just for PHP but for other languages
that there is a fundamental difference between the "=" and "==" operators.
Yes, and in this instance, as you keep being told, ==
is the wrong one.
RayPooley For example if you try to use an assignment in an IF statement expression in C# the compiler will
immediately flag it as an error for the reasons I have explained. It's wrong.
The compiler flags it as a warning (CS0665, categories as a minor "Level 3" warning) because it is such an easy typo to make, but it is still legal. (You can turn it off with a #pragma warning disable CS0665
to assert that you really did mean to write it like that. That is not an option with compiler errors; there is no corresponding #pragma error disable
.)
The if statement requires a boolean-valued expression as the C# documentation asserts, and an assignment in which the right-hand side evaluates to a boolean value is a boolean-valued expression. Not every boolean value comes from evaluating a comparison operator and there is no reason to restrict which booleans an if statement is allowed to work with. The same behaviour is documented in C, C++, Java, and JavaScript. Along with PHP, all six languages assert that the if
statement takes an expression and does not require it to involve a comparison operator. All six allow the use of an assignment operation as the condition of an if
statement.
And here's the kicker: the code you wrote does not work. @NogDog's code does. You've never tested either.
RayPooley The fact that you have been writing bad software for decades is no excuse
for writing bad sofware. It tells me that you have never understood
programming and that somehow you have been able to get away with it
for a couple of decades which is an indictment on the industry to be frank.
You appear to have been writing VBScript IF statements for decades.
That's the only language I can think of where the "=" can be used in an IF statement
becuase the interpreter figures out how to treat it from the context of the code.
But nobody who knows what they are doing has tested or reviewed your programs.
But now your argument hast just degraded to personal insults.
@RayPooley you would do well to pay more attention to WeedPacket and NogDog and read their posts more carefully. They are very talented coders with years of experience.
If I can point something out, it'd be that checking a var assignment in your conditional is something commonly done -- with database query results and when reading a file, for example. Many of the examples in this thread are assigning a variable a scalar value, but when you assign a variable to the result of a function, then you have an opportunity to take a different course of action if that function finally returns an empty result. By "empty", I mean any value that evaluates to zero or false or null when checked in a conditional. Check this example from the docs on fgetcsv, for example:
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
In this case, the conditional check is with a while
statement rather than an if
statement, but you should realize that as soon as fgetcsv
returns false
, that signals there are no more lines to be read in the file and we exit the while loop. If, on the other hand, fgetcsv
returns the next line in the file, we echo
it and keep reading lines from the file.
NogDog
Could you please let me know why it's not working on POST method?
Further discussion on this topic has somehow ended up in another thread:
https://board.phpbuilder.com/d/10404850-search-get-method-working-nice-but-post-method-results-not-found