こんにちは!今回は、PHPの標準関数であるsession_cache_limiter()について詳しく解説していきます。セッションページのキャッシュ制御方法を設定できる、セキュリティとパフォーマンスに重要な関数です!
session_cache_limiter関数とは?
session_cache_limiter()関数は、現在のセッションで使用するキャッシュリミッターを取得または設定する関数です。
キャッシュリミッターは、ブラウザやプロキシサーバーに送信されるHTTPキャッシュ制御ヘッダーを決定します。セキュリティ、プライバシー、パフォーマンスのバランスを取るために重要な役割を果たします!
基本的な構文
session_cache_limiter(?string $value = null): string|false
- $value: キャッシュリミッター名、省略時は現在の値を取得
- 戻り値: 現在の設定値、失敗時は
false
利用可能なリミッター
// nocache - キャッシュを完全に無効化(デフォルト)
session_cache_limiter('nocache');
// 送信されるヘッダー:
// Expires: Thu, 19 Nov 1981 08:52:00 GMT
// Cache-Control: no-store, no-cache, must-revalidate
// Pragma: no-cache
// private - プライベートキャッシュのみ許可
session_cache_limiter('private');
// 送信されるヘッダー:
// Expires: (現在時刻 + cache_expire)
// Cache-Control: private, max-age=...
// private_no_expire - privateと同じだがExpiresヘッダーなし
session_cache_limiter('private_no_expire');
// 送信されるヘッダー:
// Cache-Control: private, max-age=...
// public - 公開キャッシュを許可
session_cache_limiter('public');
// 送信されるヘッダー:
// Expires: (現在時刻 + cache_expire)
// Cache-Control: public, max-age=...
// '' (空文字列) - キャッシュヘッダーを送信しない
session_cache_limiter('');
// ヘッダーを送信しない(手動制御)
重要な注意点
// session_start()の前に呼び出す必要がある
session_cache_limiter('private'); // 正しい順序
session_start();
// session_start()の後では効果なし
session_start();
session_cache_limiter('private'); // 効果なし
// デフォルト値は'nocache'
echo session_cache_limiter(); // 'nocache'
// session_cache_expire()と組み合わせて使用
session_cache_expire(30); // 30分
session_cache_limiter('private');
session_start();
基本的な使用例
現在の値を取得
// デフォルト値を確認
$limiter = session_cache_limiter();
echo "現在のキャッシュリミッター: {$limiter}\n";
// 出力: 現在のキャッシュリミッター: nocache
リミッターを設定
// privateに設定
$old_limiter = session_cache_limiter('private');
echo "以前の値: {$old_limiter}\n";
echo "新しい値: " . session_cache_limiter() . "\n";
session_start();
キャッシュを完全に無効化
// セキュアなページ用設定
session_cache_limiter('nocache');
session_cache_expire(0);
session_start();
// これにより、ページは決してキャッシュされない
公開コンテンツの設定
// 公開ページ用設定
session_cache_limiter('public');
session_cache_expire(1440); // 24時間
session_start();
// プロキシやCDNでもキャッシュ可能
手動でヘッダー制御
// PHPの自動ヘッダーを無効化
session_cache_limiter('');
session_start();
// 手動でヘッダーを設定
header('Cache-Control: no-cache, must-revalidate');
header('Expires: 0');
実践的な使用例
例1: セキュリティレベル別キャッシュ管理
class SecurityBasedCacheManager {
/**
* セキュリティレベルに応じた設定
*/
public static function configure($securityLevel) {
switch ($securityLevel) {
case 'maximum':
// 最高セキュリティ - キャッシュ完全無効
session_cache_limiter('nocache');
session_cache_expire(0);
return self::getSettings('Maximum Security');
case 'high':
// 高セキュリティ - プライベートキャッシュのみ、短時間
session_cache_limiter('private_no_expire');
session_cache_expire(15);
return self::getSettings('High Security');
case 'medium':
// 中セキュリティ - プライベートキャッシュ、標準時間
session_cache_limiter('private');
session_cache_expire(30);
return self::getSettings('Medium Security');
case 'low':
// 低セキュリティ - 公開キャッシュ可
session_cache_limiter('public');
session_cache_expire(180);
return self::getSettings('Low Security');
case 'custom':
// カスタム - ヘッダーを手動制御
session_cache_limiter('');
session_cache_expire(0);
return self::getSettings('Custom Control');
default:
// デフォルト - nocache
session_cache_limiter('nocache');
session_cache_expire(180);
return self::getSettings('Default');
}
}
/**
* 現在の設定を取得
*/
private static function getSettings($level) {
return [
'security_level' => $level,
'cache_limiter' => session_cache_limiter(),
'cache_expire' => session_cache_expire(),
'headers_preview' => self::getHeadersPreview()
];
}
/**
* 送信されるヘッダーのプレビュー
*/
private static function getHeadersPreview() {
$limiter = session_cache_limiter();
$expire = session_cache_expire() * 60; // 秒に変換
$headers = [];
switch ($limiter) {
case 'nocache':
$headers = [
'Expires' => 'Thu, 19 Nov 1981 08:52:00 GMT',
'Cache-Control' => 'no-store, no-cache, must-revalidate',
'Pragma' => 'no-cache'
];
break;
case 'private':
$headers = [
'Expires' => gmdate('D, d M Y H:i:s', time() + $expire) . ' GMT',
'Cache-Control' => "private, max-age={$expire}"
];
break;
case 'private_no_expire':
$headers = [
'Cache-Control' => "private, max-age={$expire}"
];
break;
case 'public':
$headers = [
'Expires' => gmdate('D, d M Y H:i:s', time() + $expire) . ' GMT',
'Cache-Control' => "public, max-age={$expire}"
];
break;
case '':
$headers = ['Note' => 'No automatic headers sent'];
break;
}
return $headers;
}
/**
* 推奨設定を取得
*/
public static function getRecommendation($pageType) {
$recommendations = [
'login' => 'maximum',
'admin' => 'maximum',
'user_profile' => 'high',
'dashboard' => 'medium',
'blog' => 'low',
'static_content' => 'low',
'api' => 'custom'
];
$level = $recommendations[$pageType] ?? 'medium';
return [
'page_type' => $pageType,
'recommended_level' => $level,
'reason' => self::getRecommendationReason($pageType, $level)
];
}
/**
* 推奨理由を取得
*/
private static function getRecommendationReason($pageType, $level) {
$reasons = [
'login' => '認証情報を含むため最高セキュリティが必要',
'admin' => '管理画面のため最高セキュリティが必要',
'user_profile' => '個人情報を含むため高セキュリティが必要',
'dashboard' => 'ユーザー固有データのため中セキュリティが適切',
'blog' => '公開コンテンツのため低セキュリティで十分',
'static_content' => '静的コンテンツのためキャッシュ推奨',
'api' => 'APIは手動でヘッダー制御が望ましい'
];
return $reasons[$pageType] ?? 'ページタイプに応じた標準設定';
}
}
// 使用例
echo "=== セキュリティレベル別設定 ===\n";
// 各セキュリティレベルをテスト
$levels = ['maximum', 'high', 'medium', 'low', 'custom'];
foreach ($levels as $level) {
echo "\n{$level}:\n";
$settings = SecurityBasedCacheManager::configure($level);
echo " レベル: {$settings['security_level']}\n";
echo " リミッター: {$settings['cache_limiter']}\n";
echo " 有効期限: {$settings['cache_expire']}分\n";
echo " ヘッダー:\n";
foreach ($settings['headers_preview'] as $name => $value) {
echo " {$name}: {$value}\n";
}
}
// ページタイプ別の推奨設定
echo "\n=== ページタイプ別推奨設定 ===\n";
$pageTypes = ['login', 'admin', 'user_profile', 'blog', 'api'];
foreach ($pageTypes as $pageType) {
$recommendation = SecurityBasedCacheManager::getRecommendation($pageType);
echo "\n{$recommendation['page_type']}:\n";
echo " 推奨レベル: {$recommendation['recommended_level']}\n";
echo " 理由: {$recommendation['reason']}\n";
}
例2: ページタイプ別リミッター設定
class PageTypeConfigurator {
private $configurations = [];
/**
* 設定を初期化
*/
public function __construct() {
$this->configurations = [
'authentication' => [
'limiter' => 'nocache',
'expire' => 0,
'description' => 'ログイン/認証ページ',
'reason' => 'セキュリティのため絶対にキャッシュしない'
],
'user_data' => [
'limiter' => 'private_no_expire',
'expire' => 30,
'description' => 'ユーザーデータページ',
'reason' => 'プライベートキャッシュのみ、短時間'
],
'dashboard' => [
'limiter' => 'private',
'expire' => 60,
'description' => 'ダッシュボード',
'reason' => 'ユーザー固有だが更新頻度は低い'
],
'public_content' => [
'limiter' => 'public',
'expire' => 1440,
'description' => '公開コンテンツ',
'reason' => 'CDNやプロキシでのキャッシュを許可'
],
'static_page' => [
'limiter' => 'public',
'expire' => 10080, // 7日
'description' => '静的ページ',
'reason' => 'ほとんど変更されないため長時間キャッシュ'
],
'api_endpoint' => [
'limiter' => '',
'expire' => 0,
'description' => 'APIエンドポイント',
'reason' => 'カスタムヘッダーで制御'
]
];
}
/**
* ページタイプに応じて設定
*/
public function configureForPage($pageType) {
if (!isset($this->configurations[$pageType])) {
throw new Exception("Unknown page type: {$pageType}");
}
$config = $this->configurations[$pageType];
session_cache_limiter($config['limiter']);
session_cache_expire($config['expire']);
return [
'page_type' => $pageType,
'description' => $config['description'],
'reason' => $config['reason'],
'limiter' => session_cache_limiter(),
'expire' => session_cache_expire()
];
}
/**
* すべての設定を一覧表示
*/
public function listConfigurations() {
$list = [];
foreach ($this->configurations as $type => $config) {
$list[] = [
'type' => $type,
'description' => $config['description'],
'limiter' => $config['limiter'],
'expire' => $config['expire'],
'reason' => $config['reason']
];
}
return $list;
}
/**
* URLパスからページタイプを判定
*/
public function detectPageType($path) {
$patterns = [
'/^\/login/' => 'authentication',
'/^\/register/' => 'authentication',
'/^\/logout/' => 'authentication',
'/^\/user\//' => 'user_data',
'/^\/profile/' => 'user_data',
'/^\/dashboard/' => 'dashboard',
'/^\/admin/' => 'dashboard',
'/^\/api\//' => 'api_endpoint',
'/^\/blog\//' => 'public_content',
'/^\/about/' => 'static_page',
'/^\/contact/' => 'static_page'
];
foreach ($patterns as $pattern => $type) {
if (preg_match($pattern, $path)) {
return $type;
}
}
return 'public_content'; // デフォルト
}
/**
* 自動設定(URLから判定)
*/
public function autoConfigureFromUrl($url) {
$parsedUrl = parse_url($url);
$path = $parsedUrl['path'] ?? '/';
$pageType = $this->detectPageType($path);
return $this->configureForPage($pageType);
}
}
// 使用例
echo "=== ページタイプ別設定 ===\n";
$configurator = new PageTypeConfigurator();
// すべての設定を表示
echo "利用可能な設定:\n";
foreach ($configurator->listConfigurations() as $config) {
echo "\n{$config['type']}:\n";
echo " 説明: {$config['description']}\n";
echo " リミッター: {$config['limiter']}\n";
echo " 有効期限: {$config['expire']}分\n";
echo " 理由: {$config['reason']}\n";
}
// URL から自動設定
echo "\n=== URLからの自動設定 ===\n";
$urls = [
'https://example.com/login',
'https://example.com/user/profile',
'https://example.com/blog/article',
'https://example.com/api/data'
];
foreach ($urls as $url) {
$result = $configurator->autoConfigureFromUrl($url);
echo "\n{$url}:\n";
echo " ページタイプ: {$result['page_type']}\n";
echo " リミッター: {$result['limiter']}\n";
echo " 有効期限: {$result['expire']}分\n";
}
例3: 認証状態に応じた動的制御
class AuthenticationAwareCacheControl {
/**
* 認証状態に応じて設定
*/
public function configureByAuthState($isAuthenticated, $userRole = 'guest') {
if (!$isAuthenticated) {
// 未認証 - 公開キャッシュ可
session_cache_limiter('public');
session_cache_expire(180);
$state = 'unauthenticated';
} else {
// 認証済み - ロールに応じて設定
switch ($userRole) {
case 'admin':
// 管理者 - キャッシュなし
session_cache_limiter('nocache');
session_cache_expire(0);
$state = 'admin';
break;
case 'premium':
// プレミアムユーザー - 短時間プライベートキャッシュ
session_cache_limiter('private_no_expire');
session_cache_expire(15);
$state = 'premium_user';
break;
case 'user':
default:
// 一般ユーザー - プライベートキャッシュ
session_cache_limiter('private');
session_cache_expire(30);
$state = 'regular_user';
}
}
return [
'state' => $state,
'authenticated' => $isAuthenticated,
'role' => $userRole,
'limiter' => session_cache_limiter(),
'expire' => session_cache_expire()
];
}
/**
* セッションベースで設定
*/
public function configureFromSession() {
session_start();
$isAuthenticated = $_SESSION['authenticated'] ?? false;
$userRole = $_SESSION['role'] ?? 'guest';
// セッションを閉じて再設定
session_write_close();
// 新しい設定で再開
$config = $this->configureByAuthState($isAuthenticated, $userRole);
session_start();
return $config;
}
/**
* 認証後の設定変更
*/
public function onLoginSuccess($userRole) {
// 現在のセッションを終了
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
// 新しい設定を適用
$config = $this->configureByAuthState(true, $userRole);
// セッションを再開
session_start();
$_SESSION['authenticated'] = true;
$_SESSION['role'] = $userRole;
return $config;
}
/**
* ログアウト時の設定変更
*/
public function onLogout() {
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
// 未認証設定に戻す
$config = $this->configureByAuthState(false);
session_start();
$_SESSION = [];
return $config;
}
/**
* 権限昇格時の設定変更
*/
public function onRoleChange($newRole) {
session_start();
$isAuthenticated = $_SESSION['authenticated'] ?? false;
if (!$isAuthenticated) {
return ['error' => 'Not authenticated'];
}
// セッションを閉じて再設定
session_write_close();
$config = $this->configureByAuthState(true, $newRole);
session_start();
$_SESSION['role'] = $newRole;
return $config;
}
}
// 使用例
echo "=== 認証状態に応じた制御 ===\n";
$cacheControl = new AuthenticationAwareCacheControl();
// 未認証状態
echo "未認証状態:\n";
$config = $cacheControl->configureByAuthState(false);
echo " 状態: {$config['state']}\n";
echo " リミッター: {$config['limiter']}\n";
echo " 有効期限: {$config['expire']}分\n";
// 一般ユーザーとしてログイン
echo "\n一般ユーザーログイン:\n";
$config = $cacheControl->onLoginSuccess('user');
echo " 状態: {$config['state']}\n";
echo " リミッター: {$config['limiter']}\n";
echo " 有効期限: {$config['expire']}分\n";
// 管理者に権限変更
echo "\n管理者に昇格:\n";
$config = $cacheControl->onRoleChange('admin');
echo " 状態: {$config['state']}\n";
echo " リミッター: {$config['limiter']}\n";
echo " 有効期限: {$config['expire']}分\n";
// ログアウト
echo "\nログアウト:\n";
$config = $cacheControl->onLogout();
echo " 状態: {$config['state']}\n";
echo " リミッター: {$config['limiter']}\n";
echo " 有効期限: {$config['expire']}分\n";
例4: APIレスポンスヘッダー管理
class ApiHeaderManager {
/**
* APIエンドポイント用のヘッダー設定
*/
public function configureForApi($endpoint, $cacheStrategy = 'no-cache') {
// PHPの自動ヘッダーを無効化
session_cache_limiter('');
session_start();
// カスタムヘッダーを設定
switch ($cacheStrategy) {
case 'cacheable':
$this->setCacheableHeaders($endpoint);
break;
case 'conditional':
$this->setConditionalHeaders($endpoint);
break;
case 'no-cache':
default:
$this->setNoCacheHeaders();
}
return [
'endpoint' => $endpoint,
'strategy' => $cacheStrategy,
'headers' => $this->getSetHeaders()
];
}
/**
* キャッシュ可能なヘッダー
*/
private function setCacheableHeaders($endpoint) {
$maxAge = $this->getMaxAgeForEndpoint($endpoint);
header("Cache-Control: public, max-age={$maxAge}");
header("Expires: " . gmdate('D, d M Y H:i:s', time() + $maxAge) . ' GMT');
header("ETag: " . md5($endpoint . time()));
}
/**
* 条件付きキャッシュヘッダー
*/
private function setConditionalHeaders($endpoint) {
$etag = md5($endpoint . filemtime(__FILE__));
$lastModified = gmdate('D, d M Y H:i:s', filemtime(__FILE__)) . ' GMT';
header("Cache-Control: private, must-revalidate");
header("ETag: \"{$etag}\"");
header("Last-Modified: {$lastModified}");
// If-None-Matchヘッダーをチェック
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $etag) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
/**
* キャッシュなしヘッダー
*/
private function setNoCacheHeaders() {
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Expires: 0");
}
/**
* エンドポイントごとの最大キャッシュ時間
*/
private function getMaxAgeForEndpoint($endpoint) {
$maxAges = [
'/api/static' => 86400, // 24時間
'/api/content' => 3600, // 1時間
'/api/data' => 300, // 5分
'/api/realtime' => 0 // キャッシュなし
];
foreach ($maxAges as $pattern => $maxAge) {
if (strpos($endpoint, $pattern) === 0) {
return $maxAge;
}
}
return 60; // デフォルト: 1分
}
/**
* 設定されたヘッダーを取得(デバッグ用)
*/
private function getSetHeaders() {
if (function_exists('headers_list')) {
return headers_list();
}
return ['Note' => 'headers_list() not available'];
}
/**
* CORS対応ヘッダーを追加
*/
public function addCorsHeaders($allowedOrigins = ['*']) {
if (in_array('*', $allowedOrigins)) {
header("Access-Control-Allow-Origin: *");
} else {
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowedOrigins)) {
header("Access-Control-Allow-Origin: {$origin}");
}
}
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Max-Age: 86400");
}
/**
* レート制限ヘッダーを追加
*/
public function addRateLimitHeaders($limit, $remaining, $reset) {
header("X-RateLimit-Limit: {$limit}");
header("X-RateLimit-Remaining: {$remaining}");
header("X-RateLimit-Reset: {$reset}");
}
}
// 使用例
echo "=== APIヘッダー管理 ===\n";
$apiManager = new ApiHeaderManager();
// 異なる戦略でAPIを設定
$strategies = ['cacheable', 'conditional', 'no-cache'];
foreach ($strategies as $strategy) {
echo "\n{$strategy} 戦略:\n";
$result = $apiManager->configureForApi('/api/data', $strategy);
echo " エンドポイント: {$result['endpoint']}\n";
echo " 戦略: {$result['strategy']}\n";
// セッションをリセット
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
}
// CORS とレート制限を含む完全な設定
echo "\n=== 完全なAPI設定 ===\n";
session_cache_limiter('');
session_start();
$apiManager->setNoCacheHeaders();
$apiManager->addCorsHeaders(['https://example.com']);
$apiManager->addRateLimitHeaders(100, 95, time() + 3600);
echo "APIヘッダー設定完了\n";
例5: CDN連携システム
class CdnCacheIntegration {
private $cdnEnabled;
private $cdnProvider;
/**
* CDN連携を初期化
*/
public function __construct($cdnEnabled = false, $cdnProvider = 'cloudflare') {
$this->cdnEnabled = $cdnEnabled;
$this->cdnProvider = $cdnProvider;
}
/**
* CDN対応のキャッシュ設定
*/
public function configureCdnCache($contentType, $ttl = 3600) {
if ($this->cdnEnabled) {
// CDN用の設定
session_cache_limiter('public');
session_cache_expire((int)($ttl / 60)); // 分に変換
session_start();
// CDN固有のヘッダーを追加
$this->addCdnHeaders($contentType, $ttl);
} else {
// CDNなしの標準設定
session_cache_limiter('private');
session_cache_expire(30);
session_start();
}
return [
'cdn_enabled' => $this->cdnEnabled,
'content_type' => $contentType,
'ttl' => $ttl,
'limiter' => session_cache_limiter(),
'expire' => session_cache_expire()
];
}
/**
* CDN固有のヘッダーを追加
*/
private function addCdnHeaders($contentType, $ttl) {
switch ($this->cdnProvider) {
case 'cloudflare':
// Cloudflare固有のヘッダー
header("CF-Cache-Status: DYNAMIC");
header("Cache-Control: public, max-age={$ttl}, s-maxage={$ttl}");
break;
case 'fastly':
// Fastly固有のヘッダー
header("Surrogate-Control: max-age={$ttl}");
header("Cache-Control: public, max-age={$ttl}");
break;
case 'akamai':
// Akamai固有のヘッダー
header("Edge-Control: max-age={$ttl}");
header("Cache-Control: public, max-age={$ttl}");
break;
default:
// 一般的なCDNヘッダー
header("Cache-Control: public, max-age={$ttl}");
}
// Vary ヘッダーを追加
header("Vary: Accept-Encoding");
}
/**
* キャッシュパージ用のヘッダー
*/
public function setCachePurgeHeaders() {
session_cache_limiter('');
session_start();
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");
// CDN固有のパージヘッダー
if ($this->cdnEnabled) {
switch ($this->cdnProvider) {
case 'cloudflare':
header("CF-Cache-Status: BYPASS");
break;
case 'fastly':
header("Fastly-Force-Shield: 1");
break;
}
}
return ['purge_headers_set' => true];
}
/**
* コンテンツタイプ別のTTL
*/
public function getTtlForContentType($contentType) {
$ttls = [
'image' => 86400, // 24時間
'css' => 604800, // 7日
'js' => 604800, // 7日
'html' => 3600, // 1時間
'api' => 300, // 5分
'dynamic' => 60 // 1分
];
return $ttls[$contentType] ?? 3600;
}
/**
* 条件付きCDNキャッシュ
*/
public function configureConditional($conditions) {
if ($conditions['user_authenticated']) {
// 認証ユーザー - プライベートキャッシュ
session_cache_limiter('private');
session_cache_expire(15);
$cacheType = 'private';
} elseif ($conditions['content_personalized']) {
// パーソナライズコンテンツ - Varyヘッダーで制御
session_cache_limiter('public');
session_cache_expire(30);
header("Vary: Cookie");
$cacheType = 'personalized';
} else {
// 公開コンテンツ - CDNキャッシュ
$ttl = $this->getTtlForContentType($conditions['content_type']);
$this->configureCdnCache($conditions['content_type'], $ttl);
$cacheType = 'public_cdn';
}
return [
'cache_type' => $cacheType,
'conditions' => $conditions
];
}
}
// 使用例
echo "=== CDN連携システム ===\n";
// CDN有効
$cdn = new CdnCacheIntegration(true, 'cloudflare');
echo "CDN有効時の設定:\n";
$contentTypes = ['image', 'css', 'html', 'api'];
foreach ($contentTypes as $type) {
$ttl = $cdn->getTtlForContentType($type);
$config = $cdn->configureCdnCache($type, $ttl);
echo "\n{$type}:\n";
echo " TTL: {$config['ttl']}秒\n";
echo " リミッター: {$config['limiter']}\n";
session_write_close();
}
// 条件付きキャッシュ
echo "\n=== 条件付きキャッシュ ===\n";
$conditions = [
['user_authenticated' => false, 'content_personalized' => false, 'content_type' => 'html'],
['user_authenticated' => true, 'content_personalized' => false, 'content_type' => 'html'],
['user_authenticated' => false, 'content_personalized' => true, 'content_type' => 'html']
];
foreach ($conditions as $condition) {
$result = $cdn->configureConditional($condition);
echo "\nキャッシュタイプ: {$result['cache_type']}\n";
echo " 認証: " . ($condition['user_authenticated'] ? 'Yes' : 'No') . "\n";
echo " パーソナライズ: " . ($condition['content_personalized'] ? 'Yes' : 'No') . "\n";
session_write_close();
}
例6: キャッシュ戦略マネージャー
class CacheStrategyManager {
private $strategies = [];
private $currentStrategy;
/**
* キャッシュ戦略を初期化
*/
public function __construct() {
$this->strategies = [
'aggressive' => [
'limiter' => 'public',
'expire' => 10080, // 7日
'description' => '積極的キャッシュ - 静的コンテンツ向け',
'use_cases' => ['画像', 'CSS', 'JS', '変更頻度が低いページ']
],
'moderate' => [
'limiter' => 'public',
'expire' => 1440, // 24時間
'description' => '中程度キャッシュ - 一般コンテンツ向け',
'use_cases' => ['ブログ記事', 'ニュース', '商品ページ']
],
'conservative' => [
'limiter' => 'private',
'expire' => 60, // 1時間
'description' => '控えめキャッシュ - ユーザー固有コンテンツ向け',
'use_cases' => ['ダッシュボード', 'マイページ']
],
'minimal' => [
'limiter' => 'private_no_expire',
'expire' => 15, // 15分
'description' => '最小キャッシュ - 頻繁に更新されるコンテンツ向け',
'use_cases' => ['検索結果', 'フィード']
],
'none' => [
'limiter' => 'nocache',
'expire' => 0,
'description' => 'キャッシュなし - セキュアページ向け',
'use_cases' => ['ログイン', '支払い', '個人情報']
]
];
}
/**
* 戦略を適用
*/
public function applyStrategy($strategyName) {
if (!isset($this->strategies[$strategyName])) {
throw new Exception("Unknown strategy: {$strategyName}");
}
$strategy = $this->strategies[$strategyName];
session_cache_limiter($strategy['limiter']);
session_cache_expire($strategy['expire']);
$this->currentStrategy = $strategyName;
return [
'strategy' => $strategyName,
'description' => $strategy['description'],
'limiter' => session_cache_limiter(),
'expire' => session_cache_expire(),
'use_cases' => $strategy['use_cases']
];
}
/**
* コンテンツに基づいて戦略を選択
*/
public function selectStrategy($contentMetadata) {
$score = 0;
// 更新頻度スコア
if ($contentMetadata['update_frequency'] === 'never') {
$score += 4;
} elseif ($contentMetadata['update_frequency'] === 'rarely') {
$score += 3;
} elseif ($contentMetadata['update_frequency'] === 'sometimes') {
$score += 2;
} elseif ($contentMetadata['update_frequency'] === 'often') {
$score += 1;
} else {
$score += 0;
}
// パーソナライゼーションスコア
if (!$contentMetadata['personalized']) {
$score += 2;
}
// セキュリティスコア
if ($contentMetadata['sensitive']) {
return $this->applyStrategy('none');
}
// スコアに基づいて戦略を選択
if ($score >= 5) {
return $this->applyStrategy('aggressive');
} elseif ($score >= 4) {
return $this->applyStrategy('moderate');
} elseif ($score >= 2) {
return $this->applyStrategy('conservative');
} else {
return $this->applyStrategy('minimal');
}
}
/**
* 戦略一覧を取得
*/
public function listStrategies() {
$list = [];
foreach ($this->strategies as $name => $strategy) {
$list[] = [
'name' => $name,
'description' => $strategy['description'],
'limiter' => $strategy['limiter'],
'expire' => $strategy['expire'],
'use_cases' => $strategy['use_cases']
];
}
return $list;
}
/**
* 戦略の比較
*/
public function compareStrategies($strategy1, $strategy2) {
if (!isset($this->strategies[$strategy1]) || !isset($this->strategies[$strategy2])) {
throw new Exception("One or both strategies not found");
}
return [
$strategy1 => $this->strategies[$strategy1],
$strategy2 => $this->strategies[$strategy2],
'recommendation' => $this->getComparisonRecommendation($strategy1, $strategy2)
];
}
/**
* 比較に基づく推奨
*/
private function getComparisonRecommendation($strategy1, $strategy2) {
$expire1 = $this->strategies[$strategy1]['expire'];
$expire2 = $this->strategies[$strategy2]['expire'];
if ($expire1 > $expire2) {
return "{$strategy1}の方がキャッシュ時間が長く、パフォーマンスが向上しますが、コンテンツの鮮度は低下します";
} else {
return "{$strategy2}の方がキャッシュ時間が長く、パフォーマンスが向上しますが、コンテンツの鮮度は低下します";
}
}
}
// 使用例
echo "=== キャッシュ戦略マネージャー ===\n";
$manager = new CacheStrategyManager();
// すべての戦略を表示
echo "利用可能な戦略:\n";
foreach ($manager->listStrategies() as $strategy) {
echo "\n{$strategy['name']}:\n";
echo " 説明: {$strategy['description']}\n";
echo " リミッター: {$strategy['limiter']}\n";
echo " 有効期限: {$strategy['expire']}分\n";
echo " ユースケース: " . implode(', ', $strategy['use_cases']) . "\n";
}
// コンテンツメタデータに基づいて自動選択
echo "\n=== 自動戦略選択 ===\n";
$contentTypes = [
[
'name' => 'ブログ記事',
'update_frequency' => 'rarely',
'personalized' => false,
'sensitive' => false
],
[
'name' => 'ユーザーダッシュボード',
'update_frequency' => 'often',
'personalized' => true,
'sensitive' => false
],
[
'name' => 'ログインページ',
'update_frequency' => 'sometimes',
'personalized' => false,
'sensitive' => true
]
];
foreach ($contentTypes as $content) {
$result = $manager->selectStrategy($content);
echo "\n{$content['name']}:\n";
echo " 選択された戦略: {$result['strategy']}\n";
echo " 説明: {$result['description']}\n";
echo " 有効期限: {$result['expire']}分\n";
session_write_close();
}
HTTPヘッダーの詳細
// 各リミッターが送信するヘッダーの詳細
// nocache
session_cache_limiter('nocache');
session_start();
// Expires: Thu, 19 Nov 1981 08:52:00 GMT
// Cache-Control: no-store, no-cache, must-revalidate
// Pragma: no-cache
// private
session_cache_limiter('private');
session_cache_expire(30); // 30分
session_start();
// Expires: (現在時刻 + 30分)
// Cache-Control: private, max-age=1800
// private_no_expire
session_cache_limiter('private_no_expire');
session_cache_expire(30);
session_start();
// Cache-Control: private, max-age=1800
// (Expiresヘッダーなし)
// public
session_cache_limiter('public');
session_cache_expire(60);
session_start();
// Expires: (現在時刻 + 60分)
// Cache-Control: public, max-age=3600
// '' (空文字列)
session_cache_limiter('');
session_start();
// キャッシュ関連のヘッダーを送信しない
まとめ
session_cache_limiter()関数の特徴をまとめると:
できること:
- セッションページのキャッシュリミッター設定
- HTTPキャッシュヘッダーの制御
- ブラウザ・プロキシのキャッシュ動作制御
利用可能なリミッター:
nocache: キャッシュ完全無効(デフォルト)private: プライベートキャッシュのみprivate_no_expire: privateだがExpiresなしpublic: 公開キャッシュ許可'': 自動ヘッダー無効(手動制御)
推奨される使用場面:
- 認証ページ(nocache)
- ユーザーデータ(private)
- 公開コンテンツ(public)
- APIエンドポイント(”で手動制御)
- CDN連携(public)
重要な注意点:
session_start()の前に呼び出すsession_cache_expire()と組み合わせて使用- セキュリティとパフォーマンスのトレードオフ
- HTTPヘッダーに直接影響
セキュリティ考慮:
// 機密情報を含むページ
session_cache_limiter('nocache');
session_cache_expire(0);
// ユーザー固有データ
session_cache_limiter('private');
session_cache_expire(30);
// 公開データ(CDN可)
session_cache_limiter('public');
session_cache_expire(1440);
ベストプラクティス:
// 1. ページタイプに応じた設定
if ($pageType === 'login') {
session_cache_limiter('nocache');
} elseif ($pageType === 'public') {
session_cache_limiter('public');
} else {
session_cache_limiter('private');
}
// 2. session_start()の前に設定
session_cache_limiter('private');
session_cache_expire(30);
session_start();
// 3. APIでは手動制御
session_cache_limiter('');
session_start();
header('Cache-Control: no-cache');
関連関数:
session_cache_expire(): キャッシュ有効期限設定session_start(): セッション開始header(): HTTPヘッダー送信headers_sent(): ヘッダー送信済みか確認
session_cache_limiter()は、セッションページのキャッシュ動作を細かく制御できる重要な関数です。適切に設定することで、セキュリティを保ちながらパフォーマンスを最適化できます!
