本章目标

  • 掌握PHP的基本语法规则
  • 学会使用变量和常量
  • 了解PHP的数据类型
  • 掌握运算符的使用
  • 学会编写注释和文档

2.1 PHP语法基础

2.1.1 PHP标记

PHP代码必须包含在PHP标记内:

<?php
// PHP代码
echo "Hello, World!";
?>

标记类型

<?php
// 标准开始标记(推荐)
echo "标准标记";
?>

<?= "短标记输出" ?>

<!-- 不推荐的标记 -->
<script language="php">
echo "脚本标记";
</script>

<% echo "ASP风格标记"; %>

2.1.2 语句分隔符

PHP使用分号(;)作为语句分隔符:

<?php
echo "第一条语句";
echo "第二条语句";

// 最后一条语句的分号可以省略(不推荐)
echo "最后一条语句"
?>

2.1.3 大小写敏感性

<?php
// 关键字、函数名、类名不区分大小写
ECHO "Hello";
echo "World";
Echo "PHP";

// 变量名区分大小写
$name = "张三";
$Name = "李四";
$NAME = "王五";

echo $name;  // 输出:张三
echo $Name;  // 输出:李四
echo $NAME;  // 输出:王五
?>

2.1.4 空白字符

PHP忽略空白字符(空格、制表符、换行符):

<?php
// 以下代码等价
echo"Hello";
echo "Hello";
echo    "Hello";
echo
    "Hello";
?>

2.2 变量

2.2.1 变量声明

PHP变量以美元符号($)开头:

<?php
// 变量声明和赋值
$name = "张三";
$age = 25;
$height = 1.75;
$isStudent = true;

// 变量可以改变类型
$value = 100;        // 整数
$value = "Hello";    // 字符串
$value = 3.14;       // 浮点数
?>

2.2.2 变量命名规则

<?php
// 正确的变量名
$name = "有效";
$_name = "有效";
$name123 = "有效";
$userName = "有效";
$user_name = "有效";

// 错误的变量名
// $123name = "无效";     // 不能以数字开头
// $user-name = "无效";   // 不能包含连字符
// $user name = "无效";   // 不能包含空格
// $class = "无效";       // class是关键字
?>

2.2.3 变量作用域

<?php
// 全局变量
$globalVar = "全局变量";

function testScope() {
    // 局部变量
    $localVar = "局部变量";
    
    // 访问全局变量
    global $globalVar;
    echo $globalVar;
    
    // 或使用$GLOBALS
    echo $GLOBALS['globalVar'];
}

// 静态变量
function counter() {
    static $count = 0;
    $count++;
    echo "调用次数: $count";
}

counter(); // 调用次数: 1
counter(); // 调用次数: 2
counter(); // 调用次数: 3
?>

2.2.4 可变变量

<?php
$var = "name";
$$var = "张三";

// 等价于 $name = "张三";
echo $name; // 输出:张三

// 多层可变变量
$a = "b";
$b = "c";
$c = "Hello";

echo $$$a; // 输出:Hello
?>

2.2.5 引用变量

<?php
$a = 10;
$b = &$a; // $b是$a的引用

$b = 20;
echo $a; // 输出:20

// 函数引用传递
function increment(&$value) {
    $value++;
}

$num = 5;
increment($num);
echo $num; // 输出:6
?>

2.3 常量

2.3.1 定义常量

<?php
// 使用define()函数
define("SITE_NAME", "我的网站");
define("VERSION", "1.0.0");
define("DEBUG", true);

// 使用const关键字(PHP 5.3+)
const DATABASE_HOST = "localhost";
const DATABASE_PORT = 3306;

echo SITE_NAME;      // 输出:我的网站
echo DATABASE_HOST;  // 输出:localhost
?>

2.3.2 常量特性

<?php
// 常量不能被重新定义
define("PI", 3.14);
// define("PI", 3.14159); // 会产生警告

// 常量默认区分大小写
define("GREETING", "Hello");
define("greeting", "Hi");

echo GREETING; // 输出:Hello
echo greeting; // 输出:Hi

// 定义不区分大小写的常量(PHP 7.3+已废弃)
define("WELCOME", "欢迎", true);
echo WELCOME; // 输出:欢迎
echo welcome; // 输出:欢迎
?>

2.3.3 预定义常量

<?php
// 魔术常量
echo __FILE__;     // 当前文件的完整路径
echo __DIR__;      // 当前文件所在目录
echo __LINE__;     // 当前行号
echo __FUNCTION__; // 当前函数名
echo __CLASS__;    // 当前类名
echo __METHOD__;   // 当前方法名
echo __NAMESPACE__; // 当前命名空间

// 系统常量
echo PHP_VERSION;        // PHP版本
echo PHP_OS;            // 操作系统
echo PHP_EOL;           // 换行符
echo DIRECTORY_SEPARATOR; // 目录分隔符

// 数学常量
echo M_PI;    // 圆周率
echo M_E;     // 自然对数的底
echo M_LOG2E; // log_2 e
?>

2.3.4 类常量

<?php
class MathConstants {
    const PI = 3.14159;
    const E = 2.71828;
    
    public function getCircleArea($radius) {
        return self::PI * $radius * $radius;
    }
}

echo MathConstants::PI; // 输出:3.14159

$math = new MathConstants();
echo $math->getCircleArea(5);
?>

2.4 数据类型

2.4.1 标量类型

布尔型(boolean)

<?php
$isTrue = true;
$isFalse = false;

// 转换为布尔值
var_dump((bool) 0);        // false
var_dump((bool) 1);        // true
var_dump((bool) "");       // false
var_dump((bool) "0");      // false
var_dump((bool) "false");  // true
var_dump((bool) []);       // false
var_dump((bool) null);     // false
?>

整型(integer)

<?php
$decimal = 123;        // 十进制
$octal = 0123;         // 八进制
$hex = 0x1A;           // 十六进制
$binary = 0b1010;      // 二进制(PHP 5.4+)

// 整数范围
echo PHP_INT_MAX;      // 最大整数
echo PHP_INT_MIN;      // 最小整数
echo PHP_INT_SIZE;     // 整数字节数

// 整数溢出
$large = PHP_INT_MAX + 1;
var_dump($large);      // 自动转换为浮点数
?>

浮点型(float/double)

<?php
$float1 = 1.234;
$float2 = 1.2e3;       // 科学计数法:1200
$float3 = 7E-10;       // 0.0000000007

// 浮点数精度问题
var_dump(0.1 + 0.2 == 0.3); // false

// 正确的浮点数比较
function floatEqual($a, $b, $epsilon = 0.00001) {
    return abs($a - $b) < $epsilon;
}

var_dump(floatEqual(0.1 + 0.2, 0.3)); // true
?>

字符串(string)

<?php
// 单引号字符串
$single = 'Hello World';
$single2 = 'He said: \'Hello\'';

// 双引号字符串
$name = "张三";
$double = "Hello, $name";
$double2 = "Hello, {$name}";

// Heredoc语法
$heredoc = <<<EOT
这是一个多行字符串
可以包含变量:$name
可以包含特殊字符
EOT;

// Nowdoc语法(PHP 5.3+)
$nowdoc = <<<'EOT'
这是一个多行字符串
不解析变量:$name
EOT;

echo $heredoc;
echo $nowdoc;
?>

2.4.2 复合类型

数组(array)

<?php
// 索引数组
$fruits = ["苹果", "香蕉", "橙子"];
$numbers = array(1, 2, 3, 4, 5);

// 关联数组
$person = [
    "name" => "张三",
    "age" => 25,
    "city" => "北京"
];

// 多维数组
$matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

// 访问数组元素
echo $fruits[0];        // 苹果
echo $person["name"];   // 张三
echo $matrix[1][2];     // 6
?>

对象(object)

<?php
class Person {
    public $name;
    public $age;
    
    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
    
    public function introduce() {
        return "我是{$this->name},今年{$this->age}岁";
    }
}

$person = new Person("张三", 25);
echo $person->introduce();
?>

2.4.3 特殊类型

NULL类型

<?php
$null1 = null;
$null2 = NULL;
$null3; // 未初始化的变量

// 检查NULL
var_dump(is_null($null1));     // true
var_dump($null1 === null);     // true
var_dump(isset($null1));       // false
var_dump(empty($null1));       // true

// unset()会将变量设为NULL
$var = "Hello";
unset($var);
var_dump($var); // NULL
?>

资源类型(resource)

<?php
// 文件资源
$file = fopen("test.txt", "r");
var_dump($file);           // resource
var_dump(is_resource($file)); // true
fclose($file);

// 数据库连接资源
$connection = mysqli_connect("localhost", "user", "pass", "db");
var_dump(is_resource($connection));
mysqli_close($connection);
?>

2.4.4 类型检查和转换

类型检查函数

<?php
$var = 123;

// 类型检查
var_dump(is_int($var));      // true
var_dump(is_string($var));   // false
var_dump(is_bool($var));     // false
var_dump(is_array($var));    // false
var_dump(is_object($var));   // false
var_dump(is_null($var));     // false
var_dump(is_numeric($var));  // true
var_dump(is_scalar($var));   // true

// 获取类型
echo gettype($var);          // integer
echo get_class($object);     // 获取对象类名
?>

类型转换

<?php
$str = "123";

// 强制类型转换
$int = (int) $str;           // 123
$float = (float) $str;       // 123.0
$bool = (bool) $str;         // true
$array = (array) $str;       // ["123"]

// 使用函数转换
$int2 = intval($str);        // 123
$float2 = floatval($str);    // 123.0
$bool2 = boolval($str);      // true

// 自动类型转换
$result = "10" + 5;          // 15 (字符串转为数字)
$concat = 10 . 5;            // "105" (数字转为字符串)
?>

2.5 运算符

2.5.1 算术运算符

<?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 (负号)
echo ++$a;       // 11 (前置递增)
echo $a++;       // 11 (后置递增,返回原值)
echo --$a;       // 11 (前置递减)
echo $a--;       // 11 (后置递减,返回原值)
?>

2.5.2 赋值运算符

<?php
$a = 10;         // 基本赋值

$a += 5;         // $a = $a + 5;  结果:15
$a -= 3;         // $a = $a - 3;  结果:12
$a *= 2;         // $a = $a * 2;  结果:24
$a /= 4;         // $a = $a / 4;  结果:6
$a %= 5;         // $a = $a % 5;  结果:1
$a **= 3;        // $a = $a ** 3; 结果:1

// 字符串连接赋值
$str = "Hello";
$str .= " World"; // $str = $str . " World"; 结果:"Hello World"

// 引用赋值
$b = &$a;        // $b是$a的引用
?>

2.5.3 比较运算符

<?php
$a = 5;
$b = "5";
$c = 10;

// 相等比较
var_dump($a == $b);   // true  (值相等)
var_dump($a === $b);  // false (值和类型都相等)
var_dump($a != $c);   // true  (不等于)
var_dump($a !== $b);  // true  (值或类型不等)
var_dump($a <> $c);   // true  (不等于,同!=)

// 大小比较
var_dump($a < $c);    // true
var_dump($a > $c);    // false
var_dump($a <= $b);   // true
var_dump($a >= $b);   // true

// 太空船操作符(PHP 7+)
var_dump($a <=> $c);  // -1 (小于)
var_dump($c <=> $a);  // 1  (大于)
var_dump($a <=> $b);  // 0  (等于)

// NULL合并操作符(PHP 7+)
$username = $_GET['user'] ?? 'guest';
$config = $config ?? [];

// NULL合并赋值操作符(PHP 7.4+)
$config['debug'] ??= false;
?>

2.5.4 逻辑运算符

<?php
$a = true;
$b = false;
$c = true;

// 逻辑与
var_dump($a && $c);   // true
var_dump($a and $c);  // true (优先级较低)

// 逻辑或
var_dump($a || $b);   // true
var_dump($a or $b);   // true (优先级较低)

// 逻辑非
var_dump(!$a);        // false
var_dump(!$b);        // true

// 逻辑异或
var_dump($a xor $c);  // false (两个都为true)
var_dump($a xor $b);  // true  (一个true,一个false)

// 短路求值
$result = $a && someFunction(); // 如果$a为false,不会执行someFunction()
$result = $b || someFunction(); // 如果$b为true,不会执行someFunction()
?>

2.5.5 位运算符

<?php
$a = 12;  // 二进制:1100
$b = 10;  // 二进制:1010

echo $a & $b;   // 8  (1000) 按位与
echo $a | $b;   // 14 (1110) 按位或
echo $a ^ $b;   // 6  (0110) 按位异或
echo ~$a;       // -13       按位取反
echo $a << 2;   // 48 (110000) 左移
echo $a >> 2;   // 3  (11)     右移
?>

2.5.6 字符串运算符

<?php
$first = "Hello";
$second = "World";

// 字符串连接
$result = $first . " " . $second; // "Hello World"

// 连接赋值
$first .= " PHP"; // "Hello PHP"

// 字符串比较
var_dump("apple" < "banana");  // true (字典序)
var_dump("10" < "9");          // true (字符串比较)
var_dump(10 < 9);              // false (数值比较)
?>

2.5.7 数组运算符

<?php
$a = ["a" => "apple", "b" => "banana"];
$b = ["a" => "apricot", "c" => "cherry"];

// 数组合并
$union = $a + $b;
print_r($union);
// 结果:["a" => "apple", "b" => "banana", "c" => "cherry"]

// 数组比较
var_dump($a == $b);   // false (值不同)
var_dump($a === $b);  // false (值和类型不同)
var_dump($a != $b);   // true
var_dump($a !== $b);  // true
?>

2.5.8 运算符优先级

<?php
// 优先级从高到低
echo 2 + 3 * 4;        // 14 (先乘后加)
echo (2 + 3) * 4;      // 20 (括号改变优先级)

echo true || false && false; // true (&&优先级高于||)
echo (true || false) && false; // false

// 建议使用括号明确优先级
$result = ($a > $b) && ($c < $d) || ($e == $f);
?>

2.6 注释

2.6.1 注释类型

<?php
// 单行注释
echo "Hello"; // 行尾注释

# Shell风格注释
echo "World";

/*
多行注释
可以跨越多行
*/

/**
 * 文档注释(PHPDoc)
 * 用于生成API文档
 * @param string $name 用户名
 * @return string 问候语
 */
function greet($name) {
    return "Hello, $name";
}
?>

2.6.2 PHPDoc注释

<?php
/**
 * 用户类
 * 
 * 这个类用于管理用户信息
 * 
 * @package App\Models
 * @author 张三 <zhangsan@example.com>
 * @version 1.0.0
 * @since 2024-01-01
 */
class User
{
    /**
     * 用户名
     * 
     * @var string
     */
    private $username;
    
    /**
     * 用户年龄
     * 
     * @var int
     */
    private $age;
    
    /**
     * 构造函数
     * 
     * @param string $username 用户名
     * @param int $age 年龄
     * @throws InvalidArgumentException 当参数无效时
     */
    public function __construct($username, $age)
    {
        if (empty($username)) {
            throw new InvalidArgumentException('用户名不能为空');
        }
        
        $this->username = $username;
        $this->age = $age;
    }
    
    /**
     * 获取用户信息
     * 
     * @return array 包含用户信息的数组
     * @example
     * $user = new User('张三', 25);
     * $info = $user->getInfo();
     * // 返回:['username' => '张三', 'age' => 25]
     */
    public function getInfo()
    {
        return [
            'username' => $this->username,
            'age' => $this->age
        ];
    }
}
?>

2.6.3 常用PHPDoc标签

<?php
/**
 * @param type $param 参数描述
 * @return type 返回值描述
 * @throws ExceptionType 异常描述
 * @var type 变量类型
 * @see ClassName::method() 参考链接
 * @since version 版本信息
 * @deprecated version 废弃信息
 * @todo 待办事项
 * @example 示例代码
 * @link http://example.com 相关链接
 * @author 作者信息
 * @copyright 版权信息
 * @license 许可证信息
 * @package 包名
 * @subpackage 子包名
 * @version 版本号
 * @access public|private|protected 访问级别
 * @static 静态方法标记
 * @abstract 抽象方法标记
 * @final 最终方法标记
 * @ignore 忽略此项
 * @internal 内部使用
 * @override 重写方法
 * @inheritdoc 继承文档
 */
?>

2.7 输入输出

2.7.1 输出函数

<?php
// echo - 输出字符串
echo "Hello World";
echo "Hello", " ", "World"; // 可以输出多个参数

// print - 输出字符串(返回1)
print "Hello World";
$result = print "Hello"; // $result = 1

// printf - 格式化输出
printf("姓名:%s,年龄:%d岁", "张三", 25);
printf("价格:%.2f元", 19.99);

// sprintf - 格式化字符串(不输出)
$formatted = sprintf("用户ID:%05d", 123); // "用户ID:00123"

// var_dump - 输出变量信息
$data = ["name" => "张三", "age" => 25];
var_dump($data);

// print_r - 输出变量信息(更易读)
print_r($data);

// var_export - 输出PHP代码形式
var_export($data);
?>

2.7.2 输入函数

<?php
// 命令行输入
echo "请输入您的姓名:";
$name = trim(fgets(STDIN));
echo "您好,$name!";

// 从文件读取
$content = file_get_contents('input.txt');
echo $content;

// 逐行读取文件
$handle = fopen('input.txt', 'r');
while (($line = fgets($handle)) !== false) {
    echo $line;
}
fclose($handle);

// Web输入(表单数据)
$username = $_POST['username'] ?? '';
$email = $_GET['email'] ?? '';
$file = $_FILES['upload'] ?? null;
?>

2.7.3 格式化输出

<?php
$name = "张三";
$age = 25;
$price = 19.99;

// 字符串格式化
printf("姓名:%s\n", $name);           // 字符串
printf("年龄:%d岁\n", $age);          // 整数
printf("价格:%.2f元\n", $price);      // 浮点数(2位小数)
printf("十六进制:%x\n", 255);         // 十六进制
printf("八进制:%o\n", 64);            // 八进制
printf("科学计数法:%e\n", 1234.5);    // 科学计数法

// 填充和对齐
printf("|%10s|\n", $name);           // 右对齐,宽度10
printf("|%-10s|\n", $name);          // 左对齐,宽度10
printf("|%010d|\n", $age);           // 用0填充,宽度10
printf("|%+d|\n", $age);             // 显示正负号

// 位置参数
printf("%2\$s今年%1\$d岁", $age, $name); // "张三今年25岁"
?>

2.8 错误处理基础

2.8.1 错误类型

<?php
// 语法错误(Parse Error)
// echo "Hello World" // 缺少分号

// 致命错误(Fatal Error)
// call_undefined_function(); // 调用未定义函数

// 警告(Warning)
include 'nonexistent.php'; // 包含不存在的文件

// 注意(Notice)
echo $undefined_variable; // 使用未定义变量

// 用户错误
trigger_error("自定义错误", E_USER_ERROR);
trigger_error("自定义警告", E_USER_WARNING);
trigger_error("自定义注意", E_USER_NOTICE);
?>

2.8.2 错误报告设置

<?php
// 设置错误报告级别
error_reporting(E_ALL);                    // 报告所有错误
error_reporting(E_ERROR | E_WARNING);      // 只报告错误和警告
error_reporting(0);                        // 不报告任何错误

// 显示错误
ini_set('display_errors', 1);              // 显示错误
ini_set('display_startup_errors', 1);      // 显示启动错误

// 记录错误日志
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');

// 自定义错误处理函数
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    echo "错误 [$errno]: $errstr 在 $errfile 第 $errline 行\n";
    return true; // 阻止PHP默认错误处理
}

set_error_handler('customErrorHandler');
?>

2.9 代码风格和最佳实践

2.9.1 PSR编码标准

<?php

namespace App\Controllers;

use App\Models\User;
use Exception;

/**
 * 用户控制器
 */
class UserController
{
    /**
     * 用户模型
     *
     * @var User
     */
    private $userModel;

    /**
     * 构造函数
     *
     * @param User $userModel
     */
    public function __construct(User $userModel)
    {
        $this->userModel = $userModel;
    }

    /**
     * 获取用户列表
     *
     * @param int $page 页码
     * @param int $limit 每页数量
     * @return array
     * @throws Exception
     */
    public function getUsers(int $page = 1, int $limit = 10): array
    {
        if ($page < 1) {
            throw new Exception('页码必须大于0');
        }

        if ($limit < 1 || $limit > 100) {
            throw new Exception('每页数量必须在1-100之间');
        }

        $offset = ($page - 1) * $limit;
        
        return $this->userModel->getUsers($offset, $limit);
    }
}

2.9.2 命名约定

<?php
// 类名:大驼峰命名法(PascalCase)
class UserController {}
class DatabaseConnection {}

// 方法名和变量名:小驼峰命名法(camelCase)
public function getUserById($userId) {}
$userName = "张三";
$isLoggedIn = true;

// 常量:全大写,下划线分隔
const MAX_LOGIN_ATTEMPTS = 3;
define('DATABASE_HOST', 'localhost');

// 私有属性:下划线前缀(可选)
private $_privateProperty;
protected $_protectedProperty;

// 文件名:小写,下划线或连字符分隔
// user_controller.php 或 user-controller.php
?>

2.9.3 代码组织

<?php

// 1. 开始标签
// 2. 文件级文档注释
/**
 * 用户管理相关功能
 *
 * @package App\Controllers
 * @author 张三 <zhangsan@example.com>
 */

// 3. 命名空间声明
namespace App\Controllers;

// 4. use声明
use App\Models\User;
use App\Services\EmailService;
use Exception;
use InvalidArgumentException;

// 5. 类声明
class UserController
{
    // 6. 常量
    const DEFAULT_PAGE_SIZE = 20;
    
    // 7. 属性
    private $userModel;
    private $emailService;
    
    // 8. 构造函数
    public function __construct(User $userModel, EmailService $emailService)
    {
        $this->userModel = $userModel;
        $this->emailService = $emailService;
    }
    
    // 9. 公共方法
    public function createUser(array $userData): User
    {
        // 方法实现
    }
    
    // 10. 受保护方法
    protected function validateUserData(array $userData): bool
    {
        // 方法实现
    }
    
    // 11. 私有方法
    private function sendWelcomeEmail(User $user): void
    {
        // 方法实现
    }
}

// 12. 结束标签(可选,纯PHP文件建议省略)

2.10 小结

本章详细介绍了PHP的基本语法:

  1. 语法基础:PHP标记、语句分隔符、大小写敏感性
  2. 变量:声明、命名规则、作用域、引用变量
  3. 常量:定义方法、预定义常量、类常量
  4. 数据类型:标量类型、复合类型、特殊类型、类型转换
  5. 运算符:算术、赋值、比较、逻辑、位运算等
  6. 注释:单行、多行、PHPDoc文档注释
  7. 输入输出:各种输出函数和格式化方法
  8. 错误处理:错误类型和基本处理方法
  9. 代码风格:PSR标准和最佳实践

2.11 实践练习

  1. 变量练习

    • 创建不同类型的变量并输出
    • 练习变量作用域和引用
    • 使用可变变量
  2. 运算符练习

    • 编写计算器程序
    • 练习各种比较和逻辑运算
    • 使用位运算符进行权限管理
  3. 类型转换练习

    • 练习显式和隐式类型转换
    • 处理用户输入的数据验证
    • 实现安全的类型转换函数
  4. 格式化输出练习

    • 创建格式化的报表输出
    • 练习printf的各种格式符
    • 实现多语言格式化

2.12 扩展阅读

  1. PHP数据类型官方文档
  2. PSR-1编码标准
  3. PSR-12编码风格
  4. PHPDoc标准
  5. PHP运算符优先级

下一章预告:在下一章中,我们将学习PHP的控制结构,包括条件语句、循环语句和跳转语句。