想在 PHP 類別裡放固定值,或讓多個物件共用狀態時,你會遇到 const 和 static。兩者都用 :: 存取,但 const 是「不能改的規則」,static 是「不綁定單一物件的成員」(屬性可改、方法不需 new)。這篇用對照表直接回答 static vs const 怎麼選。
static vs const 速查對照
| 比較項目 | const | static(屬性) | static(方法) |
|---|---|---|---|
| 用途 | 類別常數,值不可重新指定 | 類別層級共用狀態,可修改 | 不需物件實例即可呼叫 |
| 存取 | ClassName::CONSTANT | ClassName::$property | ClassName::method() |
| 能否改值 | ❌ | ✅ | — |
需要 new 嗎 | ❌ | ❌ | ❌ |
| 典型例子 | HTTP 狀態碼、版本號 | 計數器、共用快取 | 工具型格式化函式 |
const和static不是同一層級:const是常數宣告;static是關鍵字,可用於屬性、方法或函式內區域變數。
目錄
const:不會改變的類別規則
<?php
class HttpStatus
{
public const OK = 200;
public const NOT_FOUND = 404;
}
echo HttpStatus::OK; // 200
// 錯誤:類別常數不能重新指定
// HttpStatus::OK = 201;
類別常數必須宣告在類別主體,不能在方法內用 const。若值需要在執行期間變更,就不該用 const。
static 屬性:類別層級的共用狀態
<?php
class Counter
{
public static int $count = 0;
public static function increment(): void
{
self::$count++;
}
}
Counter::increment();
Counter::increment();
echo Counter::$count; // 2
不需要 new Counter()。靜態屬性是「共用」,不是「自動安全」——若不同流程都能任意修改,狀態可能難以追蹤。
static 方法:不需物件的工具函式
<?php
class TextFormatter
{
public static function normalize(string $text): string
{
return trim(mb_strtolower($text));
}
}
echo TextFormatter::normalize(' HELLO '); // hello
靜態方法裡沒有 $this。若需要讀取或修改某個物件的屬性,應改成實例方法。
函式內的 static 變數
<?php
function nextNumber(): int
{
static $number = 0;
return ++$number;
}
echo nextNumber(); // 1
echo nextNumber(); // 2
這是函式自己的持久區域狀態,不是類別常數。會讓函式不再完全純粹,測試時要多留意。
self:: vs static:::繼承時的差別
<?php
class ParentConfig
{
public const NAME = 'parent';
public static function withSelf(): string
{
return self::NAME;
}
public static function withStatic(): string
{
return static::NAME;
}
}
class ChildConfig extends ParentConfig
{
public const NAME = 'child';
}
echo ChildConfig::withSelf(); // parent
echo ChildConfig::withStatic(); // child
self::指向方法宣告所在的類別static::使用晚期靜態繫結,依照實際呼叫的子類別解析
什麼時候用哪個?決策流程
- 值從設計上就不應改變?→
const - 多個物件需要共用且會更新的狀態?→
static屬性 - 方法完全不需要物件資料?→ 可考慮
static方法(但要衡量測試與相依性) - 只是函式多次呼叫間記住結果?→ 函式內
static - 其實是某個物件的資料?→ 一般屬性與實例方法
| 情境 | 建議 |
|---|---|
| HTTP 狀態碼、API 版本、固定上限 | const |
| 全站計數器、類別層級快取 | static 屬性(謹慎使用) |
| 字串格式化、純工具函式 | static 方法 |
| 需要物件狀態的業務邏輯 | 實例方法 + $this-> |
常見問題
Q:static 和 const 可以一起用嗎?
A:可以。例如 public static const 在 PHP 8.3+ 支援類別常數的可見性與型別,但語意仍是常數,不可重新指定。
Q:Singleton 該用 static 嗎?
A:可以用靜態屬性實作,但會引入全域存取與隱藏相依性。看到「只要一個實例」不必立刻套 Singleton。
Q:哪個比較快?
A:除非有實測,否則先依語意與可維護性選擇,不要為了微效能亂用 static。
總結
const:規則,不能重新指定static:不綁定單一物件;屬性值仍可能改變$this->:屬於目前這個物件的資料
