ก่อนมี Composer ถ้าอยากใช้ library อย่าง PHPMailer เราก็ต้องไปโหลด zip มาแตกไว้ในโปรเจกต์ แล้ว require_once ไฟล์ของมันเอง พอ library นั้นต้องใช้ library อื่นต่อ ก็ต้องไปหามาเพิ่มอีก และวันที่อยากอัปเดตก็ต้องทำแบบเดิมซ้ำทุกตัว Composer ทำงานส่วนนี้ให้ทั้งหมด
Composer เป็นตัวจัดการ dependency ของ PHP
เอกสารของ Composer เรียกตัวเองว่า dependency manager คือเราประกาศว่าโปรเจกต์ต้องใช้อะไร แล้ว Composer หาเวอร์ชันที่เข้ากันได้ทั้งหมดมาติดตั้งให้ รวมถึง package ที่ package เหล่านั้นใช้ต่ออีกทอดด้วย ทุกอย่างลงไว้ในโฟลเดอร์ vendor ของโปรเจกต์นั้น ไม่ได้ลงทั้งเครื่องแบบ apt ทำให้สองโปรเจกต์บนเครื่องเดียวกันใช้ Laravel คนละเวอร์ชันได้
package ส่วนใหญ่มาจาก Packagist ซึ่งเป็นที่รวม package สาธารณะของ PHP ตอนนี้มีมากกว่า 470,000 package แนวคิดเดียวกับ npm ฝั่ง JavaScript ซึ่ง Composer ก็บอกว่าได้แรงบันดาลใจมาจาก npm กับ bundler ของ Ruby
ติดตั้ง Composer
Composer รุ่นล่าสุดต้องใช้ PHP 7.2.5 ขึ้นไป
- Windows โหลด Composer-Setup.exe มาติดตั้ง ตัวติดตั้งจะถามหา
php.exeถ้าใช้ XAMPP ก็ชี้ไปที่C:\xampp\php\php.exeแล้วตั้ง PATH ให้เอง ปิด terminal แล้วเปิดใหม่ก่อนลองเรียกcomposer - macOS ใช้ Homebrew ติดตั้งด้วย
brew install composer - Linux และเซิร์ฟเวอร์ ใช้ตัวติดตั้งตามขั้นตอนในหน้า download แล้วย้าย
composer.pharไปไว้ที่/usr/local/bin/composer
Laragon และ Laravel Herd มี Composer มาให้ในตัวแล้ว เช็คว่าใช้ได้ด้วย composer --version
ไฟล์สามอย่างที่ Composer ดูแล
| ไฟล์ | ทำหน้าที่อะไร | commit ขึ้น git ไหม |
|---|---|---|
composer.json |
รายการ package ที่เราขอ พร้อมช่วงเวอร์ชันที่รับได้ | commit |
composer.lock |
เวอร์ชันที่ลงจริงของทุก package รวมตัวที่ลงตามมา | commit |
vendor/ |
โค้ดของ package ทั้งหมด | ไม่ commit ใส่ใน .gitignore |
composer.lock คือไฟล์ที่ทำให้ทุกเครื่องได้เวอร์ชันเดียวกัน เพื่อนในทีมที่ clone โปรเจกต์ไป และเซิร์ฟเวอร์ที่ deploy จะได้ package ทุกตัวตรงกับเครื่องเราทุกตัว ส่วน vendor สร้างใหม่จาก lock file ได้ทุกเมื่อ จึงไม่ต้องเก็บใน git
Composer ยังสร้าง autoloader ไว้ที่ vendor/autoload.php ด้วย โค้ดของเรา require ไฟล์นี้ไฟล์เดียวก็เรียกใช้ class ของทุก package ได้ทันที Laravel ก็ทำแบบนี้ไว้ใน public/index.php อยู่แล้ว
เลขเวอร์ชันใน composer.json
ใน composer.json เราไม่ได้ล็อกเวอร์ชันตายตัว แต่บอกเป็นช่วงที่รับได้ เครื่องหมายที่เจอบ่อยมีสองตัว (เอกสารเรื่องเวอร์ชัน)
| เขียนว่า | รับเวอร์ชัน | ใช้เมื่อ |
|---|---|---|
^13.0 |
ตั้งแต่ 13.0 แต่ไม่ถึง 14.0 | ค่าปกติ รับ minor กับ patch ไม่รับ major ที่อาจมี breaking change |
^0.3 |
ตั้งแต่ 0.3.0 แต่ไม่ถึง 0.4.0 | package ที่ยังไม่ถึง 1.0 ขยับ minor ก็อาจพังได้ |
~1.2.3 |
ตั้งแต่ 1.2.3 แต่ไม่ถึง 1.3.0 | อยากรับแค่ patch |
1.0.2 |
1.0.2 ตัวเดียว | ต้องล็อกไว้จริง ๆ เช่นรอแพตช์ของ package |
composer require ใส่ ^ ให้เองตามเวอร์ชันล่าสุดที่ลงได้ ส่วนใหญ่เราจึงไม่ต้องเขียนเอง
เริ่มโปรเจกต์ใหม่
composer create-project laravel/laravel shop
create-project สร้างโปรเจกต์ใหม่จาก package ต้นแบบ แล้วลง dependency ให้ครบในคำสั่งเดียว ถ้าเป็นโปรเจกต์ PHP ธรรมดาที่ยังไม่มี composer.json ก็ใช้ composer init ให้ Composer ถามทีละข้อแล้วสร้างไฟล์ให้
เพิ่มและลบ package
composer require phpoffice/phpspreadsheet
composer require --dev laravel/pint
composer remove phpoffice/phpspreadsheet
requireเพิ่ม package ลงในcomposer.jsonลงเวอร์ชันล่าสุดที่เข้ากับโปรเจกต์ได้ แล้วอัปเดต lock file ให้ ระบุเวอร์ชันเองได้ด้วยcomposer require "vendor/package:^2.0"--devใส่ไว้ในrequire-devสำหรับของที่ใช้ตอนพัฒนาเท่านั้น เช่นเครื่องมือ test และ code style ซึ่ง production ไม่ต้องลงremoveเอาออกจากcomposer.jsonแล้วลบออกจากvendorและ lock file
install กับ update ต่างกันที่ lock file
สองคำสั่งนี้ชื่อคล้ายกัน แต่ใช้คนละจังหวะ
| คำสั่ง | ทำอะไร | ใช้ตอนไหน |
|---|---|---|
composer install |
ลงตาม composer.lock ทุกตัว ไม่เปลี่ยนเวอร์ชัน |
หลัง clone, หลัง git pull, ตอน deploy |
composer update |
หาเวอร์ชันใหม่ที่ยังอยู่ในช่วงของ composer.json แล้วเขียน lock file ใหม่ |
ตอนตั้งใจอัปเดต package |
composer update laravel/framework
composer update laravel/framework -W
composer update --dry-run
- ใส่ชื่อ package หลัง
updateเพื่ออัปเดตแค่ตัวนั้น ตัวอื่นใน lock file ไม่ขยับ -W(--with-all-dependencies) ให้ขยับ dependency ของตัวนั้นด้วย ใช้เมื่อ Composer บอกว่าอัปเดตไม่ได้เพราะ dependency ล็อกเวอร์ชันไว้--dry-runดูก่อนว่าจะเปลี่ยนอะไรบ้าง โดยยังไม่ลงจริง
ถ้าเพื่อนในทีมรัน update แล้ว commit lock file มา เราแค่รัน composer install ก็ได้เวอร์ชันเดียวกัน ถ้าลืมบ่อย ลองตั้ง git hook ให้รัน composer install เองหลัง git pull ได้
update คือจังหวะที่ package เวอร์ชันใหม่เข้ามาในโปรเจกต์ Composer 2.11 ขึ้นไปตั้งให้รอเวอร์ชันที่เพิ่งออกสักพักก่อนติดตั้ง ได้ เผื่อเวอร์ชันนั้นเป็นของปลอมจากบัญชีที่โดนยึด
ตอน deploy ขึ้น production
composer install --no-dev --optimize-autoloader --no-interaction
--no-devไม่ลง package ในrequire-devเครื่องมือ test และ debug จะไม่ขึ้นไปอยู่บนเซิร์ฟเวอร์--optimize-autoloader(-o) สร้าง classmap ให้ autoloader หา class ได้เร็วขึ้น เอกสารของ Composer แนะนำให้ใช้บน production--no-interaction(-n) ไม่ถามอะไรระหว่างทาง เหมาะกับ script deploy และ CI
ห้ามรัน composer update บนเซิร์ฟเวอร์ เพราะจะได้เวอร์ชันที่ไม่เคยทดสอบบนเครื่องเรา ถ้าอยากเห็นว่าคำสั่งนี้อยู่ตรงไหนในขั้น deploy ทั้งหมด ลองอ่านลำดับขั้น deploy Laravel ได้ครับ
ดูว่ามีอะไรต้องอัปเดตและใครดึง package มา
composer outdated -D
composer show laravel/framework
composer why guzzlehttp/guzzle
composer why-not php 8.5
outdatedแสดง package ที่มีเวอร์ชันใหม่-Dดูเฉพาะตัวที่เราใส่เองในcomposer.jsonไม่รวมตัวที่ลงตามมา--major-only,--minor-only,--patch-onlyกรองตามระดับได้showดูรายละเอียดของ package ที่ลงอยู่ ใส่--treeจะเห็นว่าแต่ละตัวใช้อะไรต่อwhyบอกว่า package ไหนดึงตัวนี้เข้ามา เจอ package แปลก ๆ ใน lock file ก็ใช้คำสั่งนี้why-notบอกว่าอะไรทำให้ขยับไปเวอร์ชันนั้นไม่ได้ ใช้บ่อยตอนเตรียมอัปเกรด PHP
เช็คช่องโหว่ด้วย composer audit
composer audit
audit เทียบ package ที่ลงอยู่กับฐานข้อมูลช่องโหว่ แล้วบอกว่าตัวไหนมี advisory พร้อมระดับความรุนแรง คำสั่งจบด้วย error เมื่อเจอปัญหา จึงใส่ใน CI ได้เลย Composer รุ่นใหม่รัน audit ให้เองหลัง require และ update ด้วย ถ้าไม่อยากคอยรันเอง Dependabot ช่วยเปิด PR แพตช์ให้ได้
คำสั่งที่ไม่ได้ใช้ทุกวันแต่ควรรู้
composer dump-autoloadสร้าง autoloader ใหม่ ใช้หลังเพิ่ม namespace ในautoloadของcomposer.jsonหรือเพิ่ม helper filecomposer run-scriptหรือcomposer runรันคำสั่งที่ตั้งไว้ในscriptsของcomposer.jsonโปรเจกต์ Laravel ใหม่มีcomposer run devที่เปิด server, queue และ Vite พร้อมกันcomposer self-updateอัปเดตตัว Composer เอง ถ้ารุ่นใหม่มีปัญหา ถอยกลับด้วยcomposer self-update --rollbackcomposer diagnoseตรวจปัญหาที่เจอบ่อย เช่นต่อ Packagist ไม่ได้ หรือตั้งค่า PHP ไม่ครบcomposer global requireลงเครื่องมือไว้ใช้ทั้งเครื่อง เช่นcomposer global require laravel/installerแล้วเรียกlaravel newได้จากทุกโฟลเดอร์
ปัญหาที่อาจเจอตอนใช้งานจริง
Your requirements could not be resolved แปลว่า Composer หาเวอร์ชันที่เข้ากันได้ทุกตัวไม่เจอ อ่านข้อความต่อจากนั้นจะบอกว่าตัวไหนติดกับตัวไหน บ่อยครั้งเป็นเรื่องเวอร์ชัน PHP บนเครื่องต่ำกว่าที่ package ต้องการ เช่น XAMPP ที่ยังเป็น PHP 8.1 แต่ Laravel 13 ต้องใช้ 8.3 ขึ้นไป
ขาด PHP extension เช่น ext-zip, ext-gd หรือ ext-intl บน XAMPP เปิดได้ด้วยการเอา ; หน้าบรรทัด extension= ใน php.ini ออก แล้วเปิด terminal ใหม่ composer check-platform-reqs จะบอกว่าเครื่องนี้ขาดอะไรที่ package ในโปรเจกต์ต้องใช้
--ignore-platform-reqs ทำให้ติดตั้งผ่านได้ก็จริง แต่ package ที่ต้องใช้ extension นั้นจะไปพังตอนรันแทน ควรใช้เฉพาะตอนที่รู้ว่าเครื่องที่รันจริงมี extension ครบ เช่นลง package บนเครื่องเราแต่ไปรันใน Docker
หน่วยความจำไม่พอ บนเซิร์ฟเวอร์เล็กหรือ shared hosting composer update อาจหยุดด้วย error เรื่อง memory ทางที่ดีคือรัน update บนเครื่องเรา แล้วให้เซิร์ฟเวอร์รันแค่ install ซึ่งใช้หน่วยความจำน้อยกว่ามาก ถ้าจำเป็นต้องรันจริง ๆ ปลดล็อกชั่วคราวได้ด้วย COMPOSER_MEMORY_LIMIT=-1
คำสั่งทั้งหมดพร้อมตัวเลือกครบทุกตัวอยู่ในเอกสาร command-line ของ Composer ครับ






