想在 PHP 類別裡放固定值,或讓多個物件共用狀態時,你會遇到 conststatic。兩者都用 :: 存取,但 const 是「不能改的規則」static 是「不綁定單一物件的成員」(屬性可改、方法不需 new)。這篇用對照表直接回答 static vs const 怎麼選。

static vs const 速查對照

比較項目conststatic(屬性)static(方法)
用途類別常數,值不可重新指定類別層級共用狀態,可修改不需物件實例即可呼叫
存取ClassName::CONSTANTClassName::$propertyClassName::method()
能否改值
需要 new
典型例子HTTP 狀態碼、版本號計數器、共用快取工具型格式化函式

conststatic 不是同一層級: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:: 使用晚期靜態繫結,依照實際呼叫的子類別解析

什麼時候用哪個?決策流程

  1. 值從設計上就不應改變?→ const
  2. 多個物件需要共用且會更新的狀態?→ static 屬性
  3. 方法完全不需要物件資料?→ 可考慮 static 方法(但要衡量測試與相依性)
  4. 只是函式多次呼叫間記住結果?→ 函式內 static
  5. 其實是某個物件的資料?→ 一般屬性與實例方法
情境建議
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->:屬於目前這個物件的資料

延伸閱讀:存取修飾符 · 類別與物件入門

參考資料