あっぽログ
← 記事一覧に戻る

PHPのSplStackとSplQueueを使いこなす:標準ライブラリのデータ構造で効率的な処理を実現する

SplStackとSplQueueとは?

PHPには組み込みの配列(array)が非常に強力で、スタックやキューとしても使えます。しかしPHPのSPL(Standard PHP Library)には、用途に特化したデータ構造クラスが用意されており、意図を明示しながら安全に使える点が大きなメリットです。

今回は代表的な2つを紹介します。

クラス動作原則用途例
SplStackLIFO(後入れ先出し)戻る履歴・再帰処理の模倣
SplQueueFIFO(先入れ先出し)タスクキュー・順番処理

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()
型安全性低いクラスとして扱える

配列で十分な場面も多いですが、チーム開発や複雑なロジックではSplStackSplQueueを使うと意図が明確になりコードの可読性が向上します。


まとめ

  • SplStack はLIFO(後入れ先出し)で、undo機能や再帰の模倣に便利
  • SplQueue はFIFO(先入れ先出し)で、タスク処理や順番待ちロジックに最適
  • どちらもisEmpty()で空チェック、count()で要素数を取得できる
  • 配列でも代替できるが、SPLクラスを使うとコードの意図が明確になる

PHPのSPLにはほかにもSplMinHeapSplMaxHeapSplDoublyLinkedListなどのデータ構造クラスが揃っています。ぜひ公式ドキュメントもあわせて確認してみてください。

← 記事一覧に戻る