式は、PHP における最も重要なビルディングブロックです。PHPにおいては、ほとんど全てのものは式で記述されます。 最も簡単で最も正確な式の定義は、"値があるもの全て"です。

考えられる簡単な例は、定数と変数です。 "$a = 5" と入力すると、$a に '5' を代入することになります。 '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 は、4 種類のスカラー型: 整数(int)、 浮動小数点数(float)、文字列(string)、 真偽値(bool) をサポートします。 (スカラーとは、配列とかと異なり、より小さな部分に'分割する'ことができない値のことです。) PHP は、2種類の複合(非スカラー)型(配列とオブジェクト)もサポートします。 これらの型の値は、変数に代入することができ、 関数からの返り値とすることができます。

PHP は、他の多くの言語が行うのと同じ手法で、 更に多くの式を使用可能です。 PHP は、ほとんど全てが式であるという意味で、式指向の言語です。 既に取り扱った '$a = 5' という例について考えてみましょう。 この式には、整数定数の '5' と 5 に更新された $a の値という 2 つの値が現れているということに容易に気づくことでしょう。 しかし、実際には、ここにはもうひとつの値が含まれています。 それは、代入自体の値です。 代入式は、それ自体、代入値を評価します。 この場合、その値は 5 になります。 このことは、実際には、'$a = 5' は、それが何をするかによらず、 値 5 を有する式であることを意味します。 つまり、 '$b = ($a = 5)' のように書くことは、 '$a = 5; $b = 5;' と書くのと 同様なのです。(セミコロンは、文の終わりを示します。) 代入は、右から左へ実行されるため、'$b = $a = 5' と書くことも 可能です。

式の配置に関する別の良い例は、前置、後置加算子、あるいは減算子です。 PHP と他の多くの言語のユーザーは、variable++variable-- といった表記法に慣れていることでしょう。 これらは、加算子および減算子です。 PHP においては、C 言語のように、 前置加算と後置加算という、2 種類の加算があります。 前置加算と後置加算は、両方とも、基本的には変数を増加させ、 変数に対する効果は同じです。 異なっているのは、加算する式の値です。 前置加算は、'++$variable' と書かれますが、 加算後の値を評価します (PHP はその値を読む前に変数を増加させるので、'前置加算(pre-increment)' という名前がついています)。 後置加算は、'$variable++' と書かれますが、加算される前の $variable の元の値を評価します。 (PHP は、その値を読んだ後に変数を増加させるので、 '後置加算(post-increment)' という名前がついています。)

比較演算子は、 極めて標準的な式です。 比較演算子は、false または true のどちらかを値とします。 PHPは、>(大なり)、 >=(大なりイコール)、=(イコール)、 <(小なり)、<=(小なりイコール)をサポートします。 PHP 言語は、いくつかの厳密な等価演算子: === (イコールかつ同じ型) そして !== (イコールではないまたは型が違う) も サポートします。 これらの式は、if文のような条件式の内部で一般的に 使用されます。

式の最後の例として、ここでは、演算子+代入式の複合演算式 を扱います。 既にご存知のように、$a に 1 を加えたい場合は、'$a++' または '++$a' と書くだけで十分です。 しかし、1より大きな数、例えば 3 を加えたい場合は、どうすればよいのでしょう? '$a++' を複数回使うこともできますが、当然これはあまり効率的で快適な手法ではありません。 ふつうは、'$a = $a + 3' と書きます。 '$a + 3' の部分で $a の値に 3 を加えた値を評価し、 その結果を $a に代入するというわけです。 この結果、$a に 3 が加えられます。 PHP においては、C のような他の言語と同様に、 この例をより短かく書くことができます。 これにより、より明確になり、同時に理解も迅速になります。 $a の現在の値に 3 を加える式は、 '$a += 3' と書くことができます。 この式の正確な意味は、 "$a の値を取得し、それに 3 を加え、$a に再代入しなさい。" です。 より短く、明確になっただけでなく、実行もより高速になります。 '$a += 3' の値は、通常の代入と同様に、代入された値です。 この値は 3 ではなく、$a に 3 を加えた加算値 (この値が、$a に代入された値です)であることに注意してください。 '$a -= 5' ($a から 5 を引く) や '$b *= 7' ($b に 7 をかける)等のように、 全ての 2 項演算子は、この演算子+代入式のモードで使用することができます。

もう一種類、三項演算子(ternary operator)を用いた式がありますが、 他の言語で見たことがない場合には理解できないかもしれません。

<?php
$first 
$second $third
?>

最初の部分式の値が true (非ゼロ)の場合、二番目の部分式が評価され、 この条件文の結果となります。 そうでない場合、三番目の部分式が評価され、この文の値となります。

次の例は、前置および後置加算子と多少一般的な式の理解を 助けてくれることでしょう。

<?php
function double($i) {
    return 
$i*2;
}
$b $a 5;        /* 値 5 を $a と $b に代入します */
$c $a++;          /* 後置加算なので、$c に代入される値は、$a の
                       元の値 (5) です */
$e $d = ++$b;     /* 前置加算なので、$d と $e に代入される値は、
                       加算後の $b の値 (6) です */

/* ここまでで、$d と $e は、6 です */

$f double($d++);  /* $f には、$d が加算される前の値を2倍した値、
                       つまり 2*6 = 12 が、代入されます。 */
$g double(++$e);  /* $g には、$e が加算された後の値を2倍した値、
                        つまり 2*7 = 14 が、代入されます。 */
$h $g += 10;      /* まず、$g に 10 が加算され、24 になります。
                       代入値 (24) は、$h に代入されます。
                       そして、$h も同様に 24 になります。 */
?>

式が、文として扱われることがあります。 この場合、文は、'式 ;' 、つまり式の後にセミコロンがついた形式です。 '$b = $a =5;' において、'$a = 5' は有効な式ですが、 自身を値とする文では ありません。しかし、'$b = $a = 5;' は有効な文です。

最後に、有益な事項として式の論理値について説明します。 多くのイベント、主に条件付き実行とループにおいて、 式の特定な値には関心がないが、true または false のどちらを 意味するかに関心があるということがあります。 定数truefalse(大文字小文字を区別しない)は、論理型の値がとり得る 値です。必要に応じて式は論理値に変換されます。詳細な手法については、 型キャストに関するセクション を参照ください。

PHP は、完全で強力な式の実装を提供します。 それを完全に記述することは、このマニュアルの範囲を超えています。 上記の例は、式とは何か、そして、便利な式をどうやって作るかということ に関して良いアイデアを与えるに違いありません。 本マニュアルの残りの部分ではexprという マークを使用しますが、これは PHP の有効な式を意味します。

add a note add a note

User Contributed Notes 21 notes

up
43
yasuo_ohgaki at hotmail dot com
23 years ago
Manual defines "expression is anything that has value", Therefore, parser will give error for following code.

<?php
($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,

<?php
($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.
up
39
Magnus Deininger, dma05 at web dot de
15 years ago
Note that even though PHP borrows large portions of its syntax from C, the ',' is treated quite differently. It's not possible to create combined expressions in PHP using the comma-operator that C has, except in for() loops.

Example (parse error):

<?php

$a
= 2, $b = 4;

echo
$a."\n";
echo
$b."\n";

?>

Example (works):
<?php

for ($a = 2, $b = 4; $a < 3; $a++)
{
  echo
$a."\n";
  echo
$b."\n";
}

?>

This is because PHP doesn't actually have a proper comma-operator, it's only supported as syntactic sugar in for() loop headers. In C, it would have been perfectly legitimate to have this:

int f()
{
  int a, b;
  a = 2, b = 4;

  return a;
}

or even this:

int g()
{
  int a, b;
  a = (2, b = 4);

  return a;
}

In f(), a would have been set to 2, and b would have been set to 4.
In g(), (2, b = 4) would be a single expression which evaluates to 4, so both a and b would have been set to 4.
up
15
chriswarbo at gmail dot com
10 years ago
Note that there is a difference between a function and a function call, and both
are expressions. PHP has two kinds of function, "named functions" and "anonymous
functions". Here's an example with both:

<?php
// A named function. Its name is "double".
function double($x) {
  return
2 * $x;
}

// An anonymous function. It has no name, in the same way that the string
// "hello" has no name. Since it is an expression, we can give it a temporary
// name by assigning it to the variable $triple.
$triple = function($x) {
  return
3 * $x;
};
?>

We can "call" (or "run") both kinds of function. A "function call" is an
expression with the value of whatever the function returns. For example:

<?php
// The easiest way to run a function is to put () after its name, containing its
// arguments (if any)
$my_numbers = array(double(5), $triple(5));
?>

$my_numbers is now an array containing 10 and 15, which are the return values of
double and $triple when applied to the number 5.

Importantly, if we *don't* call a function, ie. we don't put () after its name,
then we still get expressions. For example:

<?php
$my_functions
= array('double', $triple);
?>

$my_functions is now an array containing these two functions. Notice that named
functions are more awkward than anonymous functions. PHP treats them differently
because it didn't use to have anonymous functions, and the way named functions
were implemented didn't work for anonymous functions when they were eventually
added.

This means that instead of using a named function literally, like we can with
anonymous functions, we have to use a string containing its name instead. PHP
makes sure that these strings will be treated as functions when it's
appropriate. For example:

<?php
$temp     
= 'double';
$my_number = $temp(5);
?>

$my_number will be 10, since PHP has spotted that we're treating a string as if
it were a function, so it has looked up that named function for us.

Unfortunately PHP's parser is very quirky; rather than looking for generic
patterns like "x(y)" and seeing if "x" is a function, it has lots of
special-cases like "$x(y)". This makes code like "'double'(5)" invalid, so we
have to do tricks like using temporary variables. There is another way around
this restriction though, and that is to pass our functions to the
"call_user_func" or "call_user_func_array" functions when we want to call them.
For example:

<?php
$my_numbers
= array(call_user_func('double', 5), call_user_func($triple, 5));
?>

$my_numbers contains 10 and 15 because "call_user_func" called our functions for
us. This is possible because the string 'double' and the anonymous function
$triple are expressions. Note that we can even use this technique to call an
anonymous function without ever giving it a name:

<?php
$my_number
= call_user_func(function($x) { return 4 * $x; }, 5);
?>

$my_number is now 20, since "call_user_func" called the anonymous function,
which quadruples its argument, with the value 5.

Passing functions around as expressions like this is very useful whenever we
need to use a 'callback'. Great examples of this are array_map and array_reduce.
up
7
oliver at hankeln-online dot de
21 years ago
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
up
8
shawnster
17 years ago
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.
up
8
winks716
16 years ago
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~ :)
up
9
Mattias at mail dot ee
21 years ago
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.
up
5
denzoo at gmail dot com
16 years ago
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().
up
5
petruzanauticoyahoo?com!ar
16 years ago
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.
up
2
Bichis Paul
7 years ago
Regarding 12345alex at gmx dot net's example:

I think you miss the identical equal documentation line from: http://php.net/manual/en/language.operators.comparison.php

$a == $b     Equal     TRUE if $a is equal to $b after type juggling.
$a === $b     Identical     TRUE if $a is equal to $b, and they are of the same type.

Try:
print array() === NULL ? "True" : "False";

Check this:
var_dump(is_null(array()));
up
4
tom at darlingpet dot com
19 years ago
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.
up
3
egonfreeman at gmail dot com
17 years ago
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)
up
2
Anonymous
18 years ago
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.
up
3
anthony at n dot o dot s dot p dot a dot m dot trams dot com
23 years ago
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' ) ;
up
2
richard at phase4 dot ie
18 years ago
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.
up
1
nabil_kadimi at hotmail dot com
17 years ago
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
?>
up
0
antickon at gmail dot com
12 years ago
evaluation order of subexpressions is not strictly defined for all operators

<?php
function a() {echo 'a';}
function
b() {echo 'b';}
a() == b(); // outputs "ab", ie evaluates left-to-right

$a = 3;
var_dump( $a == $a = 4 ); // outputs bool(true), ie evaluates right-to-left
?>

this is not a bug: "we [php developers] make no guarantee about the order of evaluation".
See https://bugs.php.net/bug.php?id=61188
up
0
jvm at jvmyers dot com
16 years ago
<?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!
up
-6
george dot langley at shaw dot ca
16 years ago
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
up
-10
12345alex at gmx dot net
18 years ago
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
up
-15
Martin K
18 years ago
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.
To Top