<?php
// ひらがな一覧(必要なら増やせる)
$hiragana = [
'あ','い','う','え','お',
'か','き','く','け','こ',
'さ','し','す','せ','そ',
'た','ち','つ','て','と',
'な','に','ぬ','ね','の',
'は','ひ','ふ','へ','ほ',
'ま','み','む','め','も',
'や','ゆ','よ',
'ら','り','る','れ','ろ',
'わ','を','ん'
];
// ひらがな3文字をランダム生成
$captcha = '';
for ($i = 0; $i < 3; $i++) {
$captcha .= $hiragana[random_int(0, count($hiragana) - 1)];
}
echo $captcha;
アルファベット大文字3文字のランダム生成
<?php
// アルファベット大文字一覧(A〜Z)
$alpha = range('A', 'Z');
// 3文字をランダム生成
$captcha = '';
for ($i = 0; $i < 3; $i++) {
$captcha .= $alpha[random_int(0, 25)];
}
echo $captcha;
$a = 17;
$b = 5;
$quotient = intdiv($a, $b); // 3
商と余りを両方取得
$a = 17;
$b = 5;
$quotient = intdiv($a, $b); // 3
$remainder = $a % $b; // 2
<?php
putenv('PATH=/usr/local/bin:/usr/bin:/bin:/home/ユーザー名/bin');
exec('echo $PATH', $out);
var_dump($out);
PHP の exec() を使う前に、環境変数 PATH をセットできます。
この方法は「その PHP プロセス内だけ」有効。
但し、絶対パス指定が最も安全で、PATH に依存するのは避けるべきです。
$img = new Imagick($filepath);
$frames = $img->getNumberImages();
if ($frames > 1) {
if ($file_ext === 'gif') {
// アニメ GIF
s_webp -> ffmpeg
webp -> gif2webp
o_webp -> gif2webp
}
// アニメ WebP
s_webp -> アニメ WebP → PNG → ffmpeg(静止画)
webp = o_webp -> そのままコピー(PHP の copy)
} else {
if ($file_ext === 'gif') {
// 静止 GIF
s_webp -> ffmpeg
webp -> 静止GIF → PNG → cwebp
o_webp -> 静止GIF → PNG → cwebp
}
// JPEG/PNG/静止 WebP
s_webp -> ffmpeg
webp -> cwebp
o_webp -> cwebp
}
※ cwebp が GIF をサポートしていない場合
※ ffmpeg で Animated WebP をデコードできない場合
ffmpeg の crop は 入力画像より大きいサイズを指定すると必ずエラーになるため scale で短い方を150pxに“拡大”して揃えてから中央150px角を cropする。
アニメGIF → アニメWebP
ffmpeg -i input.gif \
-vf "scale='if(gt(iw,ih),-1,150)':'if(gt(iw,ih),150,-1)',crop=150:150" \
-c:v libwebp -loop 0 output.webp
アニメGIF → 静止サムネイル(PNG)
ffmpeg -i input.gif \
-vf "scale='if(gt(iw,ih),-1,150)':'if(gt(iw,ih),150,-1)',crop=150:150" \
-vframes 1 temp.png
● 1. まず短い方を 必ず150pxに揃える
横長(iw > ih)
→ 高さを150に、幅は自動計算(-1)
縦長(ih > iw)
→ 幅を150に、高さは自動計算(-1)
つまり 短い方が必ず150pxになる
● 2. その後に中央150px角を crop
ffmpeg の “increase” が効かない特殊ケース
Invalid too big or non positive size for width '150' or height '150'
Failed to configure input pad on Parsed_crop_1
Error reinitializing filters! Failed to inject frame into filter network: Invalid argument Error while filtering: Invalid argument
内部で「拡大後のサイズが整数にならない」などの理由で crop の初期化に失敗することがある。
220×123 の GIF は、縦が 123px(150px 未満)なので本来は increase で 150px 以上に拡大されるはずですが、
拡大後のサイズが 奇数/偶数の組み合わせで ffmpeg が scale → crop の再初期化に失敗することがあります。
外部コマンドを扱うときは、次の 3 つが基本になります。
sprintf:文字列をフォーマットしてコマンドを組み立てる
escapeshellarg:引数を安全にエスケープする
exec:コマンドを実行して結果を受け取る
🧱 1. sprintf:フォーマットしてコマンドを組み立てる
役割
「%s の部分に変数を埋め込んで、整った文字列を作る」
$cmd = sprintf('cwebp %s -o %s', $input, $output);
🛡 2. escapeshellarg:引数を安全にする
役割
「シェルで危険な文字を無害化して、1つの引数として扱わせる」
$input = escapeshellarg($inputPath);
$output = escapeshellarg($outputPath);
🚀 3. exec:コマンドを実行して結果を受け取る
exec($cmd, $output, $ret);
引数の意味
$cmd:実行するコマンド
$output:コマンドの標準出力(配列で返る)
$ret:終了ステータス(0 が成功)
exec($cmd, $output, $ret);
if ($ret !== 0) {
echo "エラーが発生しました";
}
🧩 3 つを組み合わせた「正しい外部コマンド実行」
$input = escapeshellarg($inputPath);
$output = escapeshellarg($outputPath);
$cmd = sprintf(
'cwebp %s -o %s',
$input,
$output
);
exec($cmd, $outputLines, $ret);
if ($ret !== 0) {
// エラー処理
}
SVG → PNG/WebP の品質は、
rsvg-convert + cwebp の組み合わせが最強。
SVG → PNG(rsvg-convert)
PNG → WebP(cwebp)
GIF / JPEG / PNG / WebP → WebP の品質は、
cwebp + gif2webp の組み合わせが最強。
🌟 cwebp は何をするツールなのか
✔ 入力:PNG / JPEG / TIFF / BMP / PPM / WebP(再圧縮)
✔ 出力:WebP(lossy または lossless)
GIF と WebP 変換の正しい整理
1. アニメーション GIF
フレームを複数持つ
→ gif2webp が必須
cwebp はアニメーションを扱えない
フレーム保持・最適化・ループ情報などを正しく処理できるのは gif2webp
2. 静止画 GIF(1フレーム)
実体は「256色の PNG に近い静止画像」
→ cwebp で完全に変換可能
透明度もそのまま扱える
画質も PNG と同じ扱いで良い
判定
● GIF のフレーム数をチェック
$img = new Imagick($input);
if ($img->getNumberImages() > 1) {
$isAnimatedGif = true;
}
または、
$cmd = sprintf('identify -format "%%n" %s', escapeshellarg($tmpImg));
$frames = (int) trim(shell_exec($cmd));
但し、cwebp が GIF をサポートしている必要がある。
GIF デコーダを含まないビルドであるならば、最適な変換フローは、
JPEG / PNG / WebP → cwebp
静止 GIF → PNG(Imagick)→ WebP(cwebp)
アニメ GIF → gif2webp
また、cwebpでリサイズはできるが、gif2webpではリサイズはできない。アニメgifのリサイズ+WebPへの変換は ffmpeg が使える。
$data = curl_exec($ch);
$byteLength = strlen($data);
echo "Data length in bytes: " . $byteLength;
strlen() はデータを文字列として扱うので、このようなバイナリデータやメモリ内データの場合に便利です。
filesize() は、ファイルのサイズを取得するために設計されているため、ファイル自体が物理的に存在している必要があります。対して、curl_exec() の結果はバッファされたデータであり、直接ファイルとして保存されているわけではないので、filesize() を使用して $data のサイズを取得しようとすると、正常に動作しません。
IP2Location.io
$ch = curl_init('https://api.ip2location.io/?ip=8.8.8.8');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
curl_close($ch);
$api_result = json_decode($json, true);
echo '<pre>';
var_dump($api_result);
echo '</pre>';
APIキーなしでも動作するが、1日あたり1,000件のクエリに制限される。
無料プランに登録するとAPIキーを取得でき、1か月あたり5万件のクエリを利用できる。
// tracking.php
// 訪問データの取得
$ip = $_SERVER['REMOTE_ADDR'];
$page = $_SERVER['REQUEST_URI'];
$time = date('Y-m-d H:i:s');
$referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$user_agent = $_SERVER['HTTP_USER_AGENT'];
// ここでデータベースへの接続および記録処理を行います
try {
$pdo = new PDO('mysql:host=ホスト名;dbname=データベース名', 'ユーザー名', 'パスワード', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$stmt = $pdo->prepare("INSERT INTO access_logs (ip, page, access_time, referrer, user_agent) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$ip, $page, $time, $referrer, $user_agent]);
} catch (PDOException $e) {
error_log("DBエラー: " . $e->getMessage());
}
echo substr('abcdef', 0, 8); // abcdef