Laravel Pint จัดรูปแบบโค้ด PHP ให้ทั้งโปรเจกต์เขียนออกมาแบบเดียวกัน

Laravel Pint เป็น formatter ของ PHP ที่ติดมากับโปรเจกต์ Laravel ใหม่ทุกตัว ใช้ preset laravel ได้ทันทีโดยไม่ต้องตั้งค่า โพสต์นี้อธิบายคำสั่งที่ใช้บ่อย preset ที่เลือกได้ และกฎใน pint.json ที่เราเปิดเพิ่ม

เผยแพร่
เวลาอ่าน
4 นาที
ในโพสต์นี้ 5 หัวข้อ
  1. Pint คือ PHP CS Fixer ที่ตั้งค่ามาให้แล้ว
  2. คำสั่งที่ใช้บ่อย
  3. Preset เป็นชุดกฎตั้งต้น
  4. เปิดกฎเพิ่มใน pint.json
  5. Pint ในเครื่องและใน pull request

PR ที่แก้ logic แค่บรรทัดเดียว แต่ diff ขึ้นมาห้าสิบบรรทัด เพราะ editor ของคนแก้จัด indent ใหม่ทั้งไฟล์ ใครเคยรีวิว PR แบบนี้คงรู้ว่าต้องไล่หาบรรทัดที่เปลี่ยนจริงนานแค่ไหน formatter แก้เรื่องนี้ด้วยการจัดโค้ดของทุกคนให้ออกมาหน้าตาเดียวกัน ฝั่ง PHP ในโปรเจกต์ Laravel ตัวที่ใช้คือ Laravel Pint

Pint เป็น formatter หนึ่งในสี่แบบของเครื่องมือตรวจโค้ด ถ้ายังสับสนว่า Pint ต่างจาก Rector หรือ lint ยังไง ลองอ่านโพสต์ที่แยกเครื่องมือแต่ละแบบก่อนได้ครับ

Pint คือ PHP CS Fixer ที่ตั้งค่ามาให้แล้ว

Pint สร้างอยู่บน PHP CS Fixer ซึ่งเป็นเครื่องมือจัดรูปแบบโค้ด PHP ที่มีมานาน และมีกฎให้เลือกหลายร้อยข้อ ปกติถ้าใช้ PHP CS Fixer ตรง ๆ เราต้องเขียนไฟล์ config เลือกกฎเอง Pint เลือกชุดกฎไว้ให้แล้ว (เอกสารเรียกว่า opinionated) โปรเจกต์ Laravel ใหม่ทุกตัวมี Pint ติดมาใน require-dev จึงรันได้เลย

vendor/bin/pint

โปรเจกต์เก่าที่ยังไม่มี ติดตั้งเพิ่มด้วย composer require laravel/pint --dev

คำสั่งที่ใช้บ่อย

คำสั่ง ทำอะไร
vendor/bin/pint จัดทุกไฟล์ .php ในโปรเจกต์ ยกเว้น vendor
vendor/bin/pint app/Models จัดเฉพาะโฟลเดอร์หรือไฟล์ที่ระบุ
vendor/bin/pint --dirty จัดเฉพาะไฟล์ที่ยังไม่ได้ commit ตาม git
vendor/bin/pint --diff=main จัดเฉพาะไฟล์ที่ต่างจาก branch main
vendor/bin/pint --test ตรวจอย่างเดียว ไม่แก้ไฟล์ จบด้วย exit code ที่ไม่ใช่ 0 ถ้าเจอไฟล์ที่ยังไม่ผ่าน
vendor/bin/pint --repair แก้ไฟล์ให้ แต่จบด้วย exit code ที่ไม่ใช่ 0 ถ้ามีไฟล์ที่ต้องแก้
vendor/bin/pint --parallel รันหลาย process พร้อมกัน (ยังเป็น experimental)

ผลที่ได้หน้าตาแบบนี้ Pint บอกว่าแก้ไฟล์ไหน และแก้ด้วยกฎอะไร

vendor/bin/pint --dirty
  ✓

  ──────────────────────────────────────────────────────────────── Laravel
    FIXED   ................................... 1 file, 1 style issue fixed
  ✓ app/Services/PostTitle.php ordered_class_elements, class_attributes_separation

ตั้งแต่ Pint 1.30.0 ที่ออกเมื่อเดือนกรกฎาคม 2026 Pint จัดไฟล์ Blade ได้ด้วย สั่ง --blade หรือเปิดกฎ Pint/laravel_blade ใน pint.json กฎนี้ใช้ Prettier อยู่เบื้องหลัง เครื่องจึงต้องมี Node.js

Preset เป็นชุดกฎตั้งต้น

Pint มี preset ให้เลือก 5 แบบ คือ laravel, per, psr12, symfony และ empty ค่าเริ่มต้นคือ laravel ซึ่งเป็นรูปแบบเดียวกับโค้ดของตัว Laravel เอง

  • laravel รูปแบบของ Laravel เช่น ไม่มีช่องว่างรอบจุดต่อ string ('a'.$b) ใช้ quote เดี่ยว และ new Foo ไม่ใส่วงเล็บ
  • per ตาม PER Coding Style ของ PHP-FIG ซึ่งมาแทน PSR-12
  • psr12 ตาม PSR-12 สำหรับโปรเจกต์ที่ใช้มาตรฐานนี้อยู่แล้ว
  • symfony รูปแบบของ Symfony
  • empty ไม่มีกฎอะไรเลย ให้เราเลือกเองทั้งหมด

โปรเจกต์ Laravel ใช้ laravel ต่อไปดีที่สุด โค้ดของเราจะหน้าตาเหมือนโค้ดใน vendor/laravel และตัวอย่างในเอกสาร อ่านสลับไปมาได้โดยไม่สะดุด

เปิดกฎเพิ่มใน pint.json

Pint ไม่ต้องมีไฟล์ config ก็ได้ แต่ถ้าอยากเปลี่ยน preset หรือเปิดปิดกฎบางข้อ ให้สร้าง pint.json ที่ราก repo ชื่อกฎใช้ของ PHP CS Fixer ได้ทุกข้อ หาดูได้จาก PHP CS Fixer Configurator

เว็บนี้ใช้ preset laravel แล้วเปิดเพิ่มสามข้อ

{
    "preset": "laravel",
    "rules": {
        "global_namespace_import": { "import_classes": true, "import_constants": false, "import_functions": false },
        "fully_qualified_strict_types": { "import_symbols": true },
        "ordered_class_elements": true
    }
}
  • global_namespace_import ย้ายคลาสของ PHP ที่เขียนเต็มไว้ในโค้ด อย่าง new \DateTimeImmutable ไปเป็น use DateTimeImmutable; ด้านบนไฟล์ ส่วนฟังก์ชันกับค่าคงที่อย่าง count() หรือ PHP_EOL ปล่อยไว้แบบเดิม
  • fully_qualified_strict_types ทำแบบเดียวกันกับคลาสที่อยู่ใน namespace อย่าง \Illuminate\Support\Str::slug() ที่เผลอเขียนเต็มไว้กลางเมธอด จะกลายเป็น use Illuminate\Support\Str; แล้วเหลือแค่ Str::slug()
  • ordered_class_elements เรียงของในคลาสให้เป็นลำดับเดียวกันทุกไฟล์ ค่าเริ่มต้นของกฎนี้คือ trait, enum case, constant, property, constructor, magic method แล้วจึงเป็นเมธอด public, protected และ private

ลองดูคลาสที่เขียนสลับลำดับไว้ และมีชื่อคลาสเขียนเต็มอยู่ในโค้ด (ผลจากการรัน Pint จริงด้วย pint.json ข้างบน)

// เดิม
class Demo
{
    public function handle(): int
    {
        $d = new \DateTimeImmutable();
        $s = \Illuminate\Support\Str::slug('a b');
        return count([$d, $s]);
    }

    private string $name = 'x';

    const LIMIT = 3;

    public function __construct() {}
}

// หลังรัน Pint
use DateTimeImmutable;
use Illuminate\Support\Str;

class Demo
{
    const LIMIT = 3;

    private string $name = 'x';

    public function __construct() {}

    public function handle(): int
    {
        $d = new DateTimeImmutable;
        $s = Str::slug('a b');

        return count([$d, $s]);
    }
}

constant ขึ้นไปอยู่บนสุด ตามด้วย property และ constructor คลาสที่เขียนเต็มกลายเป็น use ด้านบน new DateTimeImmutable() เหลือ new DateTimeImmutable ตาม preset laravel และมีบรรทัดว่างก่อน return

ถ้าอยากให้ Pint ข้ามบางไฟล์ ใส่ไว้ใน exclude (โฟลเดอร์) notName (รูปแบบชื่อไฟล์) หรือ notPath (path ของไฟล์) ใน pint.json ได้

Pint ในเครื่องและใน pull request

ในเครื่อง เรารัน Pint หลัง Rector ทุกครั้ง เพราะโค้ดที่ Rector เขียนใหม่อาจยังไม่ตรงรูปแบบ

vendor/bin/rector process && vendor/bin/pint --dirty

editor ส่วนใหญ่ตั้งให้รัน Pint ทุกครั้งที่บันทึกไฟล์ได้ เช่น PhpStorm มี Laravel Pint อยู่ในหน้า Quality Tools ส่วน VS Code ก็มี extension ให้ติดตั้ง

ถ้าใช้ Claude Code ช่วยเขียนโค้ด ก็ตั้ง hook ให้รัน Pint กับไฟล์ที่ Claude เพิ่งแก้ได้ทุกครั้ง ตัวอย่าง hook ที่ใช้ได้ทั้ง Pint และ Prettier อยู่ในโพสต์ที่แยกเครื่องมือแต่ละแบบ

ใน pull request เว็บนี้รัน pint --test เฉพาะไฟล์ที่ PR แก้ ไฟล์ไหนยังไม่ได้จัด workflow จะไม่ผ่าน คนเปิด PR ก็รัน pint --dirty ในเครื่องแล้ว push ใหม่ เอกสารของ Pint มีอีกทางให้ด้วย คือให้ GitHub Actions รัน Pint แล้ว commit ไฟล์ที่จัดแล้วกลับเข้า branch เอง เราเลือกตรวจอย่างเดียวมากกว่า เพราะไม่อยากให้มี commit จาก bot แทรกเข้ามาใน branch ที่คนอื่นกำลังทำงานอยู่

ตอนถัดไปของซีรีส์ เครื่องมือ Code Quality ใน Laravel

อ่านต่อ

ถูกอ้างถึงใน

ล่าสุด

ดูทั้งหมด →