iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
DevOps

嘿,稍等一下!別急著開發功能,先來打造 Walking Skeleton 吧!系列 第 22

【Walking Skeleton】Day22 - 安裝 Composer 讓 autoload 來幫你自動 require 函式庫吧!

  • 分享至 

  • xImage
  •  

在安裝 Composer 之前需要安裝過 PHP,因為 Composer 本身就是用 PHP 寫的,可以使用 php -v 來檢查有沒有安裝,如果沒有安裝的話,可以參考之前的安裝教學


在 Linux 安裝 Composer

首先點開官網
https://getcomposer.org/download/

找到下載的方法

然後就把中間那四行複製貼上

這樣就安裝完啦,簡不簡單

我稍微解釋一下這四行做了什麼

  1. 從網路上把安裝程式 composer-setup.php 下載下來,你沒看錯安裝程式是 PHP 程式
  2. 檢查檔案的雜湊值,確保沒被竄改過
  3. 執行安裝程式
  4. 移除安裝程式

安裝完還要做一件事,把 Composer 執行檔移動到 /user/local/bin 中,這樣才可以使用 composer 這個指令

檢查看看是否有設定成功

composer -V

有出現版本就表示設定成功囉


在 Windows 安裝

一樣是先點開官網
https://getcomposer.org/download/

下載 Windows 的安裝程式

點開後,選上面的建議安裝方式,也就是為所有使用者安裝

這邊問說要不要用開發者模式安裝,開發者模式不包括移除程式,推薦是直接按下一步

問說這個是不是你正在用的 PHP 執行檔,如果沒出現的話可能要檢查一下有沒有安裝到 PHP,這邊也是直接按下一步

問你要不要使用代理伺服器,這個是為了解決連線不到 packagist 的問題,一般來說不需要設定這個,直接按下一步

確認設定是否有問題,沒問題就開始安裝

幾秒鐘就安裝完了,因為他本身就只是一個 PHP 程式嘛,只是在 Windows 安裝會需要額外幫你設定一些東西

打開終端機看看是否有設定成功

composer -V

有出現版本就表示安裝成功囉

介紹 Composer

composer require 是用來下載函式庫的,不需要 composer init 就能使用,先 init 的話 composer.json 設定檔會完整一點,也可以在 init 時設定 dependencies,也就是會用到的函式庫,不過那些都不是今天的重點,我這邊就直接用 require 免得要解釋一大堆

composer require ecpay/sdk

ecpay/sdk 是函式庫的名稱,不用知道這個函式庫是做什麼的,packagist 可以查到所有能用的函式庫,不過我通常會是用 google 搜尋 github,再從 github 複製指令來安裝

下載完函式庫會出現 vendor 資料夾,還有 composer.json、composer.lock

vendor 是放 dependencies 的地方,還有最重要的 autoload.php

composer.json 會放這個專案的資訊,以及會用到哪些函式庫

{
    "require": {
        "ecpay/sdk": "^1.2"
    }
}

composer.lock 是用來鎖定那些函式庫用到的函式庫版本的,composer.json 中並不會有這些資訊,如果在不同電腦載了不同的版本有低機率會炸掉,所以通常會把 composer.lock 也一起放到 git 儲存庫中


使用 Composer autoload

在程式一開始的地方用 require 把 autoload.php 載入進來,之後他就會在 new 物件時自動去找到 class 的檔案,並且將它載入進來 (注意不是在 use 的時候,是在 new 的時候,昨天的文章也有說 use 只是別名),這樣就不用再寫一堆 require 囉

index.php

require __DIR__ . '/vendor/autoload.php';

use Ecpay\Sdk\Factories\Factory;

$factory = new Factory();

echo 'success';

執行看看

$ php "d:\_code\php\school\index.php"
success

確實找到 class 並且 new 成功了,沒有炸掉


關於 Composer autoload 的一些設定 psr-4

autoload 不只可以自動載入函式庫,還可以自動載入專案中的程式,不過需要遵守 psr-4 的規範,簡單來說就是所有的命名空間前都要加上一個這個函式庫的命名空間,並且命名空間必須與檔案路徑一一對應

以下是以 miku\school\ 為專案的命名空間為例,將這個命名空間的根目錄設定為 src/

composer.json

{
    "require": {
        "ecpay/sdk": "^1.2"
    },
    "autoload": {
        "psr-4": {
            "miku\\school\\": "src/"
        }
    }
}

在 src 中新增一個 Student.php,並且將命名空間設定為與之對應的 miku\school

src/Student.php

namespace miku\school;

class Student {
    public function __construct(
        public int $id,
        public string $name,
    ) {
    }
    // ...
}

在 index 將物件 new 出來使用

index.php


require __DIR__ . '/vendor/autoload.php';

use Ecpay\Sdk\Factories\Factory;

use miku\school\Student as mikuStudent;

$factory = new Factory();

$student4 = new mikuStudent(4, 'miku');

echo 'success';

執行看看,然後就炸掉了

$ php "d:\_code\php\school\index.php"

Fatal error: Uncaught Error: Class "miku\school\Student" not found in D:\_code\php\school\index.php on line 16

Error: Class "miku\school\Student" not found in D:\_code\php\school\index.php on line 16

Call Stack:
    0.0004     366408   1. {main}() D:\_code\php\school\index.php:0

因為少做了一件事,就是要讓 composer 重新產生 autoload.php,剛剛沒有 psr-4 這個設定,現在改了 composer.json,所以要 dump 一次

composer dump

再執行看看

$ php "d:\_code\php\school\index.php"
success

這次就沒問題了吧


再新增一個 class

src/Teacher.php

namespace miku\school;

class Teacher {
    public function __construct(
        public int $id,
        public string $name,
    ) {
    }
    // ...
}

index.php


require __DIR__ . '/vendor/autoload.php';

use Ecpay\Sdk\Factories\Factory;

use miku\school\Student as mikuStudent;

$factory = new Factory();

$student4 = new mikuStudent(4, 'miku');

$teacher = new Teacher(1, 'teacher');

echo 'success';

不 dump 直接執行

$ php "d:\_code\php\school\index.php"
success

還是成功了,因為 autoload 設定成 psr-4 的話,就只要 dump 第一次,之後在 src 中新增的 class 只要有按照規範 composer 就找的到,適合在開發環境使用;如果設定成 classmap 就要新增 class 一次就 dump 一次,雖然這個選項效能比較好,但通常不會使用,因為到正式環境只要另外加 -o 參數就能達到 classmap 的效果了


關於 Composer autoload 的一些設定 files

files 主要是用來載入那些亂跑、不遵守規則不在 src 資料夾中的程式,這個每次增加一個檔案就會需要重新 dump 一次,所以盡量把程式寫在 src 中使用 psr-4,這樣可以少好幾個步驟

composer.json

{
    "require": {
        "ecpay/sdk": "^1.2"
    },
    "autoload": {
        "psr-4": {
            "miku\\school\\": "src/"
        },
        "files": [
            "lib_a/Student.php",
            "lib_b/Student.php",
            "lib_c/members/Student.php"
        ]
    }
}

index.php

require __DIR__ . '/vendor/autoload.php';

use Ecpay\Sdk\Factories\Factory;
use lib_a\Student;
use lib_b\Student as BStudent;
use lib_c\members as m;
use miku\school\Student as mikuStudent;
use miku\school\Teacher;

$factory = new Factory();

$student1 = new Student(1, 'John');
$student2 = new BStudent(2, 'Adam');
$student3 = new m\Student(3, 'Yuna');
$student4 = new mikuStudent(4, 'miku');

$teacher = new Teacher(1, 'teacher');

echo 'success';

記得加完設定要先 dump

composer dump

執行看看

$ php "d:\_code\php\school\index.php"
success

成功使用 files 另外載入檔案囉


不小心寫太多了,一大堆程式大家看了肯定會睡著的,可是沒有範例就沒辦法複製貼上跑跑看,真是兩難


上一篇
【Walking Skeleton】Day21 - 命名空間 namespace 和 use 是做什麼用的?
下一篇
【Walking Skeleton】Day23 - 用 PHPUnit 來自動測試程式是否有按照預期運作
系列文
嘿,稍等一下!別急著開發功能,先來打造 Walking Skeleton 吧!34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言