Skip to content

运算符

概述

运算符是对变量和值进行操作的符号。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

  1. Create a calculator that uses all arithmetic operators
  2. Build a permission system using bitwise operators
  3. Implement comparison functions using spaceship operator
  4. Practice operator precedence with complex expressions
  5. Create utility functions that demonstrate null coalescing

Understanding operators is crucial for writing efficient and readable PHP code!

本站内容仅供学习和研究使用。