To jvm at jvmyers dot com:
Your first two if statements just check if there's anything in the string, if you wish to actually execute the code in your string you need eval().
Εκφράσεις
Οι εκφράσεις (expressions) είναι το πιο σηματικό κομμάτι της PHP. Στην PHP, σχεδόν όλα όσα γράφετε είναι εκφράσεις. Ο απλούστερος και συγχρόνως ο πιο ακριβής τρόπος για να ορίσουμε μια έκφραση είναι "οτιδήποτε έχει τιμή".
Οι πιο βασικές μορφές εκφράσεων είναι οι σταθερές και οι μεταβλητές. Όταν γράφετε "$a = 5", αναθέτε την τιμή '5' στη μεταβλητή $a. Το '5', προφανώς, έχει την τιμή 5, ή με άλλα λόγια το '5' είναι μια έκφραση με την τιμή 5 (σ'αυτή την περίπτωση, το '5' είναι μια ακέραια σταθερά).
Μετά από αυτή την ανάθεση, θα περιμένατε η τιμή του $a να είναι επίσης 5, έτσι ώστε αν γράψετε $b = $a, θα περιμένετε να έχετε το ίδιο αποτέλεσμα με το αυτό που θα είχατε αν γράφατε ότι $b = 5. Με άλλα λόγια, η $a είναι μια έκφραση με την τιμή 5 επίσης. Αν όλα δουλέψουν σωστά, αυτό ακριβώς θα συμβεί.
Ελαφρώς πιο περίπλοκα παραδείγματα στις εκφράσεις είναι οι συναρτήσεις. Για παράδειγμα, θεωρείστε την ακόλουθη συνάρτηση:
<?php
function foo ()
{
return 5;
}
?>
Υποθέτοντας ότι είστε εξοικειωμένοι με την έννοια των συναρτήσεων (αν δεν είστε ανατρέξτε στο κεφάλαιο το σχετικό με τις συναρτήσεις), θα υποθέσετε ότι γράφοντας $c = foo() είναι ουσιαστικά ίδιο με το να γράψετε $c = 5, και έχετε δίκιο. Οι συναρτήσεις είναι εκφράσεις με την τιμή της επιστρεφόμενης τιμής. Αφού το foo() επιστρέφει 5, η τιμή της έκφρασης 'foo()' είναι 5. Συνήθως οι συναρτήσεις δεν επιστρέφουν απλά μια στατική τιμή αλλά υπολογίζουν κάτι.
Φυσικά, οι τιμές στην PHP δεν είναι υποχρεωτικά ακέραιοι, και πολύ συχνά δεν είναι. Η PHP υποστηρίζει τρεις βαθμωτούς τύπους: ακέραιες τιμές, τιμές κινητής υποδιαστολής και συμβολοσειρές (οι βαθμωτές τιμές είναι τιμές που δεν μπορούμε να "σπάσουμε" σε μικρότερα κομμάτια, σε αντίθεση με τους πίνακες, για παράδειγμα). Η PHP επίσης υποστηρίζει δυο σύνθετους (μη βαθμωτούς) τύπους: τους πίνακες (arrays) και τα αντικείμενα (objects). Ο κάθε ένας από αυτούς τους τύπους τιμών μπορεί να ανατεθεί σε μεταβλητές ή να επιστραφεί (returned) από συναρτήσεις.
Μέχρι στιγμής, οι χρήστες της PHP/FI 2 δε θα βρούν κάποια διαφορά. Παρ' όλα αυτά, η PHP προχωράει τις εκφράσεις πιο μακριά, κατά τον ίδιο τρόπο που το κάνουν και άλλες γλώσσες. Η PHP είναι μια γλώσσα προσανατολισμένη στις εκφράσεις (expression-oriented), με την έννοια ότι σχεδόν τα πάντα είναι εκφράσεις. Θεωρείστε το παράδειγμα με το οποίο έχουμε ήδη ασχοληθεί, '$a = 5'. Είναι εύκολο να δείτε ότι υπάρχουν δύο τιμές εδώ, η τιμή της ακέραιας σταθεράς '5', και η τιμή της μεταβλητής $a η οποία παίρνει επίσης την τιμή 5. Αλλά η αλήθεια είναι ότι υπάρχει μια επιπρόσθετη τιμή που εμπλέκεται εδώ, και αυτή είναι η τιμή της ίδιας της ανάθεσης. Η ίδια η ανάθεση (assignment) παίρνει την ανατιθέμενη τιμή, που στην περίπτωση μας είναι η 5. Πρακτικά, αυτό σημαίνει ότι '$a = 5',ασχέτως από το τι κάνει, είναι μια έκφραση με τιμή ίση με 5. Συνεπώς, γράφοντας κάτι σαν '$b = ($a = 5)' είναι σα να γράφουμε '$a = 5; $b = 5;' (το ερωτηματικό ορίζει το τέλος μιας έκφρασης). Αφού οι αναθέσεις μεταγλωτίζονται από δεξιά προς τα αριστερά, μπορείτε επίσης να γράψετε '$b = $a = 5'.
Ένα ακόμη καλό παράδειγμα σχετικά με εκφράσεις είναι η πριν (pre-) και μετά (post-) αύξηση και μείωση. Οι χρήστες της PHP/FI 2 και πολλών άλλων γλωσσών ίσως έχουν κάποια οικειότητα με τη μορφή variable++ και variable--. Αυτοί είναι οι τελεστές αύξησης και μείωσης. Στην PHP/FI 2, η δήλωση '$a++' δεν έχει τιμή (δεν είναι έκφραση), και συνεπώς δεν μπορείτε να την αναθέσετε ούτε να την χρησιμοποιήσετε. Η PHP αυξάνει τις δυνατότητες αύξησης/μείωσης χρησιμοποιώντας αυτές της εκφράσεις όπως και η C. Στην PHP, όπως και στη C, υπάρχουν δυο τύποι αύξησης - η (προ) pre-increment και η (μετά) post-increment. Και οι δυο ουσιαστικά αυξάνουν την τιμή της μεταβλητής, και η επίδραση τους στην μεταβλητή είναι η ίδια. Η διαφορά είναι στην τιμή της μεταβλητής που αυξάνεται. Η pre-increment, η οποία γράφεται '++$variable', παίρνει την αυξανόμενη τιμή (η PHP αυξάνει τη μεταβλητή πριν διαβάσει την τιμή της, εξού και (προ)'pre-increment'). Η post-increment, η οποία γράφεται '$variable++' παίρνει την αρχική τιμή της μεταβλητής $variable, πριν αυτή αυξηθεί (η PHP αυξάνει τη μεταβλητή αφού διαβάσει την τιμή της, εξού και το όνομα (μετά) 'post-increment')
Ένας πολύ κοινός τύπος εκφράσεων είναι οι συγκρίσεις. Αυτές οι εκφράσεις παίρνουν είτε την τιμή 0 είτε την τιμή 1, δηλαδή FALSE ή TRUE (αντίστοιχα). Η PHP υποστηρίζει τα > (μεγαλύτερο από), >= (μεγαλύτερο από ή ίσο με), == (ίσο), != (όχι ίσο), < (μικρότερο από) και <= (μικρότερο ή ίσο με). Αυτές οι εκφράσεις χρησιμοποιούνται συνήθως μέσα σε υποθέσεις, όπως οι if δηλώσεις.
Το τελευταίο παράδειγμα εκφράσεων με το οποίο θα ασχοληθούμε είναι οι σύνθετες εκφράσεις τελεστών-αναθέσεων. Θα ξέρετε ήδη ότι αν θέλετε να αυξήσετε το $a κατά 1, μπορείτε απλά να γράψετε '$a++' ή '++$a'. Αλλά τι γίνεται να θέλετε να προσθέσετε περισσότερα από ένα, 3 για παράδειγμα? Θα μπορούσατε να γράψετε '$a++' πολλές φορές, αλλά αυτό προφανώς δεν είναι ένας πολύ αποτελεσματικός ή άνετος τρόπος. Μια πιο κοινή τακτική είναι να γράψετε '$a = $a + 3'. Το '$a + 3' υπολογίζει την τιμή του $a συν 3, και αναθέτει την τιμή αυτή πίσω στην $a, η οποία καταλήγει στο να αυξηθεί κατά 3. Στην PHP, όπως και σε πολλές άλλες γλώσσες συμπεριλαμβανομένης και της C, μπορείτε να γράψετε το παραπάνω με ένα συντομότερο τρόπο, το οποίο θα γίνει πιο ξεκάθαρο και πιο γρήγορο στο να το καταλάβετε καλά. Η πρόσθεση του 3 στην τρέχουσα τιμή του $a μπορεί να γραφεί ως '$a += 3'. Αυτό ακριβώς σημαίνει "πάρε την τιμή του $a, πρόσθεσε 3 σ' αυτήν, και ανάθεσε την πάλι στην $a". Προκειμένου να γίνουμε πιο γρήγοροι και πιο σαφείς, μ'αυτόν τον τρόπο καταλήγουμε σε ταχύτερη εκτέλεση. Η τιμή του '$a += 3', όπως και η τιμή μιας κανονικής (regular) ανάθεσης, είναι η τιμή που έχει ανατεθεί. Σημειώστε ότι ΔΕΝ είναι 3, αλλά η τιμή της $a συν 3 (αυτή είναι η τιμή που ανατίθεται στην $a). Οποιοσδήποτε δυο-θέσεων τελεστής μπορεί να χρησιμοποιηθεί σ' αυτή την κατάσταση τελεστή-ανάθεσης, για παράδειγμα '$a -= 5' (αφαιρείται το 5 από την τιμή του $a), '$b *= 7' (πολλαπλασιάζεται η τιμή της $b με το 7), κτλ.
Υπάρχει ακόμη μια έκφραση που ίσως φανεί περίεργη αν δεν την έχετε δει σε άλλες γλώσσες, ο τριαδικός υποθετικός τελεστής:
<?php $first ? $second : $third ?>
Αν η τιμή της πρώτης υπό-έκφρασης είναι TRUE (όχι μηδέν), τότε γίνεται υπολογισμός της τιμής της δεύτερης υπό-έκφρασης, και αυτό είναι το αποτέλεσμα της υποθετικής έκφρασης. Διαφορετικά, η τρίτη υποέκφραση υπολογίζεται και αυτή είναι και η τιμή.
Το παρακάτω παράδειγμα θα σας βοηθήσει να καταλάβετε καλύτερα την προ- (pre-) και μετά- (post-) αύξηση και τις εκφράσεις γενικότερα:
<?php
function double($i)
{
return $i*2;
}
$b = $a = 5; /* assign the value five into the variable $a and $b */
$c = $a++; /* post-increment, assign original value of $a
(5) to $c */
$e = $d = ++$b; /* pre-increment, assign the incremented value of
$b (6) to $d and $e */
/* at this point, both $d and $e are equal to 6 */
$f = double($d++); /* assign twice the value of $d before
the increment, 2*6 = 12 to $f */
$g = double(++$e); /* assign twice the value of $e after
the increment, 2*7 = 14 to $g */
$h = $g += 10; /* first, $g is incremented by 10 and ends with the
value of 24. the value of the assignment (24) is
then assigned into $h, and $h ends with the value
of 24 as well. */
?>
Στην αρχή του κεφαλαίου, είπαμε ότι θα περιγράψουμε τους διάφορους τύπος δηλώσεων, και όπως υποσχεθήκαμε, οι εκφράσεις μπορούν να γίνουν δηλώσεις. Όπως και να έχει, δεν είναι κάθε έκφραση και δήλωση. Σ' αυτή την περίπτωση, μια δήλωση έχει τη μορφή 'expr' ';' το οποίο είναι μια έκφραση που ακολουθείται από ένα ελληνικό ερωτηματικό. Στο '$b=$a=5;', το $a=5 είναι μια έγκυρη έκφραση, αλλά δεν είναι από μόνη της μια έκφραση. Παρόλαυτα η έκφραση '$b=$a=5;' είναι μια έγκυρη δήλωση.
Ένα τελευταίο πράγμα που αξίζει να αναφέρουμε είναι η αληθινή αξία των εκφράσεων. Σε πολλά συμβάντα, κυρίως σε loops υποθετικά και εκτέλεσης, δεν ενδιαφέρεστε για τη συγκεκριμένη τιμή της έκφρασης, αλλά μόνο για το τι σημαίνει TRUE ή FALSE. Οι σταθερές TRUE και FALSE (είναι case-insensitive) είναι οι δυο πιθανές boolean τιμές. Όταν χρειάζεται, μια έκφραση αυτόματα μετατρέπεται σε boolean. Δείτε το τμήμα σχετικά με type-casting (μετατροπή τύπου) για λεπτομέρειες σχετικά με τον τρόπο.
Η PHP παρέχει μια πλήρη και δυνατή υλοποίηση των εκφράσεων, και η τεκμηρίωση της είναι πέρα από το σκοπό αυτού του εγχειριδίου. Τα παραπάνω παραδείγματα είναι για να σας δώσουν μια ιδέα σχετικά με το τι είναι οι εκφράσεις και πώς μπορείτε να σχηματίσετε χρήσιμες εκφράσεις. Στο υπόλοιπο manual θα γράφουμε expr για να συμβολίσουμε κάθε έγκυρη έκφραση στην PHP.
Εκφράσεις
16-Mar-2008 05:52
24-Feb-2008 12:20
<?php
// Compound booleans expressed as string args in an 'if' statement don't work as expected:
//
// Context:
// 1. I generate an array of counters
// 2. I dynamically generate a compound boolean based on selected counters in the array
// Note: since the real array is sparse, I must use the 'empty' operator
// 3. When I submit the compound boolean as the expression of an 'if' statement,
// the 'if' appears to resolve ONLY the first element of the compound boolean.
// Conclusion: appears to be a short-circuiting issue
$aArray = array(1,0);
// Case 1: 'if' expression passed as string:
$sCondition = "!empty($aArray[0]) && !empty($aArray[1])";
if ($sCondition)
{
echo "1. Conditions met<br />";
}
else
{
echo "1. Conditions not met<br />";
}
// Case 1 output: "1. Conditions met"
// Case 2: same as Case 1, but using catenation operator
if ("".$sCondition."")
{
echo "2. Conditions met<br />";
}
else
{
echo "2. Conditions not met<br />";
}
// Case 2 output: "2. Conditions met"
// Case 3: same 'if' expression but passed in context:
if (!empty($aArray[0]) && !empty($aArray[1]))
{
echo "3. Conditions met<br />";
}
else
{
echo "3. Conditions not met<br />";
}
// Case 3 output: "3. Conditions not met"
// jvm@jvmyers.com
?>
PS: the bug folks say this "does not imply a bug in PHP itself." Sure bugs me!
20-Oct-2007 08:41
Regarding the ternary operator, I would rather say that the best option is to enclose all the expression in parantheses, to avoid errors and improve clarity:
<?php
print ( $a > 1 ? "many" : "just one" );
?>
PS: for php, C++, and any other language that has it.
23-Aug-2007 01:42
reply to egonfreeman at gmail dot com
04-Apr-2007 07:45
the second example u mentioned as follow:
=====================================
$n = 3;
$n * $n++
from 3 * 3 into 3 * 4. Post- operations operate on a variable after it has been 'checked', but it doesn't necessarily state that it should happen AFTER an evaluation is over (on the contrary, as a matter of fact).
===========================================
everything works correctly but one sentence should be modified:
"from 3 * 3 into 3 * 4" should be "from 3 * 3 into 4 * 3"
best regards~ :)
20-Jul-2007 11:01
Here's a quick example of Pre and Post-incrementation, in case anyone does feel confused (ref anonymous poster 31 May 2005)
<?PHP
echo "Using Pre-increment ++\$a:<br>";
$a = 1;
echo "\$a = $a<br>";
$b = ++$a;
echo "\$b = ++\$a, so \$b = $b and \$a = $a<br>";
echo "<br>";
echo "Using Post-increment \$a++:<br>";
$a = 1;
echo "\$a = $a<br>";
$b = $a++;
echo "\$b = \$a++, so \$b = $b and \$a = $a<br>";
?>
HTH
04-Apr-2007 07:45
It is worthy to mention that:
$n = 3;
$n * --$n
WILL RETURN 4 instead of 6.
It can be a hard to spot "error", because in our human thought process this really isn't an error at all! But you have to remember that PHP (as it is with many other high-level languages) evaluates its statements RIGHT-TO-LEFT, and therefore "--$n" comes BEFORE multiplying, so - in the end - it's really "2 * 2", not "3 * 2".
It is also worthy to mention that the same behavior will change:
$n = 3;
$n * $n++
from 3 * 3 into 3 * 4. Post- operations operate on a variable after it has been 'checked', but it doesn't necessarily state that it should happen AFTER an evaluation is over (on the contrary, as a matter of fact).
So, if you ever find yourself on a 'wild goose chase' for a bug in that "impossible-to-break, so-very-simple" piece of code that uses pre-/post-'s, remember this post. :)
(just thought I'd check it out - turns out I was right :P)
14-Feb-2007 04:56
An easy fix (although intuitively tough to do...) is to reverse the comparison.
if (5 == $a) {}
If you forget the second '=', you'll get a parse error for trying to assign a value to a non-variable.
29-Jan-2007 07:46
Attention! php will not warn you if you write (1) When you mean (2)
(1)
<?
if($a=0)
echo "condition is true";
else
echo "condition is false";
//output: condition is false
?>
(2)
<?
if($a==0)
echo "condition is true";
else
echo "condition is false";
//output: condition is true
?>
19-Jan-2006 12:00
Follow up on Martin K. There are no hard and fast rules regarding operator precedence. Newbies should definitely learn them, but if their use results in code that is not easy to read you should use parentheses. The two important things are that it works properly AND is maintainable by you and others.
20-Oct-2005 06:28
At 04-Feb-2005 05:13, tom at darlingpet dot com said:
> It's also a good idea to use parenthesis when using something SIMILAR to:
>
> <?php
> echo (trim($var)=="") ? "empty" : "not empty";
> ?>
No, it's a BAD idea.
All the short-circuiting operators, including the ternary conditional operator, have LOWER precedence than the comparison operators, so they almost NEVER need parentheses around their subexpressions.
Inserting the parentheses suggested above does not change the meaning of the code, but their use misleads inexperienced programmers to expect that things like this will work in a similar manner:
<?php
function my_print($a) { print($a); }
my_print (trim($var)=="") ? "empty" : "not empty";
?>
when of course it doesn't.
Rather than worrying that code doesn't work as expected, simply learn the precedence rules (http://www.php.net/manual/en/language.operators.php) so that one expects the right things.
19-Aug-2005 05:06
12345alex at gmx dot net 's case is actually handled by the === operator. That's what he needs.
There is also another widely used function. I call it myself is_nil which is true for NULL,FALSE,array() and '', but not for 0 and "0".
function is_nil ($value) {
return !$value && $value !== 0 && $value !== '0';
}
Another useful function is "get first argument if it is not empty or get second argument otherwise". The code is:
function def ($value, $defaultValue) {
return is_nil ($value) ? $defaultValue : $value;
}
14-Aug-2005 07:00
this code:
print array() == NULL ? "True" : "False";
print " (" . (array() == NULL) . ")\n";
$arr = array();
print array() == $arr ? "True" : "False";
print " (" . (array() == $arr) . ")\n";
print count(array()) . "\n";
print count(NULL) . "\n";
will output (on php4 and php5):
True (1)
True (1)
0
0
so to decide wether i have NULL or an empty array i will also have to use gettype(). this seems some kind of weird for me, although if is this is a bug, somebody should have noticed it before.
alex
26-Jun-2005 11:25
Pre- and Post-Incrementation, I believe, are important to note and in the correct place. The section deals with the value of an expression. ++$a and $a++ have different values, and both forms have valid uses.
And, because it can be confusing, it is that much more important to note. Although it could be worded better, it does belong.
I don't see why it is necessary here to explain pre- and post- incrementing.
This is something that will confuse new users of PHP, even longer time programmers will sometimes miss a the fine details of a construct like that.
If something has a side-effect it should be on a line of it's own, or at least be an expression of it's own and not part of an assignment, condition or whatever.
04-Feb-2005 02:13
Something I've noticed with ternary expressions is if you do something like :
<?= $var=="something" ? "is something" : "not something"; ?>
It will give wacky results sometimes...
So be sure to enclose the ternary expression in parenthesis when ever necessary (such as having multiple expressions or nested ternary expressions)
The above could look like:
<?= ($var=="something") ? "is something" : "not something"; ?>
It's also a good idea to use parenthesis when using something SIMILAR to:
<?php
echo (trim($var)=="") ? "empty" : "not empty";
?>
In some cases other than the <?= ?> example, not placing the entire expression in appropriate parenthesis might yield undesirable results as well.. but I'm not quite sure.
25-Feb-2003 02:37
The short-circuit feature is indeed intended, and there are two types of evaluators, those who DO short-circuit, and those who DON'T, || / && and | / & respectively.
The latter method is the bitwise operators, but works great with the usual boolean values ( 0/1 )
So if you don't want short-circuiting, try using the | and & instead.
Read more about the bitwise operators here:
http://www.php.net/manual/en/language.operators.bitwise.php
07-Aug-2002 06:06
The short-circuiting IS a feature. It is also available in C, so I suppose the developers wont remove it in future PHP versions.
It is rather nice to write:
$file=fopen("foo","r") or die("Error!");
Greets,
Oliver
17-Jul-2002 11:08
It should probably be mentioned that the short-circuiting of expressions (mentioned in some of the comments above) is often called "lazy evaluation" (in case someone else searches for the term "lazy" on this page and comes up empty!).
25-May-2002 03:29
A note about the short-circuit behaviour of the boolean operators.
1. if (func1() || func2())
Now, if func1() returns true, func2() isn't run, since the expression
will be true anyway.
2. if (func1() && func2())
Now, if func1() returns false, func2() isn't run, since the expression
will be false anyway.
The reason for this behaviour comes probably from the programming
language C, on which PHP seems to be based on. There the
short-circuiting can be a very useful tool. For example:
int * myarray = a_func_to_set_myarray(); // init the array
if (myarray != NULL && myarray[0] != 4321) // check
myarray[0] = 1234;
Now, the pointer myarray is checked for being not null, then the
contents of the array is validated. This is important, because if
you try to access an array whose address is invalid, the program
will crash and die a horrible death. But thanks to the short
circuiting, if myarray == NULL then myarray[0] won't be accessed,
and the program will work fine.
11-Mar-2001 11:14
Manual defines "expression is anything that has value", Therefore, parser will give error for following code.
($val) ? echo('true') : echo('false');
Note: "? : " operator has this syntax "expr ? expr : expr;"
since echo does not have(return) value and ?: expects expression(value).
However, if function/language constructs that have/return value, such as include(), parser compiles code.
Note: User defined functions always have/return value without explicit return statement (returns NULL if there is no return statement). Therefore, user defined functions are always valid expressions.
[It may be useful to have VOID as new type to prevent programmer to use function as RVALUE by mistake]
For example,
($val) ? include('true.inc') : include('false.inc');
is valid, since "include" returns value.
The fact "echo" does not return value(="echo" is not a expression), is less obvious to me.
Print() and Echo() is NOT identical since print() has/returns value and can be a valid expression.
24-Nov-2000 11:01
The ternary conditional operator is a useful way of avoiding inconvenient if statements. They can even be used in the middle of a string concatenation, if you use parentheses.
Example:
if ( $wakka ) {
$string = 'foo' ;
} else {
$string = 'bar' ;
}
The above can be expressed like the following:
$string = $wakka ? 'foo' : 'bar' ;
If $wakka is true, $string is assigned 'foo', and if it's false, $string is assigned 'bar'.
To do the same in a concatenation, try:
$string = $otherString . ( $wakka ? 'foo' : 'bar' ) ;
