かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

TwiPla から参加者のリストを CSV でダウンロードするやつ作った

Twitter アカウントでイベントとか合同の募集できる TwiPla で参加者が多いと連絡とか進捗管理など大変になるので参加者のリストをサクッとCSV でダウンロードできると便利だよな〜と思い昔スクリプトを描いていたのでこちらにもメモとして残しておきます

TwiPla のイベントページから参加者・興味あり・不参加ユーザーのリストを CSV としてダウンロードできるスクリプト

⚠ TwiPla / ブラウザの仕様が変わると動作しなくなる可能性があります

gist.github.com

動作確認

使い方

  1. TwiPla のイベントページで dev tool を開きコンソールのタブを開く
  2. このスクリプトまたは下記のminifiされたコードをコピーしてコンソールのタブに貼り付けてエンター
const listElement=".member_list",userElement="a.namelist",getDate=()=>{let e=new Date;return`${e.getFullYear()}-${e.getMonth()}-${e.getDay()}-${e.getTime()}`},getUserData=e=>{let t=e.getAttribute("title");return[e.getAttribute("n"),t,`https://twitter.com/${t.replace("@","")}`]},getUsersList=()=>[...document.querySelectorAll(".member_list")].reduce((e,t)=>[...e,[t.firstChild?.data],...[...t.querySelectorAll("a.namelist")].map(getUserData),],[]),downloadCSV=e=>{let t=new Blob([e.map(e=>e.join(",")).join("\n")],{type:"text/csv"}),l=`${document.title}_${getDate()}.csv`,r=(window.URL||window.webkitURL).createObjectURL(t),a=document.createElement("a");a.download=l,a.href=r,document.body.appendChild(a),a.click(),document.body.removeChild(a)};(()=>{let e=["userName","twitterId","twitterLink"];downloadCSV([e,...getUsersList(),])})();
  1. CSV ファイルがダウンロードされる

ちょっとだけポイントの説明

自動で CSV をダウンロードさせるために Blob でファイルオブジェクトを作成して、createElement で作成した a タグの href に指定、ダウンロードされるファイル名は .download 属性で指定する。作成した a タグを document に追加してしまって .click() を発火させることでユーザーが a タグをクリックした体でダウンロードが始まる。
スクリプトで勝手にダウンロードさせられるのでそのうちセキュリティの仕様が変わると使えなくなりそうな気もしてるけど、2022-02-22 現状はこの方法で自動ダウンロードさせることができる

おわり ₍ ᐢ. ̫ .ᐢ ₎


これからもずっと アイカツ!

PHP 文字列中に変数で値を埋め込むやつのメモ

"Hello, xxxx!": "こんにちは、xxxxさん!" みたいな key-value で翻訳テキストを出せる機能を作っていて PHP で既定の文字列に変数を埋め込む方法を何パターンかやってみたのでメモ

sprintf ・ vsprintf

所謂文字列のフォーマットに使うメソッドを利用する方法
既定の文字列で可変な部分に %s を埋め込んでおいて出力時にこの関数を噛ませれば良い

sprintf は変換する値を可変長引数を取れるので置き換える箇所が複数あっても問題ない

<?php
$str = "Hello, %s!";
echo sprintf($str, 'Ichigo');
// => "Hello, Ichigo!"

$str = "Hello, %s!, Hi, %s.";
echo sprintf($str, 'Aoi', 'Ran');
// => "Hello, Aoi!, Hi, Ran."

vsprintf は変換する値が可変長引数ではなく配列で渡すだけ

<?php
$str = "Hello, %s!";
echo vsprintf($str, ['Akari']);
// => "Hello, Akari!"

$str = "Hello, %s!, Hi, %s and %s!!";
echo vsprintf($str, ['Otome', 'Sakura', 'Shion']);
// => "Hello, Otome!, Hi, Sakura and Shion!!"

シンプルに変換できるし、%02d などでフォーマットも可能。(単数形と複数形のフォーマットもできれば完璧なのだけど…)
一方デメリットとしては、置換したい箇所が複数ある場合に値の渡す順番を正しく合わせる必要がある点。変換箇所が多いとどの値がどこに入るのか見通しが悪い点。

strtr

Laravel の翻訳関数調べてた際に存在を知った文字の変換・部分置換を行うためのメソッド

第1引数に変換する文字列を渡し第2引数に ['from (変換する文字)' => 'to (置換する文字)'] の配列を渡す。第2引数に from、第3引数に to を渡す方法もあるが配列を渡す方が効率が良さそう

次の例は、引数を二つだけ指定して strtr() をコールしたときの挙動を示すものです。置換の優先度 ("h" よりもっと長いキーに一致しているので、この置換は行われていないこと)、 そして一度置換した文字列はもう置換の対象にならないことを確認しましょう。
cf. PHP: strtr - Manual

<?php
$trans = array("h" => "-", "hello" => "hi", "hi" => "hello");
echo strtr("hi all, I said hello", $trans);
// => hello all, I said hi

一度変換した文字列は再変換されないのも便利!

Laravel の国際化メソッドのように使える

<?php
$str = ":unit は :name1, :name2, :name3 からなるユニットです!";
echo strtr($str, [
  ":unit" => "Soleil",
  ":name1" => "星宮いちご",
  ":name2" => "霧矢あおい",
  ":name3" => "紫吹蘭",
]);
// => "Soleil は 星宮いちご, 霧矢あおい, 紫吹蘭 からなるユニットです!"

echo strtr($str, [
  ":unit" => "Tristar",
  ":name1" => "神崎美月",
  ":name2" => "藤堂ユリカ",
  ":name3" => "一ノ瀬かえで",
]);
// => "Tristar は 神崎美月, 藤堂ユリカ, 一ノ瀬かえで からなるユニットです!"

echo strtr($str, [
  ":unit" => "Luminas",
  ":name1" => "大空あかり",
  ":name2" => "氷上すみれ",
  ":name3" => "新条ひなき",
]);
// => "Luminas は 大空あかり, 氷上すみれ, 新条ひなき からなるユニットです!"

べんり!!! strtr は何を何に置換するのか分かりやすいのが良いな!と感じました。

まとめ

  • フォーマットも行いたいときは sprintf vsprintf を使う
  • 文字列中の置換をわかりやすく行いたいときは strtr を使う

のが良さそうかなと思いました!
おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]

PHP 文字列中変数展開に関数は使えない?

PHP の文字列中変数展開が奇妙だったのでメモ

環境

PHP v8.2

変数展開

" (ダブルコーテーション)中に {$変数} で変数展開が出来る

<?php
$name = 'Ichigo';
echo "Hello, {$name}!";
// => "Hello, Ichigo!"

定数は展開できない

<?php
define("ICHIGO", "Ichigo");
echo "Hello, {ICHIGO}!";
// => "Hello, {ICHIGO}!"

定数はそのまま出力される

関数も展開できない

<?php
function name() { return 'Ichigo'; }
echo "Hello, {name()}!";
// => "Hello, {name()}!"
echo "Hello, {strtoupper('ichigo')}!";
// => Hello, {strtoupper('ichigo')}!

JSX や JavaScript のテンプレートリテラルみたいに関数を書いても文字列として出力されてしまう

関数を実行する変数なら展開できる!

<?php
$_s = fn(string $s): string => $s;

// 文字列を返す関数を引数にしてしまえばOK
echo "Hello, {$_s(strtoupper("ichigo"))}!";
// => "Hello, ICHIGO!"

// 定数もOK
define("ICHIGO", "Ichigo");
echo "Hello, {$_s(ICHIGO)}!";
// => "Hello, Ichigo!"

仕様がぽわぷりぃ〜
おわり


[参考]