在實際專案中,每個功能會被定義成一個類,並且每個類都會被放到單獨的一個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 協議》,轉載必須註明作者和本文連結