~/blog/laravel-custom-crm-development-workflow-engine-2026.md
企業系統與 CRM · 2026 / 02 / 20

業務不想用 CRM?2026 Laravel 客製化開發實戰:拒絕套版束縛,打造 100% 貼合流程的業務系統

Eric — 浪花科技創辦人 / AI 架構師
Eric
浪花科技創辦人 · AI 架構師
業務不想用 CRM?2026 Laravel 客製化開發實戰:拒絕套版束縛,打造 100% 貼合流程的業務系統
目錄 table-of-contents.md

業務員一邊讓公司付著 Salesforce 等級的訂閱費,一邊偷偷開 Google Sheets 做事——因為「系統欄位跟我們的流程根本不一樣」。套版 CRM 與真實業務流程的落差,靠教育訓練是補不起來的。這篇用 Laravel 實戰客製化 CRM:把欄位、流程、工作流引擎全部照公司的業務邏輯打造,做一套業務真的願意打開的系統。

這幾年「Vibe Coding」和 AI Agent 的崛起,讓寫程式的門檻變低了,但也讓很多企業陷入了「什麼都想自己刻」和「乾脆買套版」的兩難。作為一個看過無數義大利麵程式碼(Spaghetti Code)的工程師,我必須說:CRM 的核心不是資料庫,而是「業務流程(Workflow)」。市面上的 SaaS 賣的是「通用流程」,但能夠讓你的企業獲利的,往往是那些「獨特且刁鑽」的流程。

今天這篇實戰,我們不談虛無縹緲的理論,直接切入如何使用 Laravel(假設我們現在用的是 Laravel 13)來打造一個「完全貼合」企業流程的 CRM 系統。我們將重點放在狀態管理自動化觸發以及資料庫設計,讓你的系統不再是業務的阻礙,而是加速器。

為什麼 2026 年我們還在談客製化 CRM?

你可能會問:「Eric,現在 AI 這麼強,叫 Cursor 或 Antigravity 隨便生成一個 CRM 不就好了?」

老實說,生成 CRUD(增刪查改)介面確實只需 30 秒,但業務邏輯的邊界條件是 AI 很難一次猜對的。例如:

  • 當客戶從「潛在」變成「商機」時,是否需要強制檢查統編?
  • 當報價單超過 50 萬時,是否要自動觸發 Slack 通知給區域經理,鎖定該筆訂單直到審核通過?
  • 如果是回購客戶,折扣邏輯跟新客戶有什麼不同?

這些「流程」,就是套版軟體最難改動的地方。SaaS 為了通用性,往往把這些邏輯寫死,或者要你付天價顧問費來調整。

技術堆疊選擇:Laravel + FilamentPHP (The 2026 Standard)

在 2026 年的現在,如果你還要手刻 HTML/CSS 後台,那我真的會想搖醒你。我們現在的標準起手式通常是 TALL Stack (Tailwind, Alpine, Laravel, Livewire) 加上 FilamentPHP

Filament 讓我們能專注在「後端邏輯」與「資料模型」,UI 部分它已經幫我們處理掉了 90%。這讓客製化開發的速度,幾乎可以跟設定 SaaS 軟體一樣快,但卻擁有 100% 的程式碼控制權。

1. 資料庫設計:別讓欄位限制你的想像

很多 CRM 失敗的原因是資料庫設計太過僵化。針對「業務流程」,我建議使用 JSON 欄位 來儲存動態屬性,但在核心關聯上保持嚴謹。


// migration file
Schema::create('leads', function (Blueprint $table) {
    $table->id();
    $table->string('status')->index(); // 使用 Enum 管理狀態
    $table->foreignId('user_id')->constrained(); // 負責業務
    $table->json('attributes')->nullable(); // 彈性欄位:客戶特殊需求、來源標籤等
    $table->timestamp('last_contacted_at')->nullable();
    $table->timestamps();
});

這裡的小囉嗦:拜託,雖然 2026 年的資料庫效能很強,但 `status` 這種會被拿來當作篩選條件的欄位,請務必加上 index,不然資料破萬筆後,你的業務在後台搜尋時會想砸電腦。

核心實戰:用 Enum 與 State Pattern 管理業務狀態

業務流程的核心就是「狀態機(State Machine)」。客戶從「接觸中」流動到「已報價」,再到「成交」或「流失」。在 Laravel 中,我們使用 PHP 8.1+ 的 Enum 來強制規範這些狀態,避免魔法字串(Magic Strings)滿天飛。

定義狀態 (Enums)


namespace App\Enums;

enum LeadStatus: string
{
    case NEW = 'new';
    case CONTACTED = 'contacted';
    case QUALIFIED = 'qualified';
    case PROPOSAL = 'proposal';
    case WON = 'won';
    case LOST = 'lost';

    public function label(): string
    {
        return match($this) {
            self::NEW => '新進名單',
            self::CONTACTED => '已聯繫',
            self::QUALIFIED => '需求確認',
            self::PROPOSAL => '報價中',
            self::WON => '成交',
            self::LOST => '結案流失',
        };
    }

    public function color(): string
    {
        return match($this) {
            self::NEW => 'gray',
            self::WON => 'success',
            self::LOST => 'danger',
            default => 'primary',
        };
    }
}

實作狀態轉換邏輯 (Service Layer)

不要把邏輯寫在 Controller 裡!這是資深工程師的堅持。我們創建一個 `LeadService` 來處理狀態轉換,確保每次轉換都符合業務規則。


namespace App\Services;

use App\Models\Lead;
use App\Enums\LeadStatus;
use Illuminate\Validation\ValidationException;

class LeadService
{
    public function updateStatus(Lead $lead, LeadStatus $newStatus)
    {
        // 業務規則 1: 不能從「新名單」直接跳到「成交」,必須經過「報價」
        if ($lead->status === LeadStatus::NEW && $newStatus === LeadStatus::WON) {
            throw ValidationException::withMessages([
                'status' => '新名單必須先經過報價流程才能成交。'
            ]);
        }

        // 業務規則 2: 如果要進入「報價中」,必須要有聯絡電話
        if ($newStatus === LeadStatus::PROPOSAL && empty($lead->phone)) {
             throw ValidationException::withMessages([
                'phone' => '進入報價階段前,請先補齊客戶電話。'
            ]);
        }

        $lead->update(['status' => $newStatus]);

        // 觸發後續自動化 (例如發送歡迎信或通知主管)
        event(new LeadStatusChanged($lead));
    }
}

看到沒?這就是 SaaS 很難做到的「防呆機制」。透過程式碼,我們強制執行了公司的 SOP,確保每一筆成交都是資料完整的。

自動化:讓 Laravel Queue 幫業務跑腿

在 2026 年,如果你的 CRM 還需要業務手動寄信說「感謝您的詢問」,那真的太落伍了。我們利用 Laravel 的 Event 和 Listener,結合 Queue(佇列)來處理雜事。

當 `LeadStatusChanged` 事件被觸發時,我們可以掛載多個 Listener:

  1. NotifyManagerListener: 如果金額大於 100 萬,傳送 Slack 通知給總經理。
  2. SyncToErpListener: 如果狀態變成「成交」,透過 API 將資料同步到 ERP 系統開立發票。
  3. AddToMarketingAudienceListener: 將客戶 Email 加入 Mailchimp 或自家行銷系統的「已成交」群組。

// EventServiceProvider (or bootstrap/providers.php in Laravel 11+)
protected $listen = [
    LeadStatusChanged::class => [
        SendWelcomeEmail::class,
        NotifySalesManager::class,
        SyncToERP::class,
    ],
];

這種事件驅動架構 (Event-Driven Architecture) 讓系統保持解耦。你想新增一個「成交後自動送咖啡券」的功能?沒問題,寫一個新的 Listener 掛上去就好,完全不動到核心程式碼。

CRM 裡的 AI:不只是聊天機器人

既然是 2026 年,我們當然要在 CRM 裡塞一點 AI。但不是那種只會陪聊的 Chatbot。我們可以在 `attributes` 欄位中,利用 OpenAI 或 Claude 的 API 來進行「商機評分」。

當業務輸入客戶的對話紀錄(Notes)後,系統背景自動呼叫 AI 分析客戶的購買意願,並更新 `lead_score` 欄位。這能幫助業務早上進辦公室時,優先處理那些「分數高」的潛在客戶,而不是盲目打電話。

結論:資產還是負債?

選擇客製化 CRM 還是 SaaS,本質上是在問:你想讓你的流程配合軟體,還是讓軟體配合你的流程?

在浪花科技,我們看到太多企業因為遷就套版軟體,導致業務人員為了「應付系統」而浪費大量時間。透過 Laravel 現代化的開發工具,打造一個專屬系統的成本與時間已經大幅降低。這不僅是一套軟體,更是企業累積數據與流程的數位資產。

延伸閱讀

如果你正在評估系統架構,或者對資料安全有疑慮,建議參考以下幾篇深度文章:

受夠了被 Excel 和難用的套版軟體綁架嗎?

如果你希望擁有一套真正「懂你業務流程」的系統,而不是讓員工浪費生命在輸入無意義的資料,歡迎找浪花科技聊聊。我們擅長用最新的技術棧,解決最古老的管理難題。

👉 立即填寫表單,預約系統架構諮詢

// FAQ

常見問題

AI 已經很強,為什麼 2026 年企業還需要客製化 CRM?
AI 生成 CRUD 介面確實只需幾十秒,但業務邏輯的邊界條件很難一次猜對。例如客戶從潛在轉商機時是否要強制檢查統編、報價超過特定金額是否要自動通知主管並鎖單待審、回購客折扣邏輯是否不同於新客等。這些獨特流程正是套版 SaaS 為了通用性而寫死、最難改動的部分,也往往是企業真正獲利的關鍵。
客製化 CRM 的資料庫設計如何兼顧彈性與效能?
建議在核心關聯上保持嚴謹,並用 JSON 欄位儲存動態屬性(如客戶特殊需求、來源標籤)以保留彈性。同時,會被拿來當篩選條件的欄位(例如 status)務必加上 index,否則資料量破萬筆後在後台搜尋會明顯變慢。
在 Laravel CRM 中如何管理業務狀態,避免魔法字串滿天飛?
業務流程的核心是狀態機,客戶會從接觸中流動到已報價、成交或流失。可用 PHP 8.1+ 的 Enum 來強制規範這些狀態(如 NEW、CONTACTED、QUALIFIED、PROPOSAL、WON、LOST),避免散落的魔法字串。狀態轉換邏輯則應放在 Service Layer(如 LeadService)而非 Controller,並在其中檢查業務規則,例如新名單必須先經過報價才能成交、進入報價階段前須補齊客戶電話。
客製化 CRM 如何用事件驅動架構處理自動化?
可利用 Laravel 的 Event 與 Listener 搭配 Queue 處理雜事。當狀態變更事件(如 LeadStatusChanged)觸發時,掛載多個 Listener 分別處理通知主管、同步到 ERP 開立發票、加入行銷名單等。這種事件驅動架構讓系統保持解耦,要新增功能只需寫一個新的 Listener 掛上去,完全不動到核心程式碼。
~/roamer-tech/newsletter // FREE
// newsletter

訂閱免費電子報

把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。

$
// final.exec()

準備好讓你的網站開始為你工作了嗎?