お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。
投稿日:
言語::PHP

あると何かと便利だよねというので。

確認環境

Env Ver
PHP 8.0.29

サンプルコード

取り敢えずファイルをアップロードするだけのコード

<?php
if ($_FILES['image']) {
    move_uploaded_file($_FILES['image']['tmp_name'], 'files/'. $_FILES['image']['name']);
} else {
?>
<html>
<body>
<form action="upload.php" enctype="multipart/form-data" method="POST">
    <input type="file" name="image">
    <button>upload</button>
</form>
</body>
</html>
<?php
}
投稿日:
言語::PHPミドルウェア::RDBMS::SQLite

"hoge", "piyo", "fuga"のように綺麗なCSVであるという前提。CSVファイルが巨大なので行読み込みする。

<?php

$db = new PDO('sqlite:./hoge.db');

$db->beginTransaction();
$fp = fopen("hoge.csv", "r");
$idx = 0;

if($fp){
  while ($line = fgets($fp)) {
    $row = createRow($line);
    $db->exec(
      'INSERT INTO hogehoge (`foo`, `bar`, `baz`)'
      . ' VALUES '
      .'(' . '"' . $row['foo'] .'", ' . '"' . $row['bar'] .'", ' . '"' . $row['baz'] .'"' . ')'
    );
    $idx++;
    echo $idx . "\n";
  }
}

fclose($fp);
$db->commit();

function createRow($text) {
  $r1 = preg_replace('/"/', '', $text);
  $row = explode(',', $r1);

  return [
    'foo' => $row[0],
    'bar' => $row[1],
    'baz' => $row[2],
  ];
}

トランザクションを張りっぱなしだが、exec毎にトランザクションを張りなおすと劇的に遅くなるのでやめたほうがいい(恐らく毎回同期処理でWriteが走っているのだと思う)

投稿日:
技術::プロトコル::HTTP言語::PHPNode.js::その他

動機としてはcurlだと見えない部分があるので、自分でHTTPメッセージを手組みして送ってみたかった。

Node.jsとPHPのサーバーでリクエストが期待通り取得できたので、メッセージの実装としては問題ないと思われる。

検証用サーバー

以下のコードをNode.js v20.11.1を用いて検証

import http from 'node:http';

http
  .createServer((req, res) => {
    console.log(req.headers);
    req.on('data', (chunk) => {
      // body
      console.log(Buffer.from(chunk).toString());
    });
    res.statusCode = 200;
    res.end();
  })
  .listen(9999);

netcatコマンドによるリクエスト検証

GETリクエスト

echo -e 'GET / HTTP/1.1\r\nHost: localhost:9999\r\n\r\n' | nc localhost 9999

POSTリクエスト

echo -e 'POST / HTTP/1.1\r\nHost: localhost:9999\r\nContent-Length: 4\r\n\r\nhoge' | nc localhost 9999

備考

PHPで検証サーバーを作る場合

実際にAPサーバーでリクエストの中身をパース出来るかどうかの観点で見た場合にNode.jsよりPHPのが楽なので、PHPで作ってみた結果、軽くハマったので残しておく。

以下のコードを用いてPHP 8.0.29で検証サーバーを作る場合に、php -S 0.0.0.0:9999としてサーバーを起動すると、Content-Typeヘッダがない場合に正常な動作をしなかった。

<?php

var_dump($_SERVER);
var_dump($_REQUEST);

ncで検証サーバーを作る場合

デバッグ用。生のメッセージが見れるのでダンプしてdiffを取るなどでcurlとecho + ncの差分を見るのに使える。

nc -l 9999

HTTPメソッド名を非標準的なものにした場合の挙動

前述のNode.jsサーバーでは400 Bad Request、PHPサーバーでは501 Not Implementedが応答された。

確認環境

Env Ver
OS Ubuntu 20.04.4 LTS
PHP 8.0.29
nginx 1.18.0

手順

php-fpmの導入

sudo apt install php8.0-fpm
sudo sed -i -e 's/;listen.mode = 0660/listen.mode = 0666/' /etc/php/8.0/fpm/pool.d/www.conf
sudo service php8.0-fpm start

nginxの設定

設定ファイルを開きPHPを動かす設定を書く

location ~ ^/.*$ {
  root /path/to/www;
  fastcgi_pass unix:/run/php/php8.0-fpm.sock;
  fastcgi_index index.php;
  include fastcgi_params;
  fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
}

Web開発をしていると取り敢えずHTTPリクエストが取れる雑なモックサーバーが欲しくなることがあるので、その作り方。

確認環境

Env Ver
OS Windows 11 Pro
WSL2 -
Distoribution Ubuntu 20.04.4 LTS
PHP 8.0.29
nginx 1.18.0

作り方

  1. Windows側の hosts127.0.0.1 mock-server.test を追加
  2. /etc/nginx/conf.d に以下の設定ファイルを置く
server {
  listen       80;
  client_max_body_size 100m;
  server_name  mock-server.test;
  access_log   /var/log/nginx/mock-server.access.log;
  error_log    /var/log/nginx/mock-server.error.log;


  location ~ ^/.*$ {
    rewrite ^/.*$ / break;
    # リクエストパスの確認用
    proxy_set_header X-Request-Path $request_uri;
    proxy_pass  http://127.0.0.1:8888;
  }
}
  1. sudo service nginx restart
  2. モックサーバーのコードを書いて適当な場所に置く
<?php

$server_json = json_encode($_SERVER);

file_put_contents('log', "$server_json\n", FILE_APPEND);
  1. php -S localhost:8888
  2. http://localhost:8888/hoge にアクセスしログファイルに追記されることを確認
  3. おわり

おまけ

$_SERVER の中身をフィルタしたい時

<?php

$ignoreKeys = [
    'DOCUMENT_ROOT',
    'REMOTE_ADDR',
    'REMOTE_PORT',
    'SERVER_SOFTWARE',
    'SERVER_PROTOCOL',
    'SERVER_NAME',
    'SERVER_PORT',
    'REQUEST_URI',
    'SCRIPT_NAME',
    'SCRIPT_FILENAME',
    'PHP_SELF',
    'HTTP_HOST',
    'HTTP_CONNECTION',
    'HTTP_UPGRADE_INSECURE_REQUESTS',
    'HTTP_USER_AGENT',
    'HTTP_ACCEPT',
    'HTTP_ACCEPT_ENCODING',
    'HTTP_ACCEPT_LANGUAGE',
    'HTTP_CACHE_CONTROL',
    'REQUEST_TIME_FLOAT',
    'REQUEST_TIME'
];

$buff = array_filter($_SERVER, function($key) use($ignoreKeys) {
    return !in_array($key, $ignoreKeys);
}, ARRAY_FILTER_USE_KEY);

$server_json = json_encode($buff);

file_put_contents('log', "$server_json\n", FILE_APPEND);