文件加载
[toc]
- 文件加载: 可简单的理解为将外部文件内容复制到当前文档中
- 根据被加载文件的特征和重要性,可分为: “条件加载” 和 “强制加载” 二种方式
1. 条件加载
加载外部文件,如果失败报警告级(Warning)错误,不会中断程序
序号 |
语法 |
描述 |
1 |
include |
条件加载 |
2 |
include_once |
去重(chong )条件加载 |
2. 强制加载
加载外部文件,如果失败报致命级(Fatal error)错误,并中断程序
序号 |
语法 |
描述 |
1 |
require |
强制加载 |
2 |
require_once |
去重强制加载 |
类与对象
1. 概念
序号 |
名称 |
描述 |
关键字 |
1 |
类class |
对象的模板 |
class |
2 |
对象instance |
类的实例 |
new |
- 类与对象界限并不清晰,在不影响理解前提下,常用类代表实例来引用类成员
- 对象与类的某一个实例绑定, 所以对象与实例可视为同义词,互换并不影响
2. 类中成员
2.1 按功能分类
序号 |
名称 |
描述 |
关键字 |
1 |
类属性property |
类中变量 |
无 |
2 |
类方法method |
类中函数 |
function |
3 |
类常量method |
类中常量 |
const |
2.2 按访问权限分类
序号 |
名称 |
关键字 |
类外部 |
类内部 |
类继承上下文 |
描述 |
1 |
公开成员 |
public |
允许 |
允许 |
允许 |
默认 |
2 |
受保护成员 |
protected |
禁止 |
允许 |
允许 |
封装 |
3 |
私有成员 |
private |
禁止 |
允许 |
禁止 |
封装 |
2.3 按调用主体分类
序号 |
名称 |
关键字 |
调用主体 |
1 |
非静态成员 |
默认 |
类实例调用 |
2 |
静态成员 |
static |
类调用 |
2.4 按是否有具体实现分类
序号 |
名称 |
关键字 |
具体实现 |
1 |
非抽象成员 |
默认 |
有 |
2 |
抽象成员 |
abstract |
无 |
- 类中只要有一个抽象方法,该类必须声明为抽象类
abstract class
- 严格来说未初始化的属性也应该算是抽象成员, 即: 抽象属性
- 思考: 有抽象属性的类,为什么不需要定义为抽象类呢?
- 普通属性通常会在类实例化通过构造方法进行初始化
- 静态属性由类调用而没有实例化的机会,所以定义时通常已经初始化
2.5 按方法是否可重写
序号 |
类型 |
关键字 |
描述 |
1 |
可重写方法 |
默认 |
可由子类重写 |
2 |
最终方法 |
final |
不允许子类重写 |
只有 “类和方法” 可声明为final
, 属性不可以
3. 类的分类
序号 |
类型 |
关键字 |
可实例化 |
可继承 |
可组合 |
1 |
常规类 |
class |
允许 |
允许 |
允许 |
2 |
最终类 |
final |
允许 |
禁止 |
允许 |
3 |
抽象类 |
abstract |
禁止 |
允许 |
允许 |
4 |
特征类 |
trait |
禁止 |
禁止 |
允许 |
5 |
接口类 |
interface |
禁止 |
允许 |
允许 |
6 |
匿名类 |
new class{} |
禁止 |
允许 |
允许 |
部分示例
<?php
// 加载用户的自定义模板
include 'custom.php';
include "custom.php";
include ("custom.php");
$file = "custom.php";
include $file;
include "$file";
$file = "custom";
include $file . '.php';
if (@!include 'custom1.php') include 'default.php';
$file = 'custom.php';
if (file_exists($file) && is_file($file))
include "{$file}";
else
include 'default.php';
echo '如果看到我, 说明程序没有因文件加载失败而终止';
// include_once(): 仅允许加载一次
// 全局成员:函数, 常量, 类, 接口
// 不支持函数重载, 因此在同一个程序中不允许出现同名函数
// include 'common.php';
// include 'common.php';
include_once 'common.php';
// include_once(): 加载前会检查该文件是否已经加载过了, 去重检查
include_once 'common.php';
echo fetch();
// 1. require: 强制加载
// 如果加载失败, 终止当前脚本, 与include不一样
require 'config.php';
// 2. 强制去重加载
require_once 'common.php';
require_once 'common.php';
echo '如果看到我, 说明程序没有因文件加载失败而终止';
// 文件加载与作用域
// 只要在同一个作用域内, 文件外部变量可以在被加载的文件中使用
// 当前是全局作用域
$sitename = 'php中文网';
// include 'file1.php';
echo '站点名称: ' , $sitename ?? '默认站点';
$email = 'peter@php.cn';
echo '<hr>';
// 函数作用域
function test1()
{
include 'file1.php';
echo '<br>';
echo $email;
}
test1();
echo '<hr>';
function test2()
{
include 'file2.php';
}
test2();
echo $goods ?? '默认商品';
// 小案例: 数据查询
// 连接数据库
require 'connect.php';
// 查询测试
$sql = 'SELECT `id`,`name`,`email` FROM `users` LIMIT 3';
$res = $pdo->query($sql)->fetchAll(PDO::FETCH_NUM);
// 解构遍历查询结果
foreach ($res as list($id, $name, $email)) {
printf('%s : %s ( %s ) <br>', $id, $name, $email);
}
// 变量: 数据复用
$name = '电脑';
$price = 8899;
// 函数: 代码复用
function get($name, $price)
{
return "$name : $price 元";
}
// echo get('电脑', 7899);
echo get($name, $price);
// 变量 + 函数 = 对象
// 对象也是实现"代码复用"的手段
// 要使用对象, 就得先创建一个模板,根据这个模板,不断的创建多个对象出来,实现复用
// 这个模板就叫: "类"
// $object = {
// // 变量: 数据复用
// $name = '电脑';
// $price = 8899;
// // 函数: 代码复用
// function get($name, $price)
// {
// return "$name : $price 元";
// }
// }
//类的声明与实例化
//1. 类的声明: class
class Goods
{
}
// 2. 类的实例化:创建对象的过程, new
$goods = new Goods();
// 类的实例, 对象, 在不会引起误会的场景下, 实例与对象是同义词
var_dump($goods instanceof Goods);
// 如果不知道类名,get_class()
echo get_class($goods);
// 动态类, 首字母大写
$class = ucfirst('goods');
// $class = 'goods';
die($class);
$obj = new $class();
var_dump($obj instanceof Goods);
// 类成员: 类属性, 类方法, 类常量
class User
{
// 类属性: 类中变量
// 类中成员的作用域: 访问限制
// 类属性就是有访问限制的变量
// 语法: 访问限制符 $变量标识符;
// 1. 常规属性: 非静态属性/动态属性
public $name = '胡八一';
public $age = 40;
public $options = [1,2,3];
// nowdow
public $output = <<< 'RES'
<h3>中国必胜 \n\r</h3>
RES;
// heredoc :双引号
public $output1 = <<< EOT
<h3>中国\n\r必胜 </h3>
EOT;
// 非法属性值
// 不能用变量
// public $age = $var;
// 不能用类属性/类方法
// public $user = $this->name;
// 不能用表达式
// public $total = $price * 10;
// 不能使用函数调用
// public $creat = time();
// 2. 静态属性
// 如果一个属性的值,对所有实例来说是一样的, 用类访问更方便,此时可以声明为静态的
public static $nationality = '中国/CHINA';
// php程序的运行简单的可以分为二个阶段: 编译, 执行
// 3. 抽象属性: 没有被初始化, 默认值就null
// public $salary;
public $salary = null;
}
$user = new User;
$user->name = '王胖子';
// -> : 对象运算符/对象成员访问符
echo "姓名: {$user->name}, 年龄: {$user->age}<br>";
echo $user->output . '<br>';
echo $user->output1 . '<br>';
// 访问静态属性: 使用范围解析符, 双冒号::
User::$nationality = '美国/USA';
echo User::$nationality;
var_dump(is_null($user->salary));
// 类成员: 类属性, 类方法, 类常量
class User
{
// 类属性: 类中变量
// 类中成员的作用域: 访问限制
// 类属性就是有访问限制的变量
// 语法: 访问限制符 $变量标识符;
// 1. 常规属性: 非静态属性/动态属性
public $name = '胡八一';
public $age = 40;
public $options = [1,2,3];
// nowdow
public $output = <<< 'RES'
<h3>中国必胜 \n\r</h3>
RES;
// heredoc :双引号
public $output1 = <<< EOT
<h3>中国\n\r必胜 </h3>
EOT;
// 非法属性值
// 不能用变量
// public $age = $var;
// 不能用类属性/类方法
// public $user = $this->name;
// 不能用表达式
// public $total = $price * 10;
// 不能使用函数调用
// public $creat = time();
// 2. 静态属性
// 如果一个属性的值,对所有实例来说是一样的, 用类访问更方便,此时可以声明为静态的
public static $nationality = '中国/CHINA';
// php程序的运行简单的可以分为二个阶段: 编译, 执行
// 3. 抽象属性: 没有被初始化, 默认值就null
// public $salary;
public $salary = null;
}
$user = new User;
$user->name = '王胖子';
// -> : 对象运算符/对象成员访问符
echo "姓名: {$user->name}, 年龄: {$user->age}<br>";
echo $user->output . '<br>';
echo $user->output1 . '<br>';
// 访问静态属性: 使用范围解析符, 双冒号::
User::$nationality = '美国/USA';
echo User::$nationality;
var_dump(is_null($user->salary));
// 类成员之方法
// 工作类
class User
{
// 类方法:类中函数
public $name = '胡八一';
public $age = 40;
public static $nationality = '中国/CHINA';
// 1. 访问类属性: 方法1
public function write1()
{
// 1. 创建类实例
$user = new User;
// 2. 访问类中的属性
return "姓名: {$user->name} , 年龄: {$user->age}";
}
// 2. 访问类属性: 方法2
public function write2()
{
// self: 引用当前, $this: 引用当前实例
// 1. 创建类实例, self 与当前的类绑定
// $this不允许用户设置, 由php系统进行维护和赋值
// $this = new self();
// 2. 访问类中的属性, $this 与当前类的实例绑定
return "姓名: {$this->name} , 年龄: {$this->age}";
}
// 3. 类方法中的变量与类属性的区别
public function write3()
{
// 方法中的: 私有变量
$salary = 9000;
// 类属性
return "姓名: {$this->name} , 年龄: {$this->age}, 工资: $salary";
// 什么时候用类属性, 什么时候用方法的私有变量?
// 1. 类属性: 如果某个变量需要在多个方法中都被使用(共享), 那么就该把它定义为属性
// 2. 方法变量: 如果某个变量只有一个特定方法中使用,那么应该把它定义为这个方法的私有变量
}
// 4. 类方法中访问外部成员
public function write4()
{
// 访问外部函数: 函数的作用域默认是全局, 函数是全局成员
$str = hello();
// 访问外部变量, 可以用global
global $username;
return $str . $username;
}
// 5. 改进类方法中访问外部成员
public function write5(string $name, Closure $closure)
{
return $closure() . $name;
}
// 6. 静态方法: 直接用类调用, 被所有类实例所共享
public static function write6()
{
// 静态方法不允许使用$this
// return "姓名: {$this->name} , 年龄: {$this->age}, 工资: $salary";
// 静态方法中只能访问静态成员: 静态属性, 静态方法
return '国籍是: ' . self::$nationality;
}
// 能不能在一个非静态方法中访问静态成员呢?
public function write7()
{
// 可以访问, 但不推荐, 在以后的版本中很可能被禁止
return '国籍是: ' . self::$nationality;
}
}
// 客户端代码
$user = new User;
echo $user->write1() . '<br>';
echo $user->write2() . '<br>';
echo $user->write3() . '<br>';
// 类外部函数
function hello()
{
return 'Hello ';
}
// 类外部变量
$username = '大金牙';
echo $user->write4() . '<br>';
$hello = function ()
{
return 'Hello ';
};
echo '<hr>';
echo $user->write5($username, $hello) . '<br>';
echo $user->write6() . '<br>';
echo $user->write7() . '<br>';
// 类成员的访问控制: 作用域
class User
{
// public: 公开成员,默认值, 类外部, 类内部, 以及类的子类中(类的继承上下文环境中)
// protected: 受保护的成员, 类外部禁止访问, 但是类的内部以及它的继承上下文中可以访问
// private: 私有成员, 除了当前类可以访问, 类的外部以及类的继承上下文中都禁止访问
// 继承上下文环境: 当前类, 以及它的扩展类/子类,构成的一个具有层级结构的类家庭
protected $name = '胡八一';
protected $age = 40;
// private: 是当前类的私有成员, 是完成对象封装的主要工具
private $salary = 9999;
// 类中方法可以访问类中所有成员, 不受访问控制的限制
public function write()
{
return "姓名: {$this->name} , 年龄: {$this->age}, 工资: $this->salary";
}
}
// 子类
class Rob extends User
{
public function write()
{
return "姓名: {$this->name} , 年龄: {$this->age}, 工资: $this->salary";
}
}
// 客户端
$user = new User();
// echo "姓名: {$user->name} , 年龄: {$user->age}, 工资: $user->salary";
echo $user->write() , '<br>';
$rob = new Rob;
echo $rob->write();
// OOP: 封装, 继承, 多态
// 封装:public, proteced, private
// 继承: extends
// 多态: 方法的重写是实现方法级的多态, 面向接口开发, 实现的是对象级的多态
// 类的继承
// 父类: 基类
class User
{
protected $name = '胡八一';
protected $age = 40;
private $salary = 9999;
protected static $nationality = '中国/CHINA';
public function write()
{
return "姓名: {$this->name} , 年龄: {$this->age}";
}
}
// 类的继承,也叫类的扩展
// 子类: 扩展类
class Rob extends User
{
// 二类成员: 子类有权访问的父类成员类型, public, protected
// 三种操作: 子类对父类的三种操作: 继承, 重写, 扩展
// 1. 继承: 父类的二类成员自动成为子类的成员
// 2. 重写: 覆写与父类/基类同名的成员(属性, 方法)
// 3. 扩展: 子类添加自身的方法来增加/扩展父类的功能
// 1. 重写父类成员
// 属性重写
protected $age = 50;
// 方法重写, 方法级的多态
public function write()
{
// 在子类中可以引用父类成员
// parent::write()
return parent::write() . ', 是一个盗墓人7777~~';
}
// 2. 扩展
// 属性扩展
protected $profession = '摸金校尉';
// 方法扩展
public function write1()
{
return parent::write() . ", 职业: {$this->profession}";
}
}
// 客户端
$user = new User;
echo $user->write() . '<br>';
$rob = new Rob;
echo $rob->write() . '<br>';
echo $rob->write1() . '<br>';
// 最终方法和最终类, final
final class Dad
{
public $a = 100;
public function test1()
{
return __METHOD__;
}
public function test2()
{
return __METHOD__;
}
}
class Son extends Dad
{
public function test1()
{
return __CLASS__ .' 类中的重写方法 : ' . __METHOD__;
}
public function test2()
{
return __CLASS__ .' 类中的重写方法 : ' . __METHOD__;
}
}
// 客户端
$son = new Son;
echo $son->test1(), '<br>';
echo $son->test2(), '<br>';
// 抽象类: 部分分离了" 设计(抽象类中完成)与实现(工作类中完成)"
// 设计类
abstract class User
{
protected $name = '胡八一';
protected $age = 40;
// 具体方法: 有方法体: {...},
protected function write1()
{
return "姓名: {$this->name} , 年龄: {$this->age}";
}
// 抽象方法:没有方法体
// 只要一个类中有一个抽象方法, 那么这个类就是:抽象类
abstract protected function write2();
}
// 实现类/工作类: 是一个可以被实例化的普通类
// 工作类不一定是可以被实例化的普通类,也可是一个抽象类
// 抽象类也可以被继承, 抽象类也可以用在继承的上下文环境中
// 抽象类中允许有抽象成员, 但不是强制的,也可以没有
abstract class Rob extends User{
protected $profession = '摸金校尉';
// 必须将抽象类中的抽象方法实现
protected function write2() {
return parent::write1() . ", 职业: {$this->profession}";
}
}
// 最终工作类: 允许实例化
class Work extends Rob
{
public function write2()
{
return parent::write2();
}
}
// 客户端
// 抽象类不能被实例化
// new User;
// $rob = new Rob();
// echo $rob->write2();
$work = new Work();
echo $work->write2();
// 接口: 完全分离了"设计与实现"
// 关键字: interface
// 使用与类相似的语法: 抽象方法, 常量, 构造方法(魔术方法的一种)
// 默认访问控制必须是public
// 接口允许多继承, 从而间接实现了PHP的多继承
// implements (英婆慢吃)
// 接口使用场景1: 单接口
interface iUser
{
// 接口常量
const NATION = '中国';
// 接口方法
public static function write();
// 构造方法(略)
}
// 工作类实现接口
class User implements iUser
{
protected static $name = '胡八一';
// 接口中的抽象方法,必须在工作类实现
public static function write()
{
return self::$name . ' 的国籍是: ' . iUser::NATION;
}
}
// 客户端
// 接口常量的访问与类常量一样
// echo iUser::NATION;
echo User::write();
课程学习小结
正如老师上次作业评语所说的:编程, 看是学不会的, 必须动动手。利用五一假期的时间,对文件加载及类与对象基础相关内容进行了较为全面地复习,包括回看视频及讲义代码,对之前感觉比较生疏的内容加深了理解,虽然实践时时间紧,借助了老师的课堂案例,但还是尝试着逐个函数去实现一下,对自己动手少的缺点有所改进。完成相关练习后,特别是上课时感觉没怎么听懂的地方,又查询了手册和相关资料,搞清楚了来龙去脉,并对相关知识的脉络进行了思维导图式的梳理,感觉学有所获,值得进一步坚持。回顾四月一号以来的学习经历,我觉得自己每天都有进步,哪怕比较微小,也是值得肯定的,继续加油!