运算符
概述
运算符是对变量和值进行操作的符号。PHP提供了丰富的运算符集合,用于算术、比较、逻辑运算等。本章涵盖了所有PHP运算符,并提供实用示例和最佳实践。
算术运算符
基本算术运算
php
<?php
$a = 10;
$b = 3;
echo $a + $b; // 13(加法)
echo $a - $b; // 7(减法)
echo $a * $b; // 30(乘法)
echo $a / $b; // 3.333...(除法)
echo $a % $b; // 1(取模 - 余数)
echo $a ** $b; // 1000(幂运算,PHP 5.6+)
// 一元运算符
echo +$a; // 10(一元加)
echo -$a; // -10(一元减)
?>
### 除法和取模示例
```php
<?php
// 除法行为
echo 10 / 3; // 3.333...(浮点数结果)
echo 10 / 2; // 5(浮点数结果,即使是整数)
echo intval(10 / 3); // 3(整数除法)
// 取模示例
echo 10 % 3; // 1
echo 17 % 5; // 2
echo 8 % 4; // 0
// 取模的实用用法
function isEven($number) {
return $number % 2 === 0;
}
function isOdd($number) {
return $number % 2 === 1;
}
// 检查是否能被特定数字整除
function isDivisibleBy($number, $divisor) {
return $number % $divisor === 0;
}
echo isEven(4); // true
echo isOdd(7); // true
echo isDivisibleBy(15, 3); // true
?>幂运算
php
<?php
// 幂运算符(PHP 5.6+)
echo 2 ** 3; // 8(2的三次方)
echo 5 ** 2; // 25(5的平方)
echo 2 ** 0.5; // 1.414...(2的平方根)
// 使用pow()函数的替代方法
echo pow(2, 3); // 8
echo pow(5, 2); // 25
// 大数
echo 2 ** 10; // 1024
echo 2 ** 20; // 1048576
// 分数指数
echo 8 ** (1/3); // 2(8的立方根)
echo 16 ** 0.25; // 2(16的四次方根)
?>赋值运算符
基本赋值
php
<?php
$x = 10; // 基本赋值
$y = $x; // 复制赋值
$z = &$x; // 引用赋值
$x = 20;
echo $y; // 10(未改变)
echo $z; // 20(改变了,因为它是引用)
?>复合赋值运算符
php
<?php
$x = 10;
// 算术赋值
$x += 5; // $x = $x + 5 (15)
$x -= 3; // $x = $x - 3 (12)
$x *= 2; // $x = $x * 2 (24)
$x /= 4; // $x = $x / 4 (6)
$x %= 5; // $x = $x % 5 (1)
$x **= 3; // $x = $x ** 3 (1, PHP 5.6+)
// 字符串赋值
$str = "你好";
$str .= "世界"; // $str = $str . "世界" ("你好世界")
// 位运算赋值
$bits = 5; // 二进制:101
$bits &= 3; // $bits = $bits & 3 (1, 二进制:001)
$bits |= 2; // $bits = $bits | 2 (3, 二进制:011)
$bits ^= 1; // $bits = $bits ^ 1 (2, 二进制:010)
$bits <<= 1; // $bits = $bits << 1 (4, 二进制:100)
$bits >>= 1; // $bits = $bits >> 1 (2, 二进制:010)
// 空合并赋值(PHP 7.4+)
$config = null;
$config ??= '默认值'; // 仅在$config为null时赋值
echo $config; // "默认值"
$config ??= '另一个值'; // 不会赋值,因为$config不为null
echo $config; // 仍然是"默认值"
?>比较运算符
相等和全等
php
<?php
$a = 5;
$b = "5";
$c = 5;
// 相等(宽松比较)
var_dump($a == $b); // true(类型转换后值相等)
var_dump($a == $c); // true(类型和值都相同)
// 全等(严格比较)
var_dump($a === $b); // false(类型不同)
var_dump($a === $c); // true(类型和值都相同)
// 不相等
var_dump($a != $b); // false(值相等)
var_dump($a !== $b); // true(类型不同)
// 不同类型的示例
var_dump(0 == false); // true
var_dump(0 === false); // false
var_dump("" == false); // true
var_dump("" === false); // false
var_dump(null == false); // true
var_dump(null === false); // false
?>关系运算符
php
<?php
$x = 10;
$y = 20;
var_dump($x < $y); // true(小于)
var_dump($x > $y); // false(大于)
var_dump($x <= $y); // true(小于或等于)
var_dump($x >= $y); // false(大于或等于)
// 字符串比较
$str1 = "苹果";
$str2 = "香蕉";
var_dump($str1 < $str2); // true(按字典序)
// 数组比较
$arr1 = [1, 2, 3];
$arr2 = [1, 2, 4];
var_dump($arr1 < $arr2); // true(逐元素比較)
?>太空船运算符(PHP 7+)
php
<?php
// 太空船运算符返回 -1、0 或 1
echo 1 <=> 2; // -1(左边较小)
echo 2 <=> 2; // 0(相等)
echo 3 <=> 2; // 1(左边较大)
// 对排序有用
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];
usort($numbers, function($a, $b) {
return $a <=> $b; // 升序排序
});
print_r($numbers); // [1, 1, 2, 3, 4, 5, 6, 9]
// 字符串比较
echo "苹果" <=> "香蕉"; // -1
echo "你好" <=> "你好"; // 0
echo "斐马" <=> "苹果"; // 1
// 数组比较
echo [1, 2, 3] <=> [1, 2, 4]; // -1
echo [1, 2, 3] <=> [1, 2, 3]; // 0
?>逻辑运算符
布尔逻辑
php
<?php
$x = true;
$y = false;
// AND运算符
var_dump($x && $y); // false(逻辑与)
var_dump($x and $y); // false(逻辑与,低优先级)
// OR运算符
var_dump($x || $y); // true(逻辑或)
var_dump($x or $y); // true(逻辑或,低优先级)
// NOT运算符
var_dump(!$x); // false(逻辑非)
var_dump(!$y); // true(逻辑非)
// XOR运算符
var_dump($x xor $y); // true(异或)
var_dump($x xor $x); // false(相同值)
?>短路求值
php
<?php
function expensiveOperation() {
echo "执行昂贵操作\n";
return true;
}
$condition = false;
// 短路 AND - 第二个函数不会被调用
if ($condition && expensiveOperation()) {
echo "两个条件都为真\n";
}
$condition = true;
// 短路 OR - 第二个函数不会被调用
if ($condition || expensiveOperation()) {
echo "至少一个条件为真\n";
}
// 实际示例
$user = getCurrentUser();
if ($user && $user->isActive() && $user->hasPermission('admin')) {
// 安全链式调用 - 如果$user为null则不会调用方法
showAdminPanel();
}
?>优先级差异
php
<?php
// && vs and 优先级差异
$result1 = true && false || true; // true(计算为:(true && false) || true)
$result2 = true and false or true; // true(计算为:true and (false or true))
// 与逻辑运算符的赋值
$x = true && false; // $x = false
$y = true and false; // $y = true(赋值先发生)
echo $x ? 'true' : 'false'; // "false"
echo $y ? 'true' : 'false'; // "true"
?>递增和递减运算符
前置和后置递增/递减
php
<?php
$i = 5;
// 前置递增:先递增,再返回值
echo ++$i; // 6(i现在是6)
echo $i; // 6
$i = 5;
// 后置递增:先返回值,再递增
echo $i++; // 5(之后i变成6)
echo $i; // 6
$i = 5;
// 前置递减:先递减,再返回值
echo --$i; // 4(i现在是4)
echo $i; // 4
$i = 5;
// 后置递减:先返回值,再递减
echo $i--; // 5(之后i变成4)
echo $i; // 4
?>Practical Examples
php
<?php
// Loop counters
for ($i = 0; $i < 10; $i++) {
echo $i . " ";
}
// Output: 0 1 2 3 4 5 6 7 8 9
// Array processing
$items = ['a', 'b', 'c', 'd'];
$index = 0;
while ($index < count($items)) {
echo $items[$index++] . " ";
}
// Output: a b c d
// Unique ID generator
class IdGenerator {
private static $counter = 0;
public static function getNextId() {
return ++self::$counter;
}
}
echo IdGenerator::getNextId(); // 1
echo IdGenerator::getNextId(); // 2
echo IdGenerator::getNextId(); // 3
?>String Operators
Concatenation
php
<?php
$first = "Hello";
$second = "World";
// Concatenation operator
$result = $first . " " . $second; // "Hello World"
// Concatenation assignment
$message = "Hello";
$message .= " ";
$message .= "World";
echo $message; // "Hello World"
// Multiple concatenations
$name = "John";
$age = 30;
$info = "Name: " . $name . ", Age: " . $age;
echo $info; // "Name: John, Age: 30"
// Concatenation with numbers
$number = 42;
$text = "The answer is " . $number;
echo $text; // "The answer is 42"
?>String Interpolation vs Concatenation
php
<?php
$name = "Alice";
$age = 25;
// Double quotes with variable interpolation
$message1 = "Hello, $name! You are $age years old.";
// Concatenation
$message2 = "Hello, " . $name . "! You are " . $age . " years old.";
// Complex expressions (concatenation required)
$message3 = "Hello, " . strtoupper($name) . "! You are " . ($age + 1) . " next year.";
// Heredoc with interpolation
$message4 = <<<MSG
Hello, $name!
You are $age years old.
MSG;
echo $message1; // All produce the same result
?>Array Operators
Array Union and Comparison
php
<?php
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];
$array3 = [1, 2, 3];
// Array union (+ operator)
$union = $array1 + $array2;
print_r($union); // [1, 2, 3] (left array takes precedence)
$assoc1 = ['a' => 1, 'b' => 2];
$assoc2 = ['c' => 3, 'd' => 4];
$assocUnion = $assoc1 + $assoc2;
print_r($assocUnion); // ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]
// Array equality
var_dump($array1 == $array3); // true (same values)
var_dump($array1 === $array3); // true (same values and types)
var_dump($array1 == $array2); // false (different values)
// Array inequality
var_dump($array1 != $array2); // true
var_dump($array1 !== $array2); // true
?>Array Comparison Examples
php
<?php
// Order matters for indexed arrays
$arr1 = [1, 2, 3];
$arr2 = [3, 2, 1];
var_dump($arr1 == $arr2); // false (different order)
// Order doesn't matter for associative arrays (if keys match)
$assoc1 = ['name' => 'John', 'age' => 30];
$assoc2 = ['age' => 30, 'name' => 'John'];
var_dump($assoc1 == $assoc2); // true (same key-value pairs)
// Type matters for strict comparison
$numbers1 = [1, 2, 3];
$numbers2 = ["1", "2", "3"];
var_dump($numbers1 == $numbers2); // true (loose comparison)
var_dump($numbers1 === $numbers2); // false (strict comparison)
?>Bitwise Operators
Basic Bitwise Operations
php
<?php
$a = 5; // Binary: 101
$b = 3; // Binary: 011
// Bitwise AND
echo $a & $b; // 1 (Binary: 001)
// Bitwise OR
echo $a | $b; // 7 (Binary: 111)
// Bitwise XOR
echo $a ^ $b; // 6 (Binary: 110)
// Bitwise NOT
echo ~$a; // -6 (inverts all bits)
// Left shift
echo $a << 1; // 10 (Binary: 1010)
// Right shift
echo $a >> 1; // 2 (Binary: 10)
?>Practical Bitwise Examples
php
<?php
// Permission system using bitwise flags
class Permission {
const READ = 1; // Binary: 001
const WRITE = 2; // Binary: 010
const EXECUTE = 4; // Binary: 100
public static function hasPermission($userPerms, $requiredPerm) {
return ($userPerms & $requiredPerm) === $requiredPerm;
}
public static function addPermission($userPerms, $newPerm) {
return $userPerms | $newPerm;
}
public static function removePermission($userPerms, $removePerm) {
return $userPerms & ~$removePerm;
}
}
// User has READ and WRITE permissions
$userPermissions = Permission::READ | Permission::WRITE; // 3 (Binary: 011)
// Check permissions
var_dump(Permission::hasPermission($userPermissions, Permission::READ)); // true
var_dump(Permission::hasPermission($userPermissions, Permission::EXECUTE)); // false
// Add EXECUTE permission
$userPermissions = Permission::addPermission($userPermissions, Permission::EXECUTE);
var_dump(Permission::hasPermission($userPermissions, Permission::EXECUTE)); // true
// Remove WRITE permission
$userPermissions = Permission::removePermission($userPermissions, Permission::WRITE);
var_dump(Permission::hasPermission($userPermissions, Permission::WRITE)); // false
?>Ternary and Null Coalescing Operators
Ternary Operator
php
<?php
$age = 20;
// Basic ternary
$status = ($age >= 18) ? "adult" : "minor";
echo $status; // "adult"
// Nested ternary (not recommended for readability)
$grade = 85;
$letter = ($grade >= 90) ? 'A' : (($grade >= 80) ? 'B' : (($grade >= 70) ? 'C' : 'F'));
echo $letter; // "B"
// Better approach with if-elseif
if ($grade >= 90) {
$letter = 'A';
} elseif ($grade >= 80) {
$letter = 'B';
} elseif ($grade >= 70) {
$letter = 'C';
} else {
$letter = 'F';
}
// Ternary with function calls
$user = getCurrentUser();
$username = $user ? $user->getName() : 'Guest';
// Short ternary (Elvis operator, PHP 5.3+)
$username = $user->getName() ?: 'Guest'; // If getName() is falsy, use 'Guest'
?>Null Coalescing Operator (PHP 7+)
php
<?php
// Null coalescing operator (??)
$username = $_GET['user'] ?? $_POST['user'] ?? $_SESSION['user'] ?? 'guest';
// Equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] :
(isset($_POST['user']) ? $_POST['user'] :
(isset($_SESSION['user']) ? $_SESSION['user'] : 'guest'));
// Array access
$config = [
'database' => [
'host' => 'localhost'
]
];
$host = $config['database']['host'] ?? 'default_host';
$port = $config['database']['port'] ?? 3306;
// Function parameters
function createUser($name, $email = null, $role = null) {
$email = $email ?? generateEmail($name);
$role = $role ?? 'user';
// Create user logic
}
// Null coalescing assignment (PHP 7.4+)
$cache = null;
$cache ??= expensive_operation(); // Only calls function if $cache is null
?>Operator Precedence and Associativity
Precedence Examples
php
<?php
// Arithmetic precedence
echo 2 + 3 * 4; // 14 (not 20, multiplication first)
echo (2 + 3) * 4; // 20 (parentheses override precedence)
// Comparison and logical precedence
$x = 5;
$y = 10;
$z = 15;
// Comparison happens before logical AND
if ($x < $y && $y < $z) { // Evaluated as: ($x < $y) && ($y < $z)
echo "Values are in ascending order";
}
// Assignment and logical precedence
$result = true && false || true; // $result = ((true && false) || true) = true
$result2 = true and false or true; // $result2 = true (assignment happens first)
// Ternary precedence
echo true ? 'yes' : false ? 'maybe' : 'no'; // "yes" (left-associative)
?>Associativity Examples
php
<?php
// Left-associative operators
echo 10 - 5 - 2; // 3 (evaluated as: (10 - 5) - 2)
echo 20 / 4 / 2; // 2.5 (evaluated as: (20 / 4) / 2)
// Right-associative operators
$a = $b = $c = 10; // Evaluated as: $a = ($b = ($c = 10))
// Exponentiation is right-associative
echo 2 ** 3 ** 2; // 512 (evaluated as: 2 ** (3 ** 2) = 2 ** 9)
// Ternary is left-associative (unusual)
echo true ? 'a' : true ? 'b' : 'c'; // 'a' (evaluated as: (true ? 'a' : true) ? 'b' : 'c')
?>Type Operators
instanceof Operator
php
<?php
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
$dog = new Dog();
$cat = new Cat();
// instanceof checks
var_dump($dog instanceof Dog); // true
var_dump($dog instanceof Animal); // true (inheritance)
var_dump($dog instanceof Cat); // false
var_dump($cat instanceof Animal); // true
var_dump($cat instanceof Dog); // false
// Interface checking
interface Flyable {
public function fly();
}
class Bird implements Flyable {
public function fly() {
return "Flying high!";
}
}
$bird = new Bird();
var_dump($bird instanceof Flyable); // true
var_dump($bird instanceof Bird); // true
// String class names
$className = 'Dog';
var_dump($dog instanceof $className); // true
?>Error Control Operator
Suppressing Errors with @
php
<?php
// Error suppression (not recommended for most cases)
$result = @file_get_contents('nonexistent_file.txt');
if ($result === false) {
echo "File could not be read";
}
// Better approach with proper error handling
if (file_exists('data.txt')) {
$content = file_get_contents('data.txt');
} else {
echo "File not found";
}
// Useful for optional operations
$config = @json_decode($configString, true) ?: [];
// Division by zero suppression (still not recommended)
$result = @(10 / 0); // Returns INF instead of error
?>Execution Operator
Backtick Operator
php
<?php
// Execute shell commands (security risk - use carefully)
$output = `ls -la`;
echo $output;
// Equivalent to shell_exec()
$output2 = shell_exec('ls -la');
// Better approach with proper escaping
$directory = '/home/user';
$safeDirectory = escapeshellarg($directory);
$output3 = shell_exec("ls -la $safeDirectory");
// Always validate and sanitize input before executing commands
function safeExecute($command, $args = []) {
$escapedArgs = array_map('escapeshellarg', $args);
$fullCommand = $command . ' ' . implode(' ', $escapedArgs);
return shell_exec($fullCommand);
}
?>Next Steps
Now that you understand PHP operators, let's explore conditional statements in Conditional Statements.
Practice Exercises
- Create a calculator that uses all arithmetic operators
- Build a permission system using bitwise operators
- Implement comparison functions using spaceship operator
- Practice operator precedence with complex expressions
- Create utility functions that demonstrate null coalescing
Understanding operators is crucial for writing efficient and readable PHP code!