PHP 起步:脚本、严格类型、数组与对象
安装、运行与语法检查
PHP不只是嵌入HTML的模板语言,也能写CLI脚本。CLI、FPM和Web服务器是不同运行入口,本课程先用CLI完成可测试应用,不要求Apache、数据库或Composer。核对2026-10-17:Windows官方PHP8.5.11 x64 NTS;Linux使用Ubuntu26.04官方安全更新包8.5.4-0ubuntu1.3,发行版补丁与上游补丁号不能简单比较为同一版本。本项目要求64位PHP8.3以上,实际以两种运行版本记录。
Windows从 PHP下载选x64 NTS ZIP,按页面要求准备VC运行库,解压后PowerShell调用& 'D:/tools/php/php.exe' -v。Linux按官方发行版说明安装php-cli;不想改系统可解压发行包但需同时提供依赖动态库。不要把修改Web php.ini当作CLI配置,先执行:
php -v
php --ini
php -mhello.php完整内容,源文件以<?php开始,纯PHP文件通常不写结束标签,避免尾部空白意外输出:
<?php
declare(strict_types=1);
echo "Hello, PHP!\n";php -l hello.php只检查语法;php hello.php真正执行并输出Hello, PHP!。相对路径相对启动工作目录,require依赖应使用__DIR__锚定当前文件目录。CLI参数在
变量、分支、函数和闭包
PHP变量以$开头,字符串.拼接;双引号支持变量插值,单引号大部分内容按字面。0、空字符串、字符串"0"等有布尔转换,外部输入不要依靠宽松真假判断。判断精确值通常用===,它同时比较类型和值。
下面完整脚本可直接运行:
<?php
declare(strict_types=1);
function total(array $values, int $minimum = 0): int {
$sum = 0;
foreach ($values as $value) {
if (!is_int($value)) { throw new InvalidArgumentException('integer required'); }
if ($value >= $minimum) { $sum += $value; }
}
return $sum;
}
$scores = [80, 90, 100];
echo total($scores, 90), "\n";
$factor = 2;
$double = fn(int $n): int => $n * $factor;
echo $double(3), "\n";输出190、6。箭头函数按值捕获使用的外部变量,普通闭包可显式use ($factor)或use (&$factor);后者共享变量槽位,需要额外注意生存期和后续修改。函数按职责拆,不因PHP动态类型就省略输入合同。
严格类型、联合类型与外部输入
PHP的strict_types取决于调用方,也就是发起函数调用的调用文件;类型不符合该严格调用契约时可能抛TypeError,不是被调用函数所在文件一次设置就让所有外部调用自动严格。
int/string/bool等声明可用于参数、返回与属性;?string允许null,联合如int|string表示两种合法类型。strict_types=1的标量调用检查主要由调用文件决定,不是给被调用函数打上“从此所有调用都严格”的全局标志;内置函数和特定转换还有自己的规则。测试文件也启用严格模式,才会验证parseRow(123,1)抛TypeError。
PHP没有把array声明自动变成array<string,int>的运行时泛型校验;元素仍需逐项检查。文档注解可帮助工具,但不执行验证。(int)'12oops'不是严格的业务解析,强制转换可能接受前缀或丢信息;本项目先正则限制完整十进制格式再转换。金额使用整数且设上限,不能把字符串加法自动转换当输入安全。
数组、键、复制和引用
PHP array是有序映射,可同时承担列表与字典,但两种业务语义要分清。整数字符串键如'1'会转换为整数1,'01'则保留字符串;同一键后写覆盖前值。$copy = $array通常具有值语义并以写时复制实现,不等于每次立刻递归深拷贝;数组内对象引用仍可共享。&建立引用别名,常见陷阱是foreach ($xs as &$value)结束后
ksort按键排序,选择SORT_STRING明确比较方式;排序函数可能保留键或重排键,先看API约定。isset($x['key'])对不存在和null都返回false,需要区分可用array_key_exists。外部JSON默认解析形式也影响数组/对象结构,不能凭一个array类型声明验证整个文档。可运行数组键与引用实验在运行机制。
类、接口、命名空间与readonly
class表达状态和行为,interface表达调用契约,trait复用方法实现;trait不是独立类型实例。项目Entry使用final readonly class与构造器属性提升,让name与amount构造后不重赋;readonly不自动冻结属性引用对象的内部状态,也不替代构造时验证。对象默认赋值复制句柄,用clone复制时同样需要理解嵌套对象是否共享。
namespace组织名称,require/include执行载入文件;require失败是不可继续的依赖错误,require_once避免重复载入。PSR-4自动加载通常由Composer生成,Composer是包与自动加载工具,不是PHP解释器。没有依赖的本项目使用require DIR,不为演示而虚构外部包。
练习与参考解法
练习:比较'0'、0、false的==与===;把PHP调用文件的strict_types去掉后传数字字符串;构造'1'/1/'01'三个数组键;解释为什么readonly属性保存的可变对象仍能改内部字段。
参考解法
宽松比较先转换,严格比较保留类型;外部数据应按明确合同解析。严格模式是调用边界规则,不能假定被调函数声明替代所有校验。'1'与1是同一键,'01'另一个。readonly约束属性绑定,不保证递归不可变;值对象需由不可变组件组成。完整lab.php有键与引用断言,不依赖运行时可关闭的assert。
继续阅读
- 开发实践
- 知识专题