▶ 技術めも
PHP 個人的な技術メモ
// array_unique
$arr = array_values(array_unique($arr));
// ファイル追加書き込み
file_put_contents($filePath, $line, FILE_APPEND);
拡張子取得
// 拡張子
pathinfo($fileName, PATHINFO_EXTENSION);
// 小文字化
$lowerExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
$lowerExtension = mb_strtolower(pathinfo($fileName, PATHINFO_EXTENSION), 'UTF-8');
// ファイル名(拡張子なし)
pathinfo($fileName, PATHINFO_FILENAME);
配列 KEY-VALUEを入れ替え
$keyTtpes = array_flip($types);
数字参照文字、HTMLエンティティ変換
$text = html_entity_decode($text, ENT_HTML5);
mb_strimwidth
echo mb_strimwidth("Hello World", 0, 10, '...', 'UTF-8');
strpos
$pos = strpos($mystring, $findme);
preg_match
if (preg_match('/\A[0-9]+\z/', $str)) {
// 数字のみ
}
JSONエンコード
// over PHP5.4.0
$json = json_encode($arr, JSON_UNESCAPED_UNICODE);
$json = json_encode($arr, JSON_PRETTY_PRINT);
$json = json_encode($arr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
ブラウザキャッシュ無効
// ブラウザキャッシュ無効
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
配列キー存在チェック
array_key_exists('first', $searchArray))
引数処理
if (count($argv) !== 2) {
echo '[USED] php program.php {target}'.PHP_EOL;
exit;
}
echo $argv[1];
$isUpdate = false;
if (count($argv) === 2 && $argv[1] === 'UpDaTe') $isUpdate = true;
if (count($argv) !== 2) die('[USED] php program.php {target_tag}'.PHP_EOL);
if (count($argv) !== 2 || $argv[1] !== 'UpDaTe') die("Param Error.\n");
preg_match_all
preg_match_all('/<A>(.*?)<\/A>/', $str, $matches, PREG_SET_ORDER);
Apache ログ出力
error_log('[DEBUG] HOGE FUGA: '.__FILE__.'('.__LINE__.')');
数値文字参照デコード
echo mb_convert_encoding('苆', 'UTF-8', 'HTML-ENTITIES');
CGIパラメータ構築
$params = array( 'param1'=>'aaa', 'param2'=>'bbb', 'param3'=>'ccc');
echo 'index.php?' . http_build_query($params);
index.php?param1=aaa¶m2=bbb¶m3=cc
日付ログファイルパス YYYY/MM/DD
define('LOGFILE_PATH', dirname(__FILE__).'/log/'.date('Y/m/d').'/service.log');
日時 YYYY/MM/DD HH:MM:SS
date('Y/m/d H:i:s')
date('Ymd', strtotime('-1 day', time()))
$date = new \DateTime('2010-10-10 00:00:00');
echo $date->format('U');
複数半角スペース削除
// 両サイドのスペースを消す
$str = trim($str);
// 改行、タブをスペースへ
$str = preg_replace('/[\n\r\t]/', '', $str);
// 複数スペースを一つへ
$str = preg_replace('/\s(?=\s)/', '', $str);
時刻取得
// 01:02:03(時を24時間表記し、2桁ゼロ詰めする場合)
echo date('H:i:s');
// 1時02分03秒(時を24時間表記し、2桁ゼロ詰めしない場合)
echo date('G:i:s:');
エラー表示
PHP
ini_set("display_errors", On);
error_reporting(E_ALL | E_STRICT);
.htaccess
php_flag display_errors On
タイムゾーンの設定
date_default_timezone_set('Asia/Tokyo');
ファイル存在チェック&ファイルオープン
$tmpFile = '/tmp/hogehoge.txt';
if (!file_exists($tmpFile)) {
$fp = fopen($tmpFile, 'w');
if ($fp === false) return false;
fwrite($fp, 'HogeHoge');
fclose($fp);
return true;
}
サーバ名で処理を切り替え(開発機等)
if (strpos($_SERVER["HTTP_HOST"], 'develop.') !== false) {
// 処理
}
IP制限
// 許可IP
$allowIps = array(
'xx.xxx.xxx.xxx',
'xx.xxx.xxx.xxx',
);
// アクセス元IPチェック
if (! in_array($_SERVER['REMOTE_ADDR'], $allowIps)) {
header('HTTP', true, 500);
exit;
}
IP制限 CIDR形式
function inCidr($targetIp, $allowIps)
{
if (empty($allowIps)) return false;
foreach($allowIps as $allowIp){
if (empty($allowIp)) continue;
list($pIp, $maskBit) = explode('/', $allowIp);
$numTarget = ip2long($pIp) >> (32 - $maskBit);
$numAllow = ip2long($targetIp) >> (32 - $maskBit);
if ($numTarget === $numAllow) return true;
}
return false;
}
数値化文字(16進数文字)をデコード
html_entity_decode('『予', ENT_NOQUOTES, 'UTF-8');
XSS対策エスケース関数
function h($text)
{
if (is_array($text)) return array_map('h', $text);
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}
例外ハンドラ(PHP5以降)
例外は、exception_handler がコールされた後に 停止します。
function exceptionHandler($e) {
var_dump($e->getMessage());
}
set_exception_handler('exceptionHandler');
$db = DB::init($config);
$db->setSql('SELECT * FROM ROD_BOOKS WHERE ID IN (:hoge)');
$db->setIn('hoge', array(56,57,58,59,60,41));
$db->exec();
// 明示的な例外発生
throw new Exception('HogeHoge_Error');
STRERRにエラー出力
/**
* エラーハンドラー関数
*/
function exceptionHandler($e)
{
// 標準エラーに出力
$stderr = fopen('php://stderr', 'w');
fwrite($stderr, $e->getMessage());
fclose($stderr);
}
fwrite(STDERR, "An error occurred.\n");
外部プログラムを実行
function execProgram($cmd)
{
unset($arr);
exec($cmd, $arr, $res);
if ($res === 0) return implode(PHP_EOL, $arr); // arr -> text
return false;
}
非同期実行
exec('nohup filename > /dev/null &');
ユーザーが入力したデータを渡すことを許可する場合、escapeshellarg() または escapeshellcmd() を適用する
フォルダ以下PHP構文チェック
find . -type f -name "*.php" -exec php -l {} \;
メール送信
$headers = sprintf("From: %s\n", trim($from));
mb_language('Japanese');
mb_internal_encoding("UTF-8");
mb_send_mail(trim($to), trim($title), $body, $headers);
バッチで Notice でも停止
function strict_error_handler($errno, $errstr, $errfile, $errline)
{
die ("STRICT: {$errno} {$errstr} {$errfile} {$errline} ".PHP_EOL);
}
set_error_handler("strict_error_handler");
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}, E_ALL|E_STRICT);
引数チェック&YAMLファイル読み込み
if (count($argv) !== 2) {
echo 'ARGUMENT ERROR';
exit;
}
$config = yaml_parse_file('config/'.$argv[1].'.yml');
if ($config === false) echo 'yaml_parse_file '.__LINE__;
画像ビーコン(透明GIF 1x1)
$beaconGifData = pack('H*', '47494638396101000100800000ffffff00000021f90401000000002c00000000010001000002024401003b');
header('Content-Length: '.strlen($beaconGifData));
header('Content-Type: image/gif');
echo $beaconGifData;
ヒアドキュメント
print <<< EOF
文字 文字 {$purpose} 文字 文字 文字
EOF;
$string = <<< EOF
文字 文字 {$purpose} 文字 文字 文字
EOF;
BASIC認証のユーザー名取得
$_SERVER['PHP_AUTH_USER']
20バイトのランダム文字生成
substr(md5(uniqid(mt_rand(), true)), 0, 20)
substr(mt_rand(), 0, 8) // 数字8桁
8桁のランダム数字生成
sprintf('%08d', mt_rand()%100000000)
ランダム文字列生成
/**
* ランダムな文字列の生成
*/
function generateRandomString($len = 16)
{
$res = '';
$chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// $chars = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
// $chars = '234578ABDEFGHJLMNPRTUYadefghmnprtuy'; // 見栄え発音
// $chars = '2345789ABDEFGHJLMNPQRTUYadefghmnprtuy'; // 見栄え
for ($i = 0; $i < $len; $i++) {
$res .= $chars[mt_rand(0, strlen($chars)-1)];
}
return $res;
}
オートローダー関数
$h = new Hoge();
↓ 自動でrequire_onceが実行
require_once(__DIR__.'/classes/Hoge.php');
// Autoloader
function __autoload($className)
{
$autoloadPath = array(
__DIR__.'/classes',
);
foreach ($autoloadPath as $path) {
if (file_exists($path.'/'.$className.'.php')) {
require_once($path.'/'.$className.'.php');
return;
}
}
}
md5 を 0〜15 の数字へ変換
$code = substr(md5($str), 0, 1);
if (preg_match('@^[0-9]$@', $code)) {
$code = (int)$code;
} else {
// HASH を 0〜15 のグループ変換
$code = (int)(ord($code) - 87);
}
処理時間の計測
$startTime = microtime(true);
// ほげほげ処理
$endTime = microtime(true);
echo ($endTime - $startTime)." sec\n";
外部プログラム実行
function execProgram($cmd)
{
exec($cmd, $arr, $res);
if ($res === 0) return $arr;
return false;
}
curl リクエスト関数
function requestWeb($url, $timeout)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5); // リダイレクト回数
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // SSL証明書確認無効
$response = curl_exec($ch);
$info = curl_getinfo($ch);
if(curl_errno($ch)) {
curl_close($ch);
return [(int)($info['http_code']), $info['url'], '']; // timeout: code = 0
}
$header = curl_getinfo($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$body = substr($response, $headerSize);
curl_close($ch);
return [(int)($header['http_code']), $info['url'], $body];
}
file_get_contents で POST
/**
* HTTPリクエスト
*/
function execRequest123($url, $body, $appConfig)
{
$headers = ['Content-type: application/json'];
if (! empty($appConfig['headers'])) {
$headers = array_merge($headers, $appConfig['headers']);
}
if (empty($body)) {
$method = 'GET';
$body = '';
} else {
$method = 'POST';
}
$opts['http'] = [
'method' => $method,
'header' => implode("\r\n", $headers),
'content' => $body,
];
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);
}
ロック処理
$lockFile = '/tmp/deploy_lock.txt';
// ロック
if (! @symlink(__FILE__, $lockFile)) {
echo 'Locked: '.$lockFile.PHP_EOL;
exit(0);
}
// 排他実行プログラム
unlink($lockFile); // ロック解除
exit(0);
実行中からバックグラウンド
# Ctrl+Zで中断
bg 1
jobs 1
disown %1
`
アンカー要素を上にずらす
<h1> <span id=“no1” class=“anchorlink"></span>タイトル</h1>
アンカーをつけたい場所にspanで挿入。
@media only screen and (min-width:760px){
span.anchorlink {
position: relative;
top: -120px;
display: block;
}
}
IteratorAggregate
// @see http://hensa40.cutegirl.jp/archives/2307
class ClassName implements \ArrayAccess, \IteratorAggregate
{
// ArrayAccess
public function offsetSet($key, $value)
{
$this->set($key, $value);
}
public function offsetExists($key)
{
return $this->has($key);
}
public function offsetGet($key)
{
return $this->get($key);
}
public function offsetUnset($key)
{
$this->delete($key);
}
// IteratorAggregate
public function getIterator()
{
return new \ArrayIterator($this->data);
}
}
class HOGE implements \ArrayAccess
{
//オフセットが存在するかどうか
public function offsetExists($offset) {
return property_exists(get_called_class(), $offset);
}
//オフセットを取得する
public function offsetGet($offset) {
if ($this->offsetExists($offset)) {
return $this->$offset;
}
return null;
}
//オフセットを設定する
public function offsetSet($offset, $value) {
$this->$offset = $value;
}
//オフセットの設定を解除する
public function offsetUnset($offset) {
$this->$offset = null;
}
}
リストの1行毎処理
cat list.txt | while read line; do cp "${line}" .; done
find ./hoge -type f | xargs -t -I %% cp %% .
URLリクエスト
cat request.txt | xargs -n1 -P10 -I %% curl %% -s -o /dev/null -w "%{http_code}\t%%\n" | tee sample.log
多重起動防止 crontabワンライナー
* * * * * /usr/sbin/pidof -x job.sh >/dev/null || /path/to/your/job.sh
警告表示
$this->showAttention('◯◯しますか?[Y/n]');
$stdin = trim(fgets(STDIN));
if ($stdin !== 'Y') return false;
private function showAttention($str)
{
echo "\033[41m".$str."\033[0m".PHP_EOL;
}
PHPのハマりポイントまとめ
https://qiita.com/suin/items/3a6780bb56d740eecd10