一、 开场白:别让运算符成为你的“血压飙升器”
各位码农兄弟姐妹们,有没有过这种经历——盯着自己写的PHP代码,明明逻辑清晰得能通过ISO认证,运行结果却魔幻得像春节返乡列车表?然后你瞪着屏幕半小时,最后发现罪魁祸首竟然是……一个写错的运算符!
(别问我怎么知道的,我的咖啡杯上还印着“曾经因为==写成=debug到凌晨三点”的耻辱印记)
今天咱们就来好好扒一扒PHP运算符这个“熟悉的陌生人”。放心,我不搞教科书那套“运算符优先级表”催眠术(那张表长得像地铁线路图,背下来的人可能已经羽化登仙了)。咱们主打一个说人话、讲实战、附带血泪教训,让你看完就能用到项目里,还能在代码评审时淡定怼回同事的质疑:“我这么写是有深度考虑的!”
二、 基础篇:四则运算?幼儿园大班水平!
1. 算术运算符:不只是计算器
<?php
// 你以为的算术运算
$price = 100;
$discount = 0.8;
$finalPrice = $price * $discount; // 80,小学乘法
// 实际项目中的骚操作
$userCount = 10;
$pageSize = 3;
// 计算总页数:ceil()是向上取整,但用运算符更直接
$totalPages = (int)(($userCount + $pageSize - 1) / $pageSize);
echo "用户数{$userCount},每页{$pageSize}条,需要{$totalPages}页\n";
// 输出:用户数10,每页3条,需要4页(懂这公式的请在评论区扣1)
// 取模运算的妙用:判断奇偶、分批次处理
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 == 0) {
echo "{$i}是偶数→分配A组处理\n";
} else {
echo "{$i}是奇数→分配B组处理\n";
}
}
?>
敲黑板重点:%取模运算符在循环分片、轮询任务中超级好用。比如你有1000个任务要分给5个工人:$workerIndex = $taskId % 5,每人领走200个,公平!
2. 字符串运算符:点号“.”的七十二变
<?php
// 基础拼接(谁都会)
$name = "张";
$fullName = $name . "三"; // 张三
// 实际开发中的坑爹场景
$sql = "SELECT * FROM users WHERE 1=1";
if ($keyword) {
$sql .= " AND name LIKE '%" . addslashes($keyword) . "%'";
}
// 看到问题了吗?SQL注入警告!应该用参数化查询,这里只是演示拼接
// 更常见的场景:生成动态HTML
$items = ['苹果', '香蕉', '橙子'];
$html = '<ul>';
foreach ($items as $item) {
$html .= "<li>{$item}</li>"; // 大括号包裹变量更清晰
}
$html .= '</ul>';
echo $html;
?>
防坑指南:.拼接大量字符串时性能堪忧,超过10次拼接请考虑用implode()或数组join。
三、 进阶篇:比较运算符的“罗生门”
这里是翻车重灾区,请系好安全带。
1. “==” vs “===” 世纪之战
<?php
// 大型迷惑行为现场
$testCases = [
["0" == false, "0" === false], // true, false
["" == 0, "" === 0], // true, false
[null == false, null === false], // true, false
["123" == 123, "123" === 123], // true, false
];
foreach ($testCases as $index => $case) {
echo "案例{$index}:==结果是" . ($case[0]?'true':'false') .
",===结果是" . ($case[1]?'true':'false') . "\n";
}
// 实战建议:除了明确需要类型转换,一律用===
function checkPassword($input, $stored) {
// 如果用==,0=="password"居然成立!恐怖!
return $input === $stored; // 必须严格相等
}
?>
黄金法则:除非你在写需要类型转换的魔术代码(比如从$_GET获取的参数),否则永远用===。你的同事和未来的你都会感谢这个决定。
2. 太空船运算符 “<=>”:不是外星科技
PHP 7.0加入的这个三个字符的怪物,其实超简单:
<?php
// 返回值就三种:-1(左边小)、0(相等)、1(左边大)
echo 5 <=> 3; // 1
echo 2 <=> 5; // -1
echo "b" <=> "a"; // 1(按ASCII比较)
echo "apple" <=> "banana"; // -1(首字母a<b)
// 实战:排序超好用
$products = [
['name'=>'手机', 'price'=>2999],
['name'=>'耳机', 'price'=>399],
['name'=>'电脑', 'price'=>8999]
];
// 按价格升序排序
usort($products, function($a, $b) {
return $a['price'] <=> $b['price'];
});
print_r($products);
// 输出:耳机(399)→手机(2999)→电脑(8999)
?>
四、 逻辑运算符:代码里的“心眼子”
1. 短路运算:智能偷懒
<?php
// && 和 || 的短路特性
function expensiveOperation() {
echo "别叫我,我很耗资源!\n";
return true;
}
$condition = false;
// 如果第一个条件为false,&&后面的根本不会执行
if ($condition && expensiveOperation()) {
echo "这行不会执行\n";
}
// 实际应用:安全判断
$user = getUserFromDB();
if ($user !== null && $user->isAdmin()) {
// 如果$user是null,不会调用isAdmin(),避免报错
echo "欢迎管理员";
}
// 赋值的骚操作
$config = $userConfig ?? $defaultConfig ?? [];
// 如果$userConfig存在且非null就用它,否则用$defaultConfig,都没有就空数组
?>
2. 优先级坑爹时刻
<?php
// 猜猜结果是什么?
$result1 = true && false; // false
$result2 = true and false; // true!惊不惊喜?
// 因为=的优先级高于and,所以相当于:
// $result2 = true; and false;
// 永远分开写复杂条件:
$result2 = (true and false); // 现在才是false
// 推荐的清晰写法:
$isValid = ($age >= 18);
$hasPermission = ($role === 'admin');
if ($isValid && $hasPermission) {
// 一目了然
}
?>
五、 位运算符:高端玩家的玩具
别怕,这玩意儿实际很有用。
<?php
// 权限系统经典案例
define('PERM_READ', 1); // 0001
define('PERM_WRITE', 2); // 0010
define('PERM_DELETE', 4); // 0100
define('PERM_ADMIN', 8); // 1000
// 给用户分配读+写权限
$userPerm = PERM_READ | PERM_WRITE; // 0011
// 检查是否有写权限
if ($userPerm & PERM_WRITE) {
echo "可以写入\n";
}
// 添加删除权限
$userPerm |= PERM_DELETE; // 现在有读、写、删权限
// 移除写权限
$userPerm &= ~PERM_WRITE;
echo "最终权限值:" . decbin($userPerm) . "\n"; // 二进制显示
?>
适用场景:权限系统、标志位、紧凑存储多个布尔值。一根烟的时间就能学会,装X效果满分。
六、 综合实战:电商优惠计算器
看懂了不一定会用,会用不一定能用好。来个大综合:
<?php
class DiscountCalculator {
// 综合运用各种运算符
public static function calculate($price, $userVipLevel, $coupon = null, $points = 0) {
// 1. 基础折扣(三元运算符)
$discount = ($userVipLevel >= 2) ? 0.9 : 1.0;
// 2. 优惠券(null合并运算符)
$couponValue = $coupon ?? 0;
// 3. 积分抵扣(每100积分抵1元,但不超过价格50%)
$pointsDiscount = min($price * 0.5, intval($points / 100));
// 4. 计算最终价格(确保不低于0)
$finalPrice = $price * $discount - $couponValue - $pointsDiscount;
$finalPrice = $finalPrice > 0 ? $finalPrice : 0;
// 5. 四舍五入保留两位(位运算取整技巧)
$finalPrice = round($finalPrice, 2);
return [
'原价' => $price,
'VIP折扣' => $discount,
'优惠券' => $couponValue,
'积分抵扣' => $pointsDiscount,
'最终价' => $finalPrice,
'节省' => $price - $finalPrice
];
}
}
// 测试用例
$testCases = [
['price'=>100, 'vip'=>1, 'coupon'=>null, 'points'=>50],
['price'=>200, 'vip'=>3, 'coupon'=>20, 'points'=>5000],
['price'=>50, 'vip'=>0, 'coupon'=>100, 'points'=>1000] // 券超过价格
];
foreach ($testCases as $case) {
$result = DiscountCalculator::calculate(
$case['price'],
$case['vip'],
$case['coupon'],
$case['points']
);
print_r($result);
echo str_repeat("-", 50) . "\n";
}
?>
七、 那些教科书不讲的“潜规则”
- 递增递减运算符的前后置区别:
$a = 1;
$b = $a++; // $b=1, $a=2(先用后加)
$c = ++$a; // $c=3, $a=3(先加后用)
// 循环中用前置++$i理论上更快(但现代PHP优化后差异可忽略)
- 字符串与数字比较的魔幻现实:
var_dump("10items" == 10); // true!PHP会提取开头的数字
var_dump("items10" == 10); // false!开头不是数字
// 再次强调:用===
- @错误抑制符:别用!
// 坏代码
$data = @file_get_contents('不存在的文件'); // 性能损耗+隐藏问题
// 好代码
$data = file_get_contents('文件');
if ($data === false) {
// 明确处理错误
}
八、 性能小贴士(面试装X用)
- 比较布尔值:
if ($isValid)比if ($isValid == true)快 - 乘除转换:
$a / 2可考虑$a * 0.5(乘法通常快于除法) - 预先计算:循环中的不变计算提到外面
// 不好
for ($i=0; $i<count($array); $i++) {}
// 好
$length = count($array);
for ($i=0; $i<$length; $i++) {}
九、 结语:运算符是你的瑞士军刀
运算符就像厨房里的刀具——切菜刀不能砍骨头,水果刀不能剁肉。用对了事半功倍,用错了轻则切手,重则炸锅。
终极建议:
- 初级:记住
===代替==,多用三元简化代码 - 中级:理解短路运算,善用
??空合并 - 高级:位运算优化权限系统,太空船简化排序
最后送各位一句话:代码是给人看的,顺便让机器执行。写的时候多想想三个月后的自己(或者接盘的同事)能不能看懂。运算符虽小,却是代码清晰度的放大镜。
(全文完,总字数约3200字,建议收藏反复食用)
彩蛋:测试你学废了吗?
<?php
// 猜猜输出什么?(答案在底部反白)
$a = 1;
$b = 2;
$c = 3;
$result = $a++ + ++$b * $c--;
echo $result . "\n"; // 答案:8 解析:1 + (3*3) = 10?等等再算算...
?>
PHP运算符全攻略:从入门到精通

被折叠的 条评论
为什么被折叠?



