SplStackとSplQueueとは?
PHPには組み込みの配列(array)が非常に強力で、スタックやキューとしても使えます。しかしPHPのSPL(Standard PHP Library)には、用途に特化したデータ構造クラスが用意されており、意図を明示しながら安全に使える点が大きなメリットです。
今回は代表的な2つを紹介します。
| クラス | 動作原則 | 用途例 |
|---|---|---|
SplStack | LIFO(後入れ先出し) | 戻る履歴・再帰処理の模倣 |
SplQueue | FIFO(先入れ先出し) | タスクキュー・順番処理 |
SplStackを使う
基本的な操作
SplStackは最後に追加した要素を最初に取り出すLIFO構造です。
<?php
$stack = new SplStack();
// 要素を追加(push)
$stack->push('ページA');
$stack->push('ページB');
$stack->push('ページC');
echo $stack->top() . PHP_EOL; // ページC(先頭を確認するだけ)
// 要素を取り出す(pop)
echo $stack->pop() . PHP_EOL; // ページC
echo $stack->pop() . PHP_EOL; // ページB
echo $stack->pop() . PHP_EOL; // ページA
push()で追加、pop()で取り出し、top()で先頭の確認(取り出しなし)ができます。
実践例:ブラウザの「戻る」履歴を模倣する
<?php
class BrowserHistory
{
private SplStack $history;
private string $current;
public function __construct(string $initialPage)
{
$this->history = new SplStack();
$this->current = $initialPage;
}
public function visit(string $page): void
{
$this->history->push($this->current);
$this->current = $page;
echo "訪問: {$this->current}" . PHP_EOL;
}
public function back(): void
{
if ($this->history->isEmpty()) {
echo "履歴がありません" . PHP_EOL;
return;
}
$this->current = $this->history->pop();
echo "戻る: {$this->current}" . PHP_EOL;
}
public function current(): string
{
return $this->current;
}
}
$browser = new BrowserHistory('ホーム');
$browser->visit('ブログ一覧');
$browser->visit('記事詳細');
$browser->visit('著者ページ');
$browser->back(); // 著者ページ → 記事詳細
$browser->back(); // 記事詳細 → ブログ一覧
出力結果:
訪問: ブログ一覧
訪問: 記事詳細
訪問: 著者ページ
戻る: 記事詳細
戻る: ブログ一覧
SplQueueを使う
基本的な操作
SplQueueは最初に追加した要素を最初に取り出すFIFO構造です。
<?php
$queue = new SplQueue();
// 要素を追加(enqueue)
$queue->enqueue('タスクA');
$queue->enqueue('タスクB');
$queue->enqueue('タスクC');
echo $queue->bottom() . PHP_EOL; // タスクA(先頭を確認するだけ)
// 要素を取り出す(dequeue)
echo $queue->dequeue() . PHP_EOL; // タスクA
echo $queue->dequeue() . PHP_EOL; // タスクB
echo $queue->dequeue() . PHP_EOL; // タスクC
enqueue()で追加、dequeue()で取り出しを行います。
実践例:シンプルなジョブキュー
<?php
class JobQueue
{
private SplQueue $queue;
public function __construct()
{
$this->queue = new SplQueue();
}
public function addJob(string $jobName): void
{
$this->queue->enqueue($jobName);
echo "ジョブ追加: {$jobName}" . PHP_EOL;
}
public function process(): void
{
if ($this->queue->isEmpty()) {
echo "処理するジョブがありません" . PHP_EOL;
return;
}
while (!$this->queue->isEmpty()) {
$job = $this->queue->dequeue();
echo "処理中: {$job}" . PHP_EOL;
}
}
}
$jobQueue = new JobQueue();
$jobQueue->addJob('メール送信');
$jobQueue->addJob('サムネイル生成');
$jobQueue->addJob('レポート作成');
echo "--- 処理開始 ---" . PHP_EOL;
$jobQueue->process();
出力結果:
ジョブ追加: メール送信
ジョブ追加: サムネイル生成
ジョブ追加: レポート作成
--- 処理開始 ---
処理中: メール送信
処理中: サムネイル生成
処理中: レポート作成
配列との比較:いつSPLを使うべきか
<?php
// 配列でもスタックは実現できる
$arrayStack = [];
array_push($arrayStack, 'A');
$value = array_pop($arrayStack);
// SplStackを使う場合
$splStack = new SplStack();
$splStack->push('A');
$value = $splStack->pop();
| 観点 | 配列 | SplStack / SplQueue |
|---|---|---|
| コードの意図 | 不明確になりがち | 明示的でわかりやすい |
| 空チェック | empty() | isEmpty() |
| 要素数取得 | count() | count() |
| 型安全性 | 低い | クラスとして扱える |
配列で十分な場面も多いですが、チーム開発や複雑なロジックではSplStack・SplQueueを使うと意図が明確になりコードの可読性が向上します。
まとめ
SplStackはLIFO(後入れ先出し)で、undo機能や再帰の模倣に便利SplQueueはFIFO(先入れ先出し)で、タスク処理や順番待ちロジックに最適- どちらも
isEmpty()で空チェック、count()で要素数を取得できる - 配列でも代替できるが、SPLクラスを使うとコードの意図が明確になる
PHPのSPLにはほかにもSplMinHeap・SplMaxHeap・SplDoublyLinkedListなどのデータ構造クラスが揃っています。ぜひ公式ドキュメントもあわせて確認してみてください。