Concrete CMS 8.5.x|既存ページを404にして安全に公開予約する方法

2026/02/17
Concrete CMS 8.5.x では、一度公開したページを「日時指定で非公開に戻す」ことができません。
この制約を打破するために、本機能を独自に開発しました。

本記事では、既存ページの権限を変更することなく、
指定した未来日時までは 404 を返して非表示とし、
公開日時を過ぎると 自動的に表示される ――
安全かつ実践的な「公開予約」実装方法を技術解説として紹介します。

既存ページをそのまま活かしつつ、
事故のない公開管理を実現したい方に向けた内容です。

■  権限をいじらずに「公開予約」を安全に実現する実践ノウハウ

Concrete CMS では、ページに「公開日時」を設定できますが、
新規作成時にしか未来日時を指定できず、既存ページでは「非公開に戻す」ことができない
という仕様上の制約があります。

そのため、通常は当該ページを権限付きにする措置をとりますが、一般ユーザーが閲覧すると、
ログイン画面にリダイレクトされてしまうという問題が発生します。

これはセキュリティ上も UX 上も望ましくありません。

  • ログイン画面が出ることで「この URL に何かある」と気づかれる
  • 未公開ページの存在が推測される
  • 公開予約の運用が複雑になる
  • 権限をいじると事故が起きやすい

本記事では、これらの問題を 権限を一切変更せずに解決する方法を紹介します。


■ Concrete CMS の「不条理」:既存ページは未来公開できない

Concrete CMS の標準仕様では:

  • 新規ページ作成時 → 公開日時を未来に設定できる
  • 既存ページ → 公開日時は「更新日時」扱いになり、未来日時を入れても非公開にならない

つまり、一度公開したページを「未来公開」に戻すことができません。

この仕様のため、未公開状態を作るには:

  • 閲覧権限を「管理者のみ」にする
  • しかしその状態で一般ユーザーがアクセスするとログイン画面が出る

という、運用上の不便が発生します。


■ 解決策:未来日時のページは「404」にする

そこで本記事では、
ページ属性に「公開予定日時」を作り、未来日時なら 404 を返す
という仕組みを追加します。

これにより:

  • 権限はゲストのまま
  • 未来日時の間は 404
  • 公開日時を過ぎた瞬間に自動で表示される
  • ログイン画面は出ない
  • ページの存在を隠せる(セキュリティ的に自然)

という、非常に美しい運用が実現します。


■ 必要な準備

1. ページ属性「公開予定日時」を作成

管理画面 > ページとテーマ > 属性
と進み、新規属性の定義を以下の通り行います。

タイプ:日時
を選び

ハンドル

scheduled_publish_datetime

名前: 公開予定日時

2. 404 ページ(/page_not_found)が一般公開されていることを確認

Concrete CMS 標準の 404 ページで問題ありません。


■ Concrete CMS の例外ハンドリング設定(重要)

Concrete CMS が 404 ページにフォールバックできるように、
以下の設定を /application/config/concrete.php に追加します。(ない場合は新規作成します)

<?php

return [
    'debug' => [
        'display_errors' => false,
        'log_errors' => true,
    ],
];

● なぜ必要なのか?

  • display_errors = true のままだと Symfony の例外画面が出てしまう
  • display_errors = false にすることで Concrete CMS が 404 ページに切り替える
  • log_errors = true にすると内部エラーがログに残る

この設定がないと、
NotFoundHttpException が 500 や「予期せぬエラー」に化けることがあります。


■ 実装コード

以下を /application/bootstrap/app.php の末尾に追加します。

<?php

use Concrete\Core\Page\Page;
use Concrete\Core\User\User;
use Concrete\Core\Support\Facade\Events;
use Concrete\Core\Routing\Redirect;
use Concrete\Core\Page\PageAlert\PageAlertList;

/* ------------------------------
   ① ゲスト向け:未来公開 → 404
-------------------------------- */
Events::addListener('on_start', function() {
    $page = Page::getCurrentPage();
    $u = new User();

    // ログイン済みユーザーは除外
    if ($u->isRegistered()) {
        return;
    }

    // 公開予定日時属性を取得
    $dt = $page->getAttribute('scheduled_publish_datetime');

    if ($dt) {
        $timestamp = $dt->getTimestamp();

        if ($timestamp > time()) {
            Redirect::page(Page::getByPath('/page_not_found'))->send();
            exit;
        }
    }
});

/* ------------------------------
   ② 管理者向け:公開前バナー表示
-------------------------------- */
Events::addListener('on_before_render', function() {
    $page = Page::getCurrentPage();
    $u = new User();

    // ゲストには表示しない
    if (!$u->isRegistered()) {
        return;
    }

    // 404 ページでは動かさない
    if ($page->getCollectionPath() === '/page_not_found') {
        return;
    }

    // 公開予定日時属性を取得
    $dt = $page->getAttribute('scheduled_publish_datetime');
    if (!$dt) {
        return;
    }

    $timestamp = $dt->getTimestamp();

    if ($timestamp > time()) {
        $formatted = date('Y-m-d H:i', $timestamp);

        // HTML を直接挿入(管理者バーの上に表示)
        echo '<div style="
            position: fixed;
            top: 48px;
            right: 20px;
            background: #f39c12;
            color: #fff;
            padding: 8px 14px;
            border-radius: 4px;
            z-index: 99999;
            font-size: 14px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
        ">
            このページは公開前です(公開予定:' . $formatted . ')
        </div>';
    }
});

● この方式のポイント

  • 例外を投げず、Concrete CMS の公式 API で 404 に内部リダイレクト
  • テーマやブロックの影響を受けない
  • 500 や「予期せぬエラー」にならない
  • 権限は触らないので安全

■ 動作確認

まず、404を設定したいページで、
コンポーザー/ページ設定 > 属性

属性一覧の下の方に先に属性定義した「公開予定日時」が現れますので、それをアタッチして、公開予定日時をセットします。

すると、当該ページは以下のような挙動をします。

● 公開予定日時を未来に設定

→ 404(Page Not Found)が表示される
→ ログイン画面には飛ばない
→管理者はページが見えて、右上にこのページは公開前です(公開予定:YYYY-MM-DD hh:mm)を表示

● 公開予定日時を過去に設定

→ 通常通りページが表示される

● 公開日時を過ぎた瞬間に自動公開

→ cron も権限トグルも不要


■ この方法のメリットまとめ

メリット 内容
権限を触らない Concrete CMS の権限地雷を完全回避
404 で隠せる 未公開ページの存在を推測されない
公開予約がシンプル 公開日時を過ぎたら自動で表示
既存ページでも未来公開が可能 Concrete CMS の仕様の穴を補完
例外画面が出ない 404 ページに確実にフォールバック

■ まとめ

Concrete CMS の「既存ページは未来公開できない」「未公開ページはログイン画面に飛ぶ」という仕様は、
運用現場で大きなストレスになります。

本記事の方法を使えば:

  • 権限をいじらず
  • 未来日時は 404
  • 公開日時を過ぎたら自動公開

という、現場にとって理想的な運用が実現します。

Concrete CMS を使ったサイト運用で同じ課題に悩んでいる方は、
ぜひこの方法を取り入れてみてください。

最後に大きな注意

「ナビから除く」、「ページリストから除く」、「検索インデックスから除く」
これらをステルスにすることができなかったのです。

要するに、ページは表示しないようにしてもページリストに出てきてしまう。

これも引っかからないようにしようとしましたが、もう面倒で断念しました。

一生懸命手作業でコンポーザー作業してください。でないと「頭隠して尻隠さず」になります。