Contents

PHP內建自動載入autoload方式跟常誤會一些觀念

最近有計畫學 Laravel
不過想趁機會把 PHP Namespace搞清楚
我在想autoload自動載入是甚麼機制的
最近小小的玩了一下,才知道這個自動載入是怎麼用的
其實我覺得也不是完全自動載入阿~~終究還是手動需做載入一段程式

PHP 原有 autoload 方式

include, include_once, require , require_once

都是載入功能。
比較特別注意 include 當載入失敗會跳出警告,但是不會停止程式
require 載入失敗會跳出錯誤,不會繼續執行下面程式

常常忘記哪個會載入錯誤 orz
順便記載這邊

PHP Autoload

前面兩個是比較早期的自動載入方式。簡單來講就是自動載入xxx.php方法
後面 namespace 可搭配composer實作

  • __autoload
  • spl_autoload
  • autoload 與 namespace

PHP 系列 - Autoload 自動載入 « Eric G. Huang 不像樣工程師 備份圖
上面連結介紹太清楚了。
我這邊仔細記錄我實務的問題

常常搞錯的觀念

我是有學過 Java,所以對 Java Namespace 不是很陌生
但當初看 PHP 的 Namespace 有看沒有懂
學得他們很像,但又不是很像
但說 Java Namespace 定義很清楚
PHP 並沒有那麼清楚(畢竟是腳本語言….)

還是需要放置載入程式

首先來看看 Laravel 的 Controller.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

看到這個我整個高潮了
其實我以為 PHP 已經完完整整可以自動載入
不過我自己實作卻是不能…
最終爬文還是找到答案

下面那篇 PO 文跟我一樣 HI XD
php 的 use 明顯比 require 高端大氣上檔次 - 開源中國 備份圖

php 使用命名空间:导入导出之疑问 - 开源中国

為什麼 Laravel 的 Controller.php 可以自動載入
關鍵還是 index.php 的require __DIR__.'/../vendor/autoload.php';
所以我才說也不是真正的自動載入
不過方法真的已經比以前好很多

發現我自己寫的 PHP 沒辦法 use 使用到

當以為你以為require 'vendor/autoload.php';可以載入所有 php 檔案內容
你可能就大錯特錯了!!!

composer.json 有一個 classmap 自動載入

1
2
3
4
5
6
7
8
9
{
    ...
    "autoload": {
    	"classmap": {
    		"mylib"
    	}
    }
    ...
}

~~但不能設定.~~可以設定.
發現我寫錯了,應該要用陣列才對
上面能跑純屬意外

1
2
3
4
5
6
7
8
9
{
    ...
    "autoload": {
    	"classmap": [
    		"."
    	]
    }
    ...
}

發現新增檔案跟修改 class 名稱沒有自動載入到

當我發現這件事,還以為我哪裡寫錯了
其實有看到這篇php – composer.json 設定 classmap 指定自動讀取的檔案或路徑 | jsnWork
vendor/composer/autoload_classmap.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'mylib\\Test' => $baseDir . '/mylib/test.php',
);

看到原來自動載入原來不是真的跑每一層資料夾
是透過暫存方式載入
之前一直還在想有什麼辦法看到目前會自動載入哪些
看來還是有辦法知道的

PSR0 , PSR4

看了一下好像都是自動載入
PSR0 命名規則跟 JAVA 很像
但是 PSR4 規則也不一定要跟 JAVA 擺放位置一樣
我也沒看很詳細,有空再仔細吸收….
psr-0 和 psr-4 的区别 - shuizhuniurou - SegmentFault 思否

Namespace 一些事

Namespace 是不分大小寫的,跟 class、function 一樣沒有分
但是在 use 引用變數(ex:$a)
想說 class 會不會跟 function 一樣不能共用一樣名字
但測試結果是可以的
我還滿驚呆

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php
        //Enter your code here, enjoy!

class A
{
    public function __toString() {
        return 'A';
    }
}

function a(){
    echo 'aa';
}

echo new A();
echo '========';
echo  A();

結果

1
A========aa

那同時去做 use A 不知道會
但用在 use 呢?!
經過小小實驗(未確任是否正確,自己得出的結論)
function 要用通常是要用
use function xxxx
但是做 classmap 跟 psr-4 都載入不到(不知道為什麼)
但有找到Composer/PSR - How to autoload functions? - Stack Overflow
深入 Composer autoload | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区
要選files
不過沒有什麼事情還是不要用 function 吧 XD
這我就沒實作確認

感覺 composer,psr0,psr4 之後還是需要好好了解
先記錄到這邊

參考來源: