ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
エラー内容
Warning: XMLWriter::openUri(): Unable to resolve file path in /var/www/html/app/Sitemap.php on line 12
Warning: XMLWriter::openUri(/var/www/storage/sitemap.xml): failed to open stream:
Permission denied in /var/www/html/...
Warning: XMLWriter::openUri(/some/path/file.xml): failed to open stream:
No such file or directory in /var/www/html/...
原因の切り分け
| 原因 | 確認 | 対処 |
|---|---|---|
| 保存先ディレクトリが存在しない | is_dir(dirname($path)) | mkdir(..., 0755, true) |
| 書き込み権限不足 | is_writable(dirname($path)) | chmod / オーナー変更 |
| 相対パスの基準が想定外 | getcwd() で確認 | __DIR__ で絶対化 |
| open_basedir 制限 | php -i \| grep open_basedir | 許可パス追加 / 保存先変更 |
| SELinux コンテキスト | ls -Z | chcon -t httpd_sys_rw_content_t |
| ファイルシステム空きなし | df -h | ディスク容量確保 |
| URL ラッパ未許可 | http:// / ftp:// 等 | allow_url_fopen 確認 / ローカルパスに |
基本パターン (sitemap.xml 出力)
<?php
// 安全な保存パターン
$dir = __DIR__ . '/public/sitemaps';
$file = $dir . '/sitemap.xml';
// 1. ディレクトリを必ず作成(既存なら何もしない)
if (!is_dir($dir)) {
mkdir($dir, 0755, true); // ★ true で多階層作成
}
// 2. 書込権限を確認
if (!is_writable($dir)) {
throw new RuntimeException("not writable: $dir");
}
// 3. XMLWriter で書き出し
$xw = new XMLWriter();
if (!$xw->openUri($file)) {
throw new RuntimeException("openUri failed: $file");
}
$xw->setIndent(true);
$xw->startDocument('1.0', 'UTF-8');
$xw->startElement('urlset');
$xw->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($urls as $url) {
$xw->startElement('url');
$xw->writeElement('loc', $url['loc']);
$xw->writeElement('lastmod', $url['lastmod']);
$xw->writeElement('changefreq', $url['changefreq']);
$xw->writeElement('priority', $url['priority']);
$xw->endElement();
}
$xw->endElement(); // urlset
$xw->endDocument();
$xw->flush();
// 4. 出力確認
clearstatcache();
echo "wrote: $file (" . filesize($file) . " bytes)\n";
対処1: パスを絶対化
// ❌ 相対パスは getcwd() の値次第で不安定
$xw->openUri('sitemap.xml'); // cron / Web で getcwd() が違う
// ✅ __DIR__ で絶対化(このファイルがある場所基準)
$xw->openUri(__DIR__ . '/sitemap.xml');
// ✅ Laravel の場合
$xw->openUri(storage_path('app/sitemap.xml'));
$xw->openUri(public_path('sitemap.xml'));
$xw->openUri(base_path('public/sitemap.xml'));
// ✅ realpath で実体パスを取る(シンボリックリンク解消)
$path = realpath(__DIR__ . '/../public') . '/sitemap.xml';
$xw->openUri($path);
対処2: ディレクトリ自動生成
function ensureDir(string $path, int $mode = 0755): void {
$dir = dirname($path);
if (!is_dir($dir)) {
if (!mkdir($dir, $mode, true) && !is_dir($dir)) {
throw new RuntimeException("failed to create dir: $dir");
}
}
if (!is_writable($dir)) {
throw new RuntimeException("dir not writable: $dir");
}
}
$file = '/var/www/storage/sitemaps/2026/sitemap.xml';
ensureDir($file);
$xw = new XMLWriter();
$xw->openUri($file);
対処3: open_basedir 制限の確認
// 現在の制限を確認
echo ini_get('open_basedir');
// → /var/www:/tmp のように出る場合、その外には書き込めない
// 例: open_basedir = /var/www
$xw->openUri('/tmp/foo.xml'); // ★ open_basedir 制限で失敗
// 対処1: 保存先を許可された場所に
$xw->openUri('/var/www/storage/foo.xml'); // ✅
// 対処2: php.ini で open_basedir 緩和
// open_basedir = /var/www:/var/log:/tmp
// → サーバ再起動 / FPM リロード
対処4: 権限とオーナー
# Apache / Nginx のユーザを確認
ps aux | grep -E 'apache|nginx|php-fpm' | head -3
# www-data / apache / nginx などが見つかる
# ディレクトリの所有とパーミッション
ls -la /var/www/storage
# drwxr-xr-x www-data www-data ...
# Laravel 標準
sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
# SELinux (RHEL / CentOS) のコンテキスト
ls -Z storage
sudo chcon -R -t httpd_sys_rw_content_t storage
sudo restorecon -Rv storage
応用: 大規模 sitemap (チャンク分割)
sitemap.xml は1 ファイルあたり 5 万 URL / 50MB まで。それ以上は sitemap index で分割。
function writeSitemapChunk(array $urls, string $file): void {
$xw = new XMLWriter();
$xw->openUri($file);
$xw->setIndent(true);
$xw->startDocument('1.0', 'UTF-8');
$xw->startElement('urlset');
$xw->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($urls as $u) {
$xw->startElement('url');
$xw->writeElement('loc', $u['loc']);
$xw->writeElement('lastmod', $u['lastmod']);
$xw->endElement();
}
$xw->endElement();
$xw->endDocument();
$xw->flush();
}
function writeSitemapIndex(array $sitemaps, string $file): void {
$xw = new XMLWriter();
$xw->openUri($file);
$xw->setIndent(true);
$xw->startDocument('1.0', 'UTF-8');
$xw->startElement('sitemapindex');
$xw->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
foreach ($sitemaps as $sm) {
$xw->startElement('sitemap');
$xw->writeElement('loc', $sm['loc']);
$xw->writeElement('lastmod', $sm['lastmod']);
$xw->endElement();
}
$xw->endElement();
$xw->endDocument();
$xw->flush();
}
// 50,000 URL ごとに分割
$chunks = array_chunk($allUrls, 50000);
$baseDir = public_path('sitemaps');
ensureDir($baseDir . '/dummy');
$sitemapEntries = [];
foreach ($chunks as $i => $chunk) {
$name = "sitemap-{$i}.xml";
writeSitemapChunk($chunk, "$baseDir/$name");
$sitemapEntries[] = [
'loc' => "https://example.com/sitemaps/$name",
'lastmod' => date('Y-m-d'),
];
}
writeSitemapIndex($sitemapEntries, public_path('sitemap.xml'));
openMemory / openUri / outputMemory
| メソッド | 用途 |
|---|---|
openUri($filename) | ファイル / ストリームに直接書込(メモリ効率良) |
openMemory() | メモリ上に蓄積、後で outputMemory() で取得 |
outputMemory(bool $flush) | 蓄積した XML を返す(true でリセット) |
flush(bool $empty) | バッファを書き出す |
// メモリで作って、後で出力(小規模・テスト向き)
$xw = new XMLWriter();
$xw->openMemory();
$xw->startDocument('1.0', 'UTF-8');
$xw->startElement('root');
$xw->writeElement('hello', 'world');
$xw->endElement();
$xw->endDocument();
$xml = $xw->outputMemory(); // ★ 文字列で取得
echo $xml;
// ファイル書込
file_put_contents('/tmp/out.xml', $xml);
// HTTP レスポンスとして返す
header('Content-Type: application/xml; charset=UTF-8');
echo $xml;
PHP 7.4 → 8.x の変更
- PHP 8.0 から多くの関数で「失敗時に warning + false」 から「false 返却のみ」に変更(XMLWriter 系も含む)
- PHP 8.0 から
libxml_use_internal_errors(true)を使うとパース系エラーが例外でなくバッファに溜まる - 厳密モード
declare(strict_types=1)で第 1 引数が string でないとき TypeError
FAQ
Q: PHP 内蔵サーバ (php -S) で動くのに本番で失敗する
A: 実行ユーザの差です。php -S は自分のユーザ権限ですが、本番は www-data / apache 等。chown と chmod を確認。
Q: Docker 内で書込失敗
A: ホストとコンテナで UID/GID が違うとマウントしたボリュームに書けません。Dockerfile で USER 1000:1000 を合わせる、または docker run -u $(id -u):$(id -g)。
Q: 巨大 XML でメモリ不足
A: openMemory() でなく openUri() で直接ファイル書込 + flush() をループ内で呼ぶ。memory_limit も拡張。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
- Fatal error: Maximum execution time of 30 seconds exceeded in...
- Fatal error: Uncaught Error: Cannot use object of type stdClass as array in ...
- Warning: Use of undefined constant ... - assumed '...' (this will throw an Error)
- ERROR: Call to undefined method Maatwebsite\Excel\Excel::load()
- Maximum execution time of 30 seconds exceeded
- Your requirements could not be resolved to an installable set of packages. ... To enable extensions, verify that they are enabled in your .ini files:
- could not find driver
- the requested PHP extension mbstring is missing from your system.
- the requested PHP extension dom is missing from your system.
- A non well formed numeric value encountered
- Warning: Cannot modify header information - headers already sent by ...
- php_network_getaddresses: getaddrinfo failed: Name or service not known
- XMLWriter::openUri(): Unable to resolve file path
- Object of class stdClass could not be converted to string
- Class 'Google_Service_Youtube' not found
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?