SQLの窓

2020年06月17日


PHP のファイルアップロードで画像ファイルを限定で行う為のテンプレートと注意事項と解説

Webアプリのサンプルソースとして基本的な事

● キャラクタセットは utf-8 で、http ヘッダも meta 要素も統一してどちらも記述します

● イザと言う時の為に、jquery のライブラリは読み込んでいます。これは、デベロッパーツールのコンソールで何かしたい時にとても有効です。

● スマホ表示用として、meta 要素の viewport は記述しておきます。

● デバッグ表示は、print_r( $変数, true ) を pre 要素で挟んで表示します

● コメントを好きな場所に書いて、結果が消えるように <?php // コメントの記述 ?> というような記述方法を使っています。

ブラウザキャッシュについて

PHP の関数として用意されている session_cache_limiter('nocache'); を使用しています。ただ、これを使うには、セッションを開始する必要があります。ここでは、セッションは使用していませんが、いつでも使用できるようにしても損はありません。

ファイルのアップロード処理として2アクションを使用

画面には、アップロードする為の UI に記述を限定しています。実装としてはHTML でも良いのですが、後々の事や、キャッシュやキャラクタセット、そして PHP コメントの使用を考えれば、PHP で記述するほうが得です。但し、機能としてはほぼ、クライアントの処理のみに限定しています。

さらに、IFRAME を使用して、結果によって画面を崩さないようにしています。実用的に考えた場合、この画面自体を IFRAME にして、自由に開いたり閉じたりする UI を想定しています。その場合、3階層のウインドウになりますが、同一ドメインであれば相互の処理は jQuery で容易に行えるので、現在デバッグ情報を表示している最下層の IFRAME で jQuery を出力すれば、フォーム画面の表示調整は容易です。

2アクション目の、upload.php の役目も、ファイルの処理のみに限定でき、メンテナンスや拡張も容易になるはずです。

ファイルアップロード時のエラーコード

PHP のドキュメントを参照して下さい。通常、2(MAX_FILE_SIZE オーバー) か 4 のエラーになると思います

$_FILES 情報の type のウソについて

この情報は正確ではありません。拡張子より決定しているようなので、exif_imagetype で正しいフォーマットを決定して使用しています。Windows 環境では、php.ini で php_exif.dll を有効にする必要があるので注意して下さい。

日本語ファイル名について

日本語部分を urlencode する事によって、一般的に WEB環境のディスクに保存できるようになります。但し、その文字のまま、WEB で呼び出そうとすると Not Found となるので注意して下さい。ブラウザ等から呼び出す場合、urlencode 部分が元に戻ってサーバに渡されます。なので、WEBアプリのクライアント側で扱う文字列としては、もう一度 urlencode しておく必要があります。

同一ファイルのアップロードについて

簡単に uniqid() の結果を頭に付けてファイル名を決定しています。ブラウザ側で、ギャラリーとして表示する場合は、uniqid() 部分を取り除いて表示する事によってオリジナルファイル名となります。しかし、ここでもしそのファイルが日本語の場合、urlencode されているので、urldecode する必要がありますが、そのままでは Windows 環境からアップロードされたものは、SHIFT_JIS のままだという事に注意して下さい。ギャラリーのページのキャラクタセットが SHIFT_JIS 以外の場合は、mb_convert_encoding で変換が必要になります

未実装の処理について

このままでは、ファイルがアップロードされて images フォルダに増えて行くばかりとなります。画像という前提の為、『ギャラリー』を作成する必要がありますが、画像の表示には、メモリを圧迫しない小さな画像ファイル(サムネイル)が必要になります。その為には、GD を使用してアップロードが成功した後に、縮小したファイルを作成する必要があります。

サムネイルが作成されれば、一覧表示をファイルシステム関数を使用して表示するだけですが、オリジナル画像を参照する為に、ポピューラーな Lightbox2 ライブラリ等を実装して使用する事となります。

アップロードフォーム
▼ file_upload.php
<?php
// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: text/html; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<?php // キャラクタセット ?>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<?php // スマホ用 ?>
<meta name="viewport" content="width=device-width,initial-scale=1.0">

<?php // イザと言う時の為 ?>
<script src="https//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

<style>
body {
	margin: 0;
	padding: 30px;
	background-color: #d0d0d0;
}
body,pre,input {
	font-size: 16px;

<?php // よくある(ポピュラーな)設定 ?>
	font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
}
</style>

</head>

<body>
<form
<?php // ファイルアップロードで必須 ?>
	enctype="multipart/form-data"
	method="post"

<?php // ファイルがアップロードされる php ?>
	action="upload.php"

<?php // 結果が表示される IFRAME の名称 ?>
	target="result_window">

<?php // php の画像サイズ制限の設定 ?>
	<input type="hidden" name="MAX_FILE_SIZE" value="1000000">

<?php // ローカルファイル参照用 ?>
	<input type="file" id="file" name="file" size="40">
	<br>
	<br>
	<input
		type="submit"
		name="send"
		value="開始">
	<br>
	<br>
</form>

<?php // 結果が表示される IFRAME ?>
<iframe
	name="result_window"
	frameborder="1"
	scrolling="yes"
	width="100%"
	height="400"
	style='background-color:white;'
></iframe>


</body>
</html>


アップロードされたファイルの処理
▼ upload.php
<?php
// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: text/html; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ファイルを移動するフォルダ
$target_folder = "./images/";

// *************************************
// アップロードされたファイル
// *************************************
$ok = ( $_FILES['file']['error'] == 0 );
if ( $ok ) {

	// *************************************
	// 以降、アップロードそのものは成功
	// *************************************

	// *************************************
	// 1) 画像フォーマットの取得
	// *************************************
	$type_string = image_type_to_mime_type( exif_imagetype( $_FILES['file']['tmp_name'] ) );

	// *************************************
	// 2) オリジナルファイル名の取得
	// *************************************
	$file = explode(".", $_FILES['file']['name']);

	// *************************************
	// 3) 日本語ファイル名対応
	// *************************************
	$file_name = urlencode( $file[0] );

	// *************************************
	// 4) 保存ファイル名を作成
	//   a) 拡張子決定
	//   b) uniqid() でファイル目をユニーク
	// *************************************
	$target = "";
	if ( $type_string == "image/jpeg" ) {
		$target = uniqid() . "_{$file_name}.jpg";
	}
	if ( $type_string == "image/gif" ) {
		$target = uniqid() . "_{$file_name}.gif";
	}
	if ( $type_string == "image/png" ) {
		$target = uniqid() . "_{$file_name}.png";
	}
	if ( $target == "" ) {
		$result = "アップロードできないフォーマットです\n";
	}
	else {
		// *************************************
		// アップロードファイルの保存
		// *************************************
		if ( @move_uploaded_file( $_FILES['file']['tmp_name'], $target_folder . $target ) ) {
			$result = "アップロードに成功しました\n";
		}
		else {
			// なんらかの環境エラー
			$result = "アップロードに失敗しました\n";
		}
		
	}
}
else {
	$result = "ファイルはアップロードされていません";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

<style>
body {
	margin: 0;
	padding: 40px;
	background-color: #ffffff;
}
body,pre {
	font-size: 16px;
	font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
}
</style>

</head>

<body>
<h3><?= $result ?></h3>

<?php // 情報を最も簡単に表示する方法 ?>
<pre>
<?= print_r( $_FILES, true ) ?>
<?= print_r( $_POST, true ) ?>
</pre>
<?php // urlencode は、日本語のファイル名に必要です ?>
<img src="<?= $target_folder . urlencode( $target ) ?>" style='width:90%;'>
</body>
</html>


オリジナルファイル名については、. がファイル名に含まれないように考慮しています。


posted by lightbox at 2020-06-17 05:06 | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

PHP : 指定ファイル名でダウンロード 『application/octet-stream』 と 『Content-disposition: attachment』

application/octet-stream を使う事によって、通常はブラウザに表示されてしまうようなファイルをダウンロードさせる事ができます。

また、保存時のファイル名を正しくする為に Content-disposition を使用しています。

PHP のオンラインマニュアル にはそのものズバリのサンプルが readfile のページにあります。

例1 readfile() によるダウンロードの強制
<?php
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
?>
リンク先のマニュアルでも説明されていますが、readfile はそもそもこのような目的で使われる事を想定しているようで、『メモリに関する問題はなく、 巨大なファイルを送ってもかまいません。』とあります。特殊な目的で出力する為に内容に加工を加えるような場合は、後述のような内容で読み込めばいいはずです。

但し、キャッシュ制御が有効の場合は際限なく読み込んでしまって out of memory エラーが出る場合があるので、ob_end_clean であらかじめキャンセルしておくといいと思います。

システム書き込みバッファの内容を出力したい場合、キャッシュ制御が有効の場合は flash と ob_flush の両方が必要です

ファイルサイズは無くてもダウンロード可能ですが、ただ、存在しないとクライアント側で何パーセント処理済みかの表示が不可能になります。

fread を使用して読み込む
<?
header( "Content-Type: application/octet-stream" );
header( "Content-disposition: attachment; filename={$_GET['download_target']}" );

$path = '../download/' . $_GET['download_target'];

$size = filesize( $path );

header( "Content-Length: $size" );

$fp = fopen( $path, 'rb' );

if ( $fp ) {

	while( TRUE ) {
		if ( feof( $fp ) ) {
			break;
		}
		$ret = fread( $fp, 1024 );
		print $ret;
	}

	fclose( $fp );
}

?>


ファイルの取得方法では、小さいファイルならば、file_get_contents で十分ですが、大きなファイルではメモリが大量に消費させる可能性を考慮する必要があります。さらに、大きなファイルでは PHP 側のタイムアウトの設定も必要になる可能性があります。また、他のサーバーから取り込む場合は、ファイルサイズを取得するのに cURL 関数が必要になります。( PHP 5.0.0 以降 では filesize がそのまま使えるようなニュアンスですが、stat() を http がサポートしていないので使えません )

※ 参考 : max_execution_time (30/PHP_INI_ALL)

▼ PHP マニュアルの投稿の引用
<?php
$remoteFile = 'http://us.php.net/get/php-5.2.10.tar.bz2/from/this/mirror';
$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
  echo 'cURL failed';
  exit;
}

$contentLength = 'unknown';
$status = 'unknown';
if (preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
  $status = (int)$matches[1];
}
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
  $contentLength = (int)$matches[1];
}

echo 'HTTP Status: ' . $status . "\n";
echo 'Content-Length: ' . $contentLength;
?>

Result:

HTTP Status: 302
Content-Length: 8808759
cURL を使ったサンプル

PHP : WEBでもコマンドラインでもHTTPでファイルをダウンロードする



タグ:PHP readfile fread
posted by lightbox at 2020-06-17 04:37 | TrackBack(0) | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

2018年09月01日


PHP の関数で規定されているキャッシュコントロールの無効 : session_cache_limiter( 'nocache' )

session_start() を実行しないと有効にならないので、セッションが必要無い場合は header を直書きすればいいと思いますが、セッションを有効にしても損は無いので以下のようにとておくと簡単です。

session_cache_limiter
<?php
session_cache_limiter('nocache');
session_start();
?>


header を直接書くと以下のようになります
<?php
header( "Expires: Thu, 19 Nov 1981 08:52:00 GMT" );
header( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" );
header( "Pragma: no-cache" );
?>

▼ 以下は、Cache-Control の値についての解説です
HTTP キャッシュ
「no-store」はもっと単純です。返されたレスポンスのバージョンにかかわらず、ブラウザのキャッシュやすべての中間キャッシュはそのレスポンスを一切格納できません。たとえば、個人の機密データや銀行データが含まれているレスポンスなどです。ユーザーがこのアセットをリクエストするたびに、リクエストがサーバーに送信され、完全なレスポンスが毎回ダウンロードされます。
※ 一部引用
posted by lightbox at 2018-09-01 13:31 | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

2018年08月30日


PHP : 一定時間前のファイルの削除

めったに使わないので忘れがちですが、必要になった時に覚えていない。「あのコードどこに使ったっけ・・・」というコードです。

PATH_SEPARATOR は、検索パスのセパレータで、DIRECTORY_SEPARATOR は、ファイルにアクセスする為のパス内のセパレータです

デモページ
$basedir = realpath("../basic-php");

// ターゲットディレクトリの一覧
$dir_handle = @opendir($basedir);
if ( $dir_handle ) {
	$target = readdir( $dir_handle );
	while( $target !== false ) {
		print $target . "\n";
		$target = readdir( $dir_handle );
	}

	closedir( $dir_handle );
}

print "\n\n";

// 5分以上前に作成されたファイルを削除
$dir_handle = @opendir($basedir);
if ( $dir_handle ) {
	$target = readdir( $dir_handle );
	while( $target !== false ) {
		if ( $target == '.' || $target == '..' ) {
			// 対象外
			$target = readdir( $dir_handle );
			continue;
		}

		$astamp = stat($basedir.DIRECTORY_SEPARATOR.$target);
		$laststamp = $astamp[9];

		$lasttime = (int)((time() - $laststamp) / 60) . "." . ((time() - $laststamp) % 60);

		print "{$target} : {$lasttime}\n";

		// 一番最後の . 以降の文字列
		$ext = strrchr( $target, "." );
		// 全て小文字に変換
		$ext = strtolower($ext);
		// 目的の拡張子 のみ削除
		if ( $ext == ".data" ) {
			if ( $laststamp <= time() - 300 ) {
				@unlink($basedir.DIRECTORY_SEPARATOR.$target);
			}
		}
		$target = readdir( $dir_handle );
	}

	closedir( $dir_handle );
}





タグ:PHP
posted by lightbox at 2018-08-30 15:12 | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

2017年04月11日


PHP : ${'日本語表示'} という可変変数と、${hello . "X"} という連結可変変数

※ hello という定数が無いという通知が出る環境では、error_reporting 関数で抑制できます
※ 結果が PHP の認識できる文字列であればいいので、"hello" . (10 * 4) もありです。
※ PHP の可変変数

以下のコードは全て正しく動作しますが、最後の連想配列を除いて、変数名を可変で表現する可変変数のサンプルです。

PHP が変数として許している文字は制限がありますので、$2011/07/08 と言う変数はエラーになりますが、${'2011/07/08'} という変数は正しく動作します。
JavaScript で var a = {}; a["2017/01/01"] = "001"; として、参照が a.2017/01/01 ができないのと同様で、JSON を PHP 内で変換して使う時にも意識するといいです
つまり、日本語を変数として使いたい場合は、${'日本語表示'} という書き方で確実に使える事になります。 日本語は、その構成文字が「キャラクタセット」によって変わるので、どの文字が実際 PHP で変数として使えるかどうかは、はっきり言えませんが、実際使えるものもたくさんあります。しかし、確実では無いので${'日本語表示'}という表現は選択肢のうちの一つです。 また、PHP のマニュアルの投稿内容にありましたが、${文字 . "文字列"} という書き方が何故か正常に動作します。
<?php
error_reporting(E_ALL ^ E_NOTICE);

// $a に値をセット
$a = 'hello';

// $a を変数名として利用
${$a} = 'world (1)';

// world (1) が表示されます
print $hello . "<br>";


// ★ もう少し複雑な場合(1)

// $b[1] に値をセット
$b[1] = 'hello';

// $b[1] を変数名として利用
${$b[1]} = 'world (2)';

// world (2) が表示されます
print $hello . "<br>";


// ★ もう少し複雑な場合(2)

// $c に値をセット
$c = 'hello2';

// $c を変数名として利用
${$c}[1] = 'world (3)';

// world (3) が表示されます
print $hello2[1] . "<br>";


// ★ 文字列の接続

${hello . "X"} = 'world (4)';

// world (4) が表示されます
print $helloX . "<br>";


// ★ エラーにならない特殊な変数
// ※ $2011/07/08 という変数は作れません

$d = '2011/07/08';
${$d} = 'world (5)';

// world (5) が表示されます
print ${'2011/07/08'} . "<br>";


// ★ 日本語変数
// キャラクタセットによって、PHPが使える文字なら
// $日本語表示 でもエラーにはなりません 

$e = '日本語表示';
${$e} = 'world (6)';

// world (6) が表示されます
print ${'日本語表示'} . "<br>";

${'日本語表示'} .= " 追加OK";
print $$e . "<br>";

// ★ 連想配列による日本語表現

$f['日本語表示'] = 'world (7)';

// world (7) が表示されます
print $f['日本語表示'] . "<br>";

?> 




posted by lightbox at 2017-04-11 15:22 | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする

2017年02月28日


cp932 の SQLServer に対して、PHP の ODBC 関数に対して UTF8 変換で地道に対応し、特殊なUncode文字は、HTML 数値エンティティで保存する。

Microsoft のドライバで自動的に対応させる方法もありますが、かつて切り替え時期に Microsoft 純正を使ってえらい目にあった経緯があり、全て SHIFT_JIS で現在も運用していますが、jQuery の ajax を使用するに当たってどうしても通信部分は UTF-8 になるため、以下のようにしています。

また、国際化のためどうしても SHIFT_JIS に無い文字に対応する必要も出てきました。

まず、以下のソースは SHIFT_JIS で書かれており、mb_convert_encoding が不可欠なので、先頭で内部コードを UTF-8 に設定しています。
<?php
mb_internal_encoding("UTF-8");
require_once( "../db.php" );

// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ajax の為、入力値は UTF-8
foreach( $_POST as $Key => $Value ) {

	if ( $Key == "name" || $Key == "name2" ) {
		$_POST[$Key] = mb_encode_numericentity( $Value, array(0x0, 0x2FFFF, 0, 0xFFFFF) );
	}
	else {
		$_POST[$Key] = mb_convert_encoding( $Value, "cp932", "UTF-8" );
	}
}

// *************************************
// 処理
// *************************************
$SQL = new DBSS( $COMMON_DB, "sa" );

$query = "update SQLServerのテーブル set";
$query .= " 姓 = '{$_POST["name"]}'";
$query .= " ,名 = '{$_POST["name2"]}'";

$query .= " where 番号 = {$_POST["no"]}";


$_POST['query'] = $query;

$ret = $SQL->Execute( $query );

if ( $ret === false ) {
	$_POST['status'] = 0;
}
else {
	$_POST['status'] = 1;
}


// *************************************
// PHP の結果を result キーで
// JSON としてブラウザに返す
// *************************************
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
}
print json_encode($_POST);

?>

この処理は、jQuery から呼び出された更新処理です。name と name2 に、HTML 数値エンティティに変換すべき文字列が入っています。全て変換する必要は無いのですが、SHIFT_JIS と Unicode の云々の詳細を省く為に array(0x0, 0x2FFFF, 0, 0xFFFFF) となっています。

0x0 〜 0x2FFFF : オフセット 0、マスク 0xFFFFF

ここでは、サンプルとしてのコードなので、入力文字列が name と name2 しかないので、mb_convert_encoding( $Value, "cp932", "UTF-8" ) が実行されませんが、一般的な SHIFT_JIS の文字列のデータに対して必要です。

print する場合は、jQuery の中に戻るので、再度 UTF-8 に変換する必要があります。

以下は同様の処理で、読み出すだけのコードです。
<?php
mb_internal_encoding("UTF-8");
require_once( "../db.php" );

// *************************************
// キャラクタセット
// *************************************
header( "Content-Type: application/json; charset=utf-8" );
// *************************************
// キャッシュ無効
// *************************************
session_cache_limiter('nocache');
session_start();

// ajax の為、入力値は UTF-8
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "cp932", "UTF-8" );
}

// *************************************
// 処理
// *************************************
$SQL = new DBSS( $COMMON_DB, "sa" );

$query = "select * from SQLServerのテーブル where 番号 = {$_POST["no"]}";
$column = $SQL->QueryEx( $query );

if ( $column ) {

	foreach( $column as $Key => $Value ) {
		$fld = mb_convert_encoding( $Key, "UTF-8", "cp932" );

		if ( $Key == "姓" || $Key == "名" ) {
			$column2[$fld] = mb_decode_numericentity( $Value, array(0x0, 0x2FFFF, 0, 0xFFFFF) );
		}
		else {
			$column2[$fld] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
		}

	}


	$_POST['exist'] = 1;
}
else {
	$_POST['exist'] = 0;
}


// *************************************
// PHP の結果を result キーで
// JSON としてブラウザに返す
// *************************************
foreach( $_POST as $Key => $Value ) {
	$_POST[$Key] = mb_convert_encoding( $Value, "UTF-8", "cp932" );
}
$_POST['data'] = $column2;
print json_encode($_POST);

file_put_contents("debug.log", print_r($_POST, true));

?>

ここで、一番重要なのは、HTML 数値エンティティ を mb_decode_numericentity で元の文字列に戻す事です。これでブラウザから貼り付けれる文字であれば、DB には HTML 数値エンティティ で保存されて、表示すると元に戻るはずです。

※ ただ、DB 側の列の文字列サイズがかなり大きくなります。

ちなみに、Excel への変換は、IE を使用してブラウザからの Excel オフジェクト呼び出しでまかなっています。
▼ 
IE11 で VBScript を使う場合の注意事項 ( 古い社内アプリ移行時必見 )


posted by lightbox at 2017-02-28 22:03 | PHP + 特記事項 | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり