PHP のスニペット集
このページは、PHP のスニペットとユーティリティ関数などをまとめる予定のページです。
目次
注意
- コードのライセンスは CC0 (クレジット表示不要、改変可、商用可) です。
- 下記は別ページにあります。
スニペット
文字列
置換
かな変換
バイト配列
コードポイント
正規表現
マッチ
置換
HTTP
filter_input()
header()
メール
送信テスト
ob_start()
ob_start();
// echo や var_dump() などを実行
$c = ob_get_clean();
セッションの設定と開始
<?php
// 設定 (別途定数などを定義しておいて取得)
$sessionLifetime = 14*24*60*60; // セッション有効期限 (秒)。例: 14*24*60*60 = 14日
$sessionUrlPath = '/'; // セッション範囲のURLパス
$sessionSavePath = dirname(__FILE__) . '/tmp'; // セッション保存場所 (レンタルサーバーの場合はGC設定が他ユーザーと競合して意図しない動作になるため特に変更が必要)
// ガベージコレクション(GC)の設定
ini_set('session.gc_maxlifetime', max(ini_get('session.gc_maxlifetime'), $sessionLifetime)); // セッション有効期限より長くします
// セッションクッキーの設定
$cookieParams = session_get_cookie_params();
$lifetime = $sessionLifetime;
$path = $sessionUrlPath;
$domain = $cookieParams['domain'];
$secure = isset($_SERVER['HTTPS']) /*&& $_SERVER['HTTPS'] == 'on'*/; // https の時は true
$httponly = true; // 常に true
session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
// セッション保存場所変更
if (!is_dir($sessionSavePath)) @mkdir($sessionSavePath, 0700, true);
session_save_path($sessionSavePath);
// セッション開始
@session_start();
暗号化
$method = 'AES-256-CBC'; // 暗号化の種類 (http://php.net/manual/ja/function.openssl-get-cipher-methods.php にあるもの)
$key = 'password'; // 任意のキー(パスフレーズ)
$iv = '1234567890123456'; // 任意の初期化ベクトル。AESの場合16桁。openssl_cipher_iv_length($method) で取得した桁をもとに文字をランダム生成してもよいです
$data = 'テスト'; // 暗号化したい文字列
$encrypted = openssl_encrypt($data, $method, $key, 0, $iv); // 暗号化 (バイナリが必要な場合、 0 の部分を OPENSSL_RAW_DATA にします)
$decrypted = openssl_decrypt($encrypted, $method, $key, 0, $iv); // 復号 ($sと同じ文字列になります。バイナリの復号は 0 の部分を OPENSSL_RAW_DATA にします)
$method = 'AES-256-CBC'; // 暗号化の種類 (http://php.net/manual/ja/function.openssl-get-cipher-methods.php にあるもの)
$key = 'password'; // 任意のキー(パスフレーズ)
$iv = '1234567890123456'; // 任意の初期化ベクトル。AESの場合16桁。openssl_cipher_iv_length($method) で取得した桁をもとに文字をランダム生成してもよいです
$src = 'test.pdf'; // 元ファイル
$enPath = 'test-e.pdf'; // 暗号化ファイル
$dePath = 'test-d.pdf'; // 複合ファイル
// 暗号化
$data = file_get_contents($src);
file_put_contents($enPath, openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv));
// 復号
$enData = file_get_contents($enPath);
file_put_contents($dePath, openssl_decrypt($enData, $method, $key, OPENSSL_RAW_DATA, $iv));
簡易的なBasic認証
.htaccess
で Basic 認証ができない場合(サーバーで制限されている場合等)でBasic認証したいときに使用します。
<?php
// IDとパスワード(平文)を「:」で区切ってセットして下さい。複数IDで認証したい場合は「,」で区切って下さい。
// 例: define('BASIC_AUTH_PASSWORD', 'test:testpw,test2:test2pw');
define('BASIC_AUTH_PASSWORD', 'test:test,test2:test2');
function basic_auth() {
// http://stackoverflow.com/questions/3663520/php-auth-user-not-set
// CGIモードの場合、.htaccessに下記を記述して下さい (CGIだとPHP_AUTH_**がセットされない)
// RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
if (substr(php_sapi_name(), 0, 3) == 'cgi' && isset($_SERVER['HTTP_AUTHORIZATION'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
}
$user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
$pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
$auth = false;
$pairs = preg_split('/\s*,\s*/', BASIC_AUTH_PASSWORD);
foreach ($pairs as $pair) {
list($u, $p) = preg_split('/\s*:\s*/', $pair);
if ($user == $u && $pass == $p) {
$auth = true;
break;
}
}
if (!$auth) {
header('WWW-Authenticate: Basic realm=\'INPUT USER/PW\'');
header('HTTP/1.0 401 Unauthorized');
echo '認証に失敗しました。';
exit;
}
}
basic_auth();
?>
以下にBASIC認証後のHTMLなどを記載します。非公開領域に置いたファイルを readfile() してきてもよいです。
QRコード生成
Google Chart API を利用して QR コードを生成します。
$size = 300; // QRコードのサイズ(px)
$text = 'https://knooto.info/'; // QRコードに埋め込みたいテキスト
$url = "https://chart.googleapis.com/chart?chs={$size}x{$size}&cht=qr&chl=" . rawurlencode($text); // QRコードのURL
// ファイル保存する場合
// file_put_contents('qr.png', file_get_contents($url));
?>
<img src="<?php echo htmlspecialchars($url, ENT_QUOTES) ?>">
CLI
コマンド
opcodeのダンプ
ユーティリティ関数
(主にフレームワークなどを使う必要が無い小さなプログラム用の関数です)
htmlspecialchars の簡易版
htmlspecialchars()
, echo htmlspecialchars()
と打つのが長いため、h()
, eh()
で呼び出せるようにします。
/**
* 値をHTMLエスケープします。
* @param mixed $value 対象文字列
* @return mixed 変換された文字列
*/
function h($value, $encoding = 'UTF-8') { return htmlspecialchars($value, ENT_QUOTES, $encoding); }
/**
* 値をHTMLエスケープして出力します。
* @param mixed $value 対象文字列
* @return mixed 変換された文字列
*/
function eh($value, $encoding = 'UTF-8') { echo h($value, $encoding); }
リダイレクト
header('Location: ...');
を書く煩わしさを軽減するためのものです。
/**
* 指定されたパスにリダイレクトします。
* @param string $url URL
* @param mixed $args 追加引数
*/
function redirect($url, $args = null) {
if (!is_null($args)) {
$query = http_build_query($args, '', '&', PHP_QUERY_RFC3986); // 追加の引数がある場合、クエリとして追加します。
$url = $url . '?' . $query;
}
header('Location: ' . $url);
exit;
}
// 例:
// redirect('http://example.com/');
// redirect('http://example.com/', array('param' => 'value'));
GET リクエスト判定
/**
* リクエストが GET リクエストか確認します。
* @return boolean GET の場合 true
*/
function is_get() { return (strtoupper($_SERVER['REQUEST_METHOD']) == 'GET'); }
POST リクエスト判定
/**
* リクエストが POST か確認します。
* @return boolean POST の場合 true
*/
function is_post() { return (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST'); }
Ajax リクエスト判定
/**
* リクエストがAjaxのものか確認します。
* @return boolean Ajaxリクエストの場合 (HTTP_X_REQUESTED_WITHが 'XMLHttpRequest' ※case-insentive) true
*/
function is_ajax(){ return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; }
HTTPS 判定
/**
* 現在の通信が https かどうかを確認します。
* @return boolean 現在の通信が https (SSL/TLS) の場合 true
*/
function is_https() {
if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') $https = true;
else if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') $https = true;
else $https = false;
return $https;
}
現在のページの URL
/**
* 現在のページの URL を取得します。
* @return string URL文字列
*/
function current_url() {
return 'http' . (is_https() ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // is_https() を使います
}
文字エンコーディングの変換
SJIS
/**
* 文字列を SJIS に変換します。
*
* @param string $s 文字列
* @param string $fromEncoding 文字列のエンコーディング
* @return mixed 変換後の文字列。失敗した場合は false
*/
function sjis($s, $fromEncoding = 'UTF-8') { return mb_convert_encoding($s, 'SJIS-win', $fromEncoding); }
base64 (URL形式) のエンコード・デコード
/**
* 指定した data を base64 でエンコードします。URLに含められるよう、"+", "/" は "-", "_" に変換し、不要なパディング("=")は除去します。
*
* @param string $data エンコードするデータ。
* @return string エンコードされたデータを文字列で返します。失敗した場合に FALSE を返します。
*/
function base64url_encode($data) {
$encoded = base64_encode($data);
if ($encoded === false) return false;
return rtrim(strtr($encoded, '+/', '-_'), '=');
}
/**
* base64 でエンコードされた data をデコードします。base64url_encode() でエンコードされたデータをデコードするための関数です。
*
* @param string $data デコードされるデータ
* @return string デコードしたデータを返します。失敗した場合に FALSE を返します。
*/
function base64url_decode($data) {
return base64_decode(strtr($data, '-_', '+/')); // base64_decode() はパディング("=")を埋めなくてもデコード可能です。
}
ファイルコピー (フォルダが無ければ生成)
ユニークID (UUID v4)
/**
* ユニークID (UUID v4) を生成します。
*
* @return string RRRRRRRR-RRRR-4RRR-rRRR-RRRRRRRRRRRR 形式の文字列 (R = ランダム、4 = 固定数字 4、r = 0b10RR に相当する16進数文字列)
*/
function uuid_v4() {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
バイト数のフォーマット
/**
* バイト数のフォーマットした値を取得します。(例: 2048 → 2 KB, 1234567 → 1.17737484 MB → 1.18 MB)
*
* @param integer $bytes バイト数
* @param integer $precision 小数点の桁数
* @return string 結果文字列
*/
function byte_format($bytes, $precision = 2) {
$units = array('B', 'KB', 'MB', 'GB', 'TB'); // 単位
$sign = '';
if ($bytes < 0) { // 負数の場合、正にして計算したのち最後に符号を追加します。
$bytes = $bytes * -1;
$sign = '-';
}
$exp = min(floor(log($bytes, 1024)), count($units) - 1); // 指数を取得
if ($bytes != 0) $bytes = $bytes / pow(1024, $exp); // 除算 (KB → bytes / 1024, MB → bytes / 1024^2, GB → bytes / 1024^3, ...)
return $sign . number_format($bytes, $precision) . ' ' . $units[$exp]; // フォーマット
}
簡易ログ
<?php
/** ログの出力先ディレクトリパス */
define('DEBUG_LOG_DIR', './log');
/** ログの保持日数 */
define('DEBUG_LOG_DAYS', 7);
/*
* 簡易ログを出力します。(例: '[2018-01-01 00:00:00] テスト')
* @param string $message ログメッセージ
*/
function debug_log($message) {
$dir = defined('DEBUG_LOG_DIR') ? DEBUG_LOG_DIR : null; // 出力先ディレクトリパスを定数から取得
if (is_null($dir) || (!is_dir($dir) && !@mkdir($dir))) return false; // 出力先ディレクトリパスが無い・生成できない場合中断
$days = (defined('DEBUG_LOG_DAYS')) ? DEBUG_LOG_DAYS : 7; // 保持日数を定数から取得
$logPath = $dir . DIRECTORY_SEPARATOR . date('Ymd') . '.log'; // 例: 20180101.log
// ログファイルを取得して古いログを削除
$files = glob($dir . DIRECTORY_SEPARATOR . '*.log');
$oldLogName = date('Ymd', strtotime("-{$days} day")) . '.log'; // $days = 7 の場合7日前のログ
foreach ($files as $path) {
$name = basename($path);
if (preg_match('#\A[0-9]{8}.log\z#', $name) && $name <= $oldLogName) @unlink($path);
}
// ログ出力
$log = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;
error_log($log, 3, $logPath);
}
// debug_log('テスト');
エラー制御
/**
* エラーを独自制御してメッセージやログを出力します。(h()関数が必要です)
* @param string $errno
* @param string $errstr
* @param string $ettfile
* @param int $errline
*/
function error_handler($errno, $errstr, $errfile, $errline) {
// @ 付きで呼び出された場合 (0) や error_reporting 外のエラーは制御しない
if (!(error_reporting() & $errno)) {
return;
}
// エラーのラベル
$labels = array(
E_WARNING => 'E_WARNING', E_NOTICE => 'E_NOTICE', E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING', E_USER_NOTICE => 'E_USER_NOTICE',
E_STRICT => 'E_STRICT',
);
if (defined('E_RECOVERABLE_ERROR')) $labels[E_RECOVERABLE_ERROR] = 'E_RECOVERABLE_ERROR';
if (defined('E_DEPRECATED')) $labels[E_DEPRECATED] = 'E_DEPRECATED';
if (defined('E_USER_DEPRECATED')) $labels[E_USER_DEPRECATED] = 'E_USER_DEPRECATED';
$label = isset($labels[$errno]) ? $labels[$errno] : 'ERROR';
// 画面表示
if (ini_get('display_errors')) {
header('Content-Type: text/html;charset=UTF-8');
echo '<strong>' . h($label) . '</strong> (' . h($errno) . ') ' . h($errstr) . ' - ';
echo '<strong>' . h($errfile) . '</strong> の <strong>' . h($errline) . '</strong> 行目でエラーが発生しました。' . '<br>';
if (function_exists('debug_backtrace')) { // 4.3.0 未満は debug_backtrace() が無い
$backtrace = debug_backtrace();
array_shift($backtrace);
foreach($backtrace as $i=>$l){
echo ' [' . h($i) . '] in function <strong>';
echo (isset($l['class']) ? (h($l['class'])) : '');
echo (isset($l['type']) ? (h($l['type'])) : '');
echo (isset($l['function']) ? (h($l['function'])) : '');
echo '</strong>';
if(isset($l['file'])) echo ' in <strong>' . h($l['file']) . '</strong>';
if(isset($l['line'])) echo ' on line <strong>' . h($l['line']) . '</strong>';
echo '<br>';
}
}
}
// ログ
$message = '';
$message .= $label . ' (' . $errno . ') ' . $errstr . ' - ';
$message .= $errfile . ' の ' . $errline . ' 行目でエラーが発生しました。' . PHP_EOL;
if (function_exists('debug_backtrace')) { // 4.3.0 未満に debug_backtrace() が無い
$backtrace = debug_backtrace();
array_shift($backtrace);
foreach($backtrace as $i=>$l){
$message .= ' [' . $i . '] in function ';
$message .= (isset($l['class']) ? ($l['class']) : '');
$message .= (isset($l['type']) ? ($l['type']) : '');
$message .= (isset($l['function']) ? ($l['function']) : '');
if(isset($l['file'])) $message .= ' in ' . $l['file'];
if(isset($l['line'])) $message .= ' on line ' . $l['line'];
$message .= PHP_EOL;
}
}
//@debug_log($message); // 必要なログ関数を実行
// 内部エラーハンドラを実行しない
return true;
}
WordPress にある checked() の簡易版
ラジオボタンやチェックボックスの checked
(checked="checked"
) を書く煩わしさを軽減するためのものです。
/**
* 真になる値の場合、checkedを出力します(ラジオボタン、チェックボックス用)。
* @param mixed $v
*/
function checked($v) { if ($v) echo ' checked="checked" '; }
// 例: $x の値によってラジオボタンのチェックを変える
// <input type="radio" name="x" value="1" <?php checked($x == 1) ?>>
// <input type="radio" name="x" value="2" <?php checked($x == 2) ?>>
// <input type="radio" name="x" value="3" <?php checked($x == 3) ?>>
- WordPressの場合、例と同じ形で出力するには
checked($x, 1, true)
かchecked($x == 1, true, true)
とする必要があります。
WordPress にある selected() の簡易版
プルダウンの selected
(selected="selected"
) を書く煩わしさを軽減するためのものです。
/**
* 真になる値の場合、selectedを出力します(select用)。
* @param mixed $v
*/
function selected($v) { if ($v) echo ' selected="selected" '; }
// 例: $x の値によって<select>のチェックを変える
// <select name="x">
// <option value="1" <?php selected($x === '1') ?>>1</option>
// <option value="2" <?php selected($x === '2') ?>>2</option>
// <option value="3" <?php selected($x === '3') ?>>3</option>
// </select>
- WordPressの場合、例と同じ形で出力するには
selected($x, 1, true)
かselected($x == 1, true, true)
とする必要があります。
入力チェックの簡易関数
1つの値の入力チェックをするための簡易関数です。
/**
* 入力ルールに従って1つの値の入力チェックを行います。
* @param string $var 入力値
* @param array $rule 入力ルール
* @param array $errors 標準エラーメッセージを上書きするための連想配列
* @return array 'success' (true, false), 'error' (エラーメッセージ) をキーに持つ連想配列
*/
function validate_var($var, array $rule, array $errors = null) {
$success = true; // 成功したか
$error = ''; // エラーメッセージ
// エラーメッセージ一覧
$defaultErrors = array(
'required' => '{displayName}を入力してください。',
'minValue' => '{displayName}は{minValue}以上で入力してください。',
'maxValue' => '{displayName}は{maxValue}以下で入力してください。',
'minLength' => '{displayName}は{minLength}文字以上で入力してください。',
'maxLength' => '{displayName}は{maxLength}文字以下で入力してください。',
'format' => array(
'number' => '{displayName}は数値の形式で入力してください。',
'email' => '{displayName}はメールアドレスの形式で入力してください。'
),
'items' => '{displayName}の値が規定値と異なります。',
'pattern' => '{displayName}の形式が異なります。'
);
// エラーメッセージ一覧 (マージ)
$e = ($errors) ? array_merge($defaultErrors, $errors) : $defaultErrors;
// エラーメッセージの書式化関数
$str_format = function($text, $params) {
return preg_replace_callback('#\{([^}]+)\}#', function($m) use($params) {
return $params[$m[1]];
}, $text);
};
// フォーマット
$formatPatterns = array(
'number' => '#\A-?(?:[0-9]|[1-9][0-9]+)(?:\.[0-9]+)?\z#',
'email' => '#\A.+?@.+?\..+\z#'
);
if (is_array($var) || is_object($var)) $v = '';
else $v = (string)$var;
if (!isset($rule['displayName'])) $rule['displayName'] = '項目';
$ruleKeys = array_keys($e);
$format = '';
if ($v === '') {
$success = (!isset($rule['required']) || !$rule['required']);
}
else {
foreach ($ruleKeys as $k) {
if (!isset($rule[$k])) continue;
$format = '';
switch ($k) {
// 最小値
case 'minValue':
if ($v < $rule[$k]) $success = false;
break;
// 最大値
case 'maxValue':
if ($v > $rule[$k]) $success = false;
break;
// 最小桁数
case 'minLength':
if (mb_strlen($v) < $rule[$k]) $success = false;
break;
// 最大桁数
case 'maxLength':
if (mb_strlen($v) > $rule[$k]) $success = false;
break;
// 形式
case 'format':
$format = $rule[$k];
if (isset($formatPatterns[$format])) {
$formatPattern = $formatPatterns[$format];
if (!preg_match($formatPattern, $v)) {
$success = false;
}
}
break;
// 規定値
case 'items':
if (!in_array($v, $rule[$k])) $success = false;
break;
// パターン
case 'pattern':
if (!preg_match($rule[$k], $v)) $success = false;
break;
}
if (!$success) {
if (!$error) {
$ve = $e[$k];
if ($k == 'format' && isset($ve[$format])) {
$ve = $ve[$format];
}
// ルールにエラーメッセージがある場合はルールのエラーを優先
if (isset($rule['error'])) {
// 連想配列
if (is_array($rule['error'])) {
// チェック名と同じキーがある
if (isset($rule['error'][$k])) {
// 形式の場合さらに連想配列になっているので、あればその値を使用
if ($k == 'format' && isset($rule['error'][$k][$format])) {
$ve = $rule['error'][$k][$format];
}
else {
$ve = $rule['error'][$k];
}
}
}
// 文字列
else {
$ve = $rule['error'];
}
}
$error = $str_format($ve, $rule);
}
return compact('success', 'error');
}
}
}
return compact('success', 'error');
}