初学 PHP 类的自动加载
一。几点要求#
在实际项目中,每个功能会被定义成一个类,并且每个类都会被放到单独的一个 PHP 文件中,在另外一个文件中想要使用某一个类,就需要引入存放该类的类文件.
类文件的定义有几个要求:
- 类文件名以
.class.php
结尾. - 类文件名要与其中的类名一致.
- 类文件以及类的命名使用 "大驼峰" 命名法.
- 类中方法与属性使用 "小驼峰" 命名法.
二。手动加载类#
./User.class.php
类文件.
<?php
class User {
private $name = "刘看山";
private $age = "4";
public function getInfo(){
return "我是{$this->name},我有{$this->age}岁了!";
}
}
./index.php
文件.
<?php
require_once "./User.class.php";
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
在上面这个例子中,./index.php
文件中的 require_once "./User.class.php";
这个语句相当于把 ./User.class.php
类文件中的代码赋值到了 ./index.php
文件中,但是当真正做项目的时候,类文件成百上千,不可能每一次都这样手动来加载.
三。自动加载类#
__autoload()
函数#
注意,该函数在 PHP 7.2.0 中被废弃了.
当在脚本中调用本脚本中不存在的类时,__autoload()
函数会被调用,有如下几种情况:
- new 一个对象时。例如
$obj = new User();
- 调用类中的静态属性或者静态方法时。例如
$result = User::showMessage()
- 继承父类时。例如
class Staff extends Person{};
- 实现接口时。这个还没学过.
在该函数中要做两件事情:
- 拼装一个类文件的真实物理路径.
- 类文件存在则包含之.
上文中的 ./User.class.php
类文件保持不变。修改 ./index.php
文件.
<?php
function __autoload($className) {
//构建类文件的真实路径
$filePath = "./$className.class.php";
//如果类文件存在,包含之
if (file_exists($filePath)) {
require_once "./$filePath";
}
}
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
spl_autoload_register()
函数#
使用该函数需要传入一个回调函数,这里结合了回调函数的知识点。上文中的 ./User.class.php
类文件保持不变。修改 ./index.php
文件。有三种写法,如下所示.
<?php
spl_autoload_register(function ($className) {
//构建类文件的真实路径
$filePath = "./$className.class.php";
//如果类文件存在,包含之
if (file_exists($filePath)) {
require_once "./$filePath";
}
});
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
或者写成
<?php
$myFunc = function ($className) {
//构建类文件的真实路径
$filePath = "./$className.class.php";
//如果类文件存在,包含之
if (file_exists($filePath)) {
require_once "./$filePath";
}
};//这里有个坑,要注意记得加上分号
spl_autoload_register($myFunc);
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
或者写成
<?php
function myFunc($className) {
//构建类文件的真实路径
$filePath = "./$className.class.php";
//如果类文件存在,包含之
if (file_exists($filePath)) {
require_once "./$filePath";
}
}
spl_autoload_register("myFunc");
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
相比较于 __autoload()
函数,spl_autoload_register()
函数的优势是可以注册多个回调函数,每个回调函数可以对应不同的加载规则。下面做个记录../User/User.class.php
文件.
<?php
class User {
private $name = "刘看山";
private $age = "4";
public function getInfo(){
return "我是{$this->name},我有{$this->age}岁了!";
}
}
./Student/Student.class.php
文件.
<?php
class Student {
private $name = "刘看火";
private $job = "打妖怪";
public function getInfo(){
return "我是{$this->name},我的工作是{$this->job}";
}
}
./Teacher/Teacher.class.php
文件.
<?php
class Teacher {
private $name = "刘看水";
private $school = "北京大学";
public function getInfo(){
return "我是{$this->name},我在{$this->school}任教";
}
}
./index.php
文件.
<?php
function myFunc1($className) {
$filePath = "./User/$className.class.php";
if (file_exists($filePath)) {
require_once "./$filePath";
}
}
function myFunc2($className) {
$filePath = "./Student/$className.class.php";
if (file_exists($filePath)) {
require_once "./$filePath";
}
}
function myFunc3($className) {
$filePath = "./Teacher/$className.class.php";
if (file_exists($filePath)) {
require_once "./$filePath";
}
}
spl_autoload_register("myFunc1");
spl_autoload_register("myFunc2");
spl_autoload_register("myFunc3");
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
$studentObj = new Student();
echo $studentObj->getInfo();//输出"我是刘看火,我的工作是打妖怪"
$teacherObj = new Teacher();
echo $teacherObj->getInfo();//输出"我是刘看水,我在北京大学任教"
上面这种写法很繁琐,优化一下../User/User.class.php
, ./Student/Student.class.php
, ./Teacher/Teacher.class.php
这三个文件保持不变。修改 ./index.php
文件.
<?php
spl_autoload_register(function ($className) {
$filePaths = [
"./User/$className.class.php",
"./Student/$className.class.php",
"./Teacher/$className.class.php",
];
foreach ($filePaths as $filePath){
if (file_exists($filePath)){
require_once "$filePath";
}
}
});
$userObj = new User();
echo $userObj->getInfo();//输出"我是刘看山,我有4岁了!"
$userObj = new Student();
echo $userObj->getInfo();//输出"我是刘看火,我的工作是打妖怪"
$userObj = new Teacher();
echo $userObj->getInfo();//输出"我是刘看水,我在北京大学任教"
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: