初學PHP時,最早會面對的問題之一就是require與include差別何在?
require_once與include_once又是什麼?
弄懂這些問題之後,如果不使用framework,直接開發,便常出現類似這樣的code:

// whatever.php
// 這檔案需要用到幾個類別
require 'xxx_class.php';
require 'yyy_class.php';
require 'zzz_class.php';
// ...

然後在其他檔案會出現:

// another.php
// 這檔案需要用到幾個類別
require 'yyy_class.php';
require 'zzz_class.php';
// ...

這樣的結果,會產生至少兩個問題:
1. 許多檔案用到同樣幾個class,於是在不同地方都需要載入一次。
2. 當類別多了起來,會顯得很亂、忘記載入時還會出現error。

那麼,不如試試一種懶惰的作法?
寫一個php,負責載入所有類別:

// load_everything.php
require 'xxx_class.php';
require 'yyy_class.php';
require 'zzz_class.php';
require 'aaa_class.php';
require 'bbb_class.php';
require 'ccc_class.php';

然後在其他檔案都載入這支檔案即可:

require 'load_everything.php'

結果新問題又來了:當類別很多的時候,隨便一個web page都會載入一堆code,吃爆記憶體,怎麼辦呢?

__autoload

為了解決這個問題,PHP 5開始提供__autoload這種俗稱「magic method」的函式。
當你要使用的類別PHP找不到時,它會將類別名稱當成字串丟進這個函式,在PHP噴error投降之前,做最後的嘗試:

// autoload.php
function __autoload($classname) {
if ($classname === 'xxx.php'){
$filename = "./". $classname .".php";
include_once($filename);
} else if ($classname === 'yyy.php'){
$filename = "./other_library/". $classname .".php";
include_once($filename);
} else if ($classname === 'zzz.php'){
$filename = "./my_library/". $classname .".php";
include_once($filename);
}
// blah
}

也因為PHP這種「投降前最後一次嘗試」的行為,有時會讓沒注意到的人困惑「奇怪我的code怎麼跑得動?我根本沒有require啊..」,所以被稱為「magic method」。
如此一來,問題似乎解決了?
可惜還是有小缺點..,就是這個__autoload函式內容會變得很巨大。以上面的例子來說,一下會去根目錄找、一下會去other_library資料夾、一下會去my_library資料夾尋找。在整理檔案的時候,顯得有些混亂。

spl_autoload_register

於是PHP從5.1.2開始,多提供了一個函式。
可以多寫幾個autoload函式,然後註冊起來,效果跟直接使用__autoload相同。
現在可以針對不同用途的類別,分批autoload了。

spl_autoload_register('my_library_loader');
spl_autoload_register('other_library_loader');
spl_autoload_register('basic_loader'); function my_library_loader($classname) {
$filename = "./my_library/". $classname .".php";
include_once($filename);
}
function other_library_loader($classname) {
$filename = "./other_library/". $classname .".php";
include_once($filename);
}
function basic_loader($classname) {
$filename = "./". $classname .".php";
include_once($filename);
}

每個loader內容可以做很多變化。可以多寫判斷式讓它更智慧、可以進行字串處理…。
自動載入類別的問題終於解決了…。

但是光上面的code也有15行,而且在每個project一定都會寫類似的東西。有沒有辦法自動產生這15行呢?
我的願望很簡單,我告訴你,反正我有my_library資料夾跟other_library資料夾,你自己進去看到什麼類別就全部載入好不好…?
阿不對,全部載入剛又說效能不好,那你進去看到什麼就全部想辦法用spl_autoload_register記起來好不好…?
我懶得打15行了,我只想打這幾個字:

$please_autoload = array( 'my_library', 'other_library');
可不可以發明一個工具,去吃$please_autoload這個變數,然後自己想辦法載入一切啊…?

ㄟ等等,我連php程式碼都懶得打了,在web領域JSON格式更簡潔。允許我這樣打,好嗎?

{
"autoload": [
"my_library",
"other_library"
]
}

然後誰來個工具幫我產生一大串autoload相關的php程式碼吧…,可以嗎?

可以。
Composer登場
首先,裝好composer(本文不介紹如何安裝。)
再來,建立一個composer.json檔,裡面輸入這些:

{
"autoload": {
"classmap": [
"my_library",
"other_library"
]
}
}

比原本希望的多打了一些字,不過差不多。
再來,在terminal輸入

composer install
執行成功之後,你會看到一個vendor資料夾,內含一個autoload.php。
沒錯,跟你夢想的一樣。你只要載入這個檔案:

require 'vendor/autoload.php';
你需要的所有類別,都會在適當的時候、以適當的方式自動載入。
php再也不會噴error說你「類別尚未定義」了!
這vendor資料夾裡面的一切,都只是php code而已,並沒有特別神奇的地方。只要去看autoload.php的原始碼,就能知道composer到底寫了哪些php code給你。

ㄟ等等,我寫的類別都放在my_library裡面了,other_library都是網路上copy下來的現成類別。我想要用Google API的Client類別、Doctrine資料庫管理抽象層類別、還有guzzlehttp的發送request類別。
我連去下載這些檔案、然後丟進這個資料夾都懶得做了,我根本不想手動建立other_library這個資料夾。composer真那麼神…不如連下載都幫我自動下載?可以嗎?

可以。
查詢一下那幾個套件在「https://packagist.org/」的名稱、還有你需要的版本號。
把剛剛的composer.json改成這樣:

{
"require": {
"google/apiclient": "1.0.*@beta",
"guzzlehttp/guzzle": "~4.0",
"doctrine/dbal": "~2.4"
}, "autoload": {
"classmap": [
"my_library"
]
}
}

然後’composer install’指令除了自動載入你的類別之外、還會自動下載你需要的類別、然後自動載入它們。
一樣require ‘vendor/autoload.php’就可以了。composer實在是太棒了

php自动加载的更多相关文章

  1. BPM配置故事之案例3-参与者与数据自动加载

    这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...

  2. Composer概述及其自动加载探秘

    composer概述 一开始,最吸引我的当属 Composer 了,因为之前从没用过 Composer . Composer 是PHP中用来管理依赖关系的工具,你只需在自己的项目中声明所依赖的外部工具 ...

  3. 让Lua自己把文件夹下面的所有文件自动加载起来吧

    没有想到我也做了一回标题党.其实这里边说的自动还是有夸大其词的部分.其实只是指定文件夹,然后根据指定文件夹数据,加载目录下边的内容而已. 怎么来进行Lua文件的加载 一般情况下,相关的功能需要给他创建 ...

  4. 如何实现一个php框架系列文章【3】支持psr4的自动加载类

    psr4自动加载规范https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-4-autoloader-cn.md 我们把第三方使用psr规范的类库放在v ...

  5. PHP 自动加载规范PSR-4

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  6. 构建自己的PHP框架之自动加载类中详解spl_autoload_register()函数

    在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.c ...

  7. jquery 页面滚动到底部自动加载插件集合

    很多社交网站都使用无限滚动的翻页技术来提高用户体验,当你页面滑到列表底部时候无需点击就自动加载更多的内容.下面为你推荐 10 个 jQuery 的无限滚动的插件: 1. jQuery ScrollPa ...

  8. 自动加载dll,加载dll中程序集的信息。

    自动加载程序集,解析程序集中的方法. private static object Invoke(string lpFileName, string Namespace, string ClassNam ...

  9. 【PHP面向对象(OOP)编程入门教程】23.自动加载类 __autoload()函数

    很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件.一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表. 在软件开发的系统中,不可能把所有的类都写在 ...

  10. autocad2008+C#2008开发中设置自动加载dll

    一.复制编译后的dlll路径,比如我的是D:\zjy\cad开发\学习\宗地图\bin\Debug\zd.dll 二.随便找个地方新建一个记事本,在记事本中写入以下内容: (command " ...

随机推荐

  1. Nginx编译参数.md

    Nginx 介绍 简介 Nginx(发音同engine x)是一个网页服务器,它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的协议链接,以及一个负载均衡器和一个HTTP缓存. ...

  2. WPF Popup 控件导致被遮挡内容不刷新的原因

    WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...

  3. C#汉字转拼音(npinyin)将中文转换成拼音全文或首字母

    汉字转拼音貌似一直是C#开发的一个难题,无论什么方案都有一定的bug,之前使用了两种方案. 1.Chinese2Spell.cs 一些不能识别的汉字全部转为Z 2.Microsoft Visual S ...

  4. Computer assisted surgery

    Computer assisted surgery (CAS) represents a surgical concept and set of methods, that use computer ...

  5. Android开发自学笔记(Android Studio)—4.5 ProgressBar及其子类

    一.前言 ProgressBar本身代表了进度条组件,它还派生出了两个常用的组件:SeekBar和RatingBar,他们的使用方法类似,只是显示界面有一定的区别.我们看一下API文档中的说明: 从图 ...

  6. 随便写一下看下效果。一个js问题

    (function(a){ console.log(a); var a = 10; function a(){} }(100)); 问:执行这段代码会输出什么.

  7. C 语言学习 第五次作业总结

    第五次作业,主要学习和复习的是几种循环结构的使用. 在前一次的课堂上,同学们已经学习了分支语句的使用.分支语句和循环语句配合使用,就可以写出更多的,逻辑功能丰富的代码了. 逻辑功能的丰富,也意味着学习 ...

  8. 选择CRM

    第一:可扩展和定制 选择CRM系统一定要注意系统扩展性,要用发展的眼光去审视公司的CRM需求,所以CRM系统必须具有一定的扩展性,从而满足不断变化的公司需求.而那些看起来功能和强大不能扩展看起来貌似也 ...

  9. Iptables防火墙NAT地址转换与端口转发

    开启系统转发功能: [root@localhost /]# vim /etc/sysctl.conf # Generated by iptables-save v1.4.7 on Thu May 12 ...

  10. 写个c++小例子

    class Rational{ public: const Rational operator*( const Rational& rhs); Rational(int num); priva ...