textareaの入力文字数によって高さを可変にする

こういうやつ

コード

<textarea></textarea>
<script>
  const textarea = document.querySelector('textarea');
  textarea.addEventListener('input', () => {
    textarea.style.height = null;
    textarea.style.height = `${textarea.scrollHeight}px`;
  });
</script>

改行の数をカウントしてtextareaのrowsに入れたりしたけど, それだと文字の折返しのときに高さが取れなかったのでtextareaのスクロール量を高さに入れるようにした

実際使うときは高さの上限決めた方がいいかも

LINEスタンプ作ったときの備忘録

直近死んだ犬2匹を素材にしてLINEスタンプを作りました。

store.line.me

store.line.me

これでトークの中でレオンとネネは生き続ける。嬉しい。
一気に2匹も死んでペットロス半端なかったけどこれで少しは緩和されるといいな

多分またいつか作るから備忘録というか忘れそうな部分をまとめておきます


作り方

[方法1] LINEスタンプメーカーを使って作る

creator.line.me 風呂でスマホ触っててスタンプ作ろうってなったときにこれにたどり着きました。
作成〜申請までスマホで1Hちょっとで作れたけど、写真素材の透過が甘かったり用意されてるステッカーがダサいあらかじめ決められてるから自由度は低いと思います。

[方法2] LINEクリエイターズマーケットを使って作る

自分でスタンプ素材を作ってWeb上で申請する方法。
LINEスタンプメーカーで作ったものが気に入らなくて作り直したときに使いました。
Photoshopなどのフォトエディタツールで作ったスタンプ素材をLINEクリエイターズマーケットに登録して、必要情報を入力して申請しました
スタンプ素材は自分の好きなように作れるけど、LINEスタンプメーカーよりは申請までの入力項目が多いので手間だと思います。

申請から承認までの時間

LINEスタンプメーカーとLINEクリエイターズマーケットの両方とも22時とか23時に申請して翌日の13~15時頃には結果が来ていました。

申請がリジェクトされた。再申請から承認までの時間は?

LINEスタンプメーカーで申請したときは一発で承認されたけど、LINEクリエイターズマーケットで申請したときはリジェクトされました。
販売情報のテキストに不備があったので修正して、その日のうちに再申請したら5時間後くらいには承認されました。
リジェクトされたらメッセージセンターに理由が書いてあるのでその通り修正して再申請すれば承認されると思います。

表示情報や販売情報の入力不備に関しては、LINEスタンプメーカーだとアプリが適当にやってくれるのでよっぽど不適切な文字列を入れない限り、リジェクトされる可能性は低いと思う。

承認されたけどリリースされない

承認されたらLINEクリエイターズマーケットのアイテム管理画面の右上らへんに赤いリリースボタンが表示されます。
リリースボタンを押すことでリリースが完了します。
LINEスタンプメーカーのときは忘れた。

リリースしたけど購入用URLに反映されない

5~10分くらい待てば反映されます。

スタンプのタグはなにを設定すればいいの?

特にこだわりがなければ何も設定しなくていいと思う。
設定した場合はLINEのトーク画面で文字入力時にサジェストとしてスタンプが出てくる。
設定しなかった場合はリリース後の2,3日後にLINE側で適当につけてくれる。
再申請は必要になっちゃうけど後日つけられたタグを確認して、このタグ違うなってものがあれば修正すればいい。

売上分配金が入らない

LINEスタンプメーカーで作るとデフォルトで売上分配金なしになってます。
申請前に絶対に確認しよう!
ちゃんと読んでない自分も悪いけどこれ罠だと思う。せめてデフォルト未選択にしてほしいっす…

制作ガイドラインについて

スタンプの制作ガイドラインに以下の記載があります。

トリミングされた画像の外枠とコンテンツの間には10pxぐらいの余白が必要です。画像をつくるときは上下左右のバランスに注意してください。

ガイドラインを一通り読んだ上で自分はこれをガン無視しました。余白なしで外枠ギリギリまで素材を設置しました。
リジェクトされたときに「あーやっぱりか」って思ったけどリジェクトの理由は前述の通り、販売情報のテキストの不備だったので関係ありませんでした。
これ実際どうなんだろう?みんな守ってるのかな?写真スタンプだと関係ないとかある?

使用したツール

LINEクリエイターズマーケットでのスタンプ作成時に以下のツールを使用させていただきました。
ありがとうございました。

medibangpaint.com

lightbox.on.coocan.jp

fukidesign.com

apngasm.sourceforge.net

※本記事に記載されている内容は2022/02/06時点のものです。

hoverでbackground-imageを切り替えたときの画像のチラつきが気になる

↓これのこと*1

なんでチラつくの?

レンダリングのときは読み込まれなくて、hoverのときに初めて画像を読み込んでるから
Networkタブを見てみるとhoverのタイミングで読み込んでるのがわかる

対応策

① preloadで読み込んでおこう

headタグの中にpreloadを指定する

<link rel="preload" href="./images/hover.png" as="image">

あらかじめ読み込んでくれてるので初回hoverでもチラつかない!

preloadって何?

指定したリソースを先に読み込むようにブラウザに指示すること
imageの他にもstyleやscriptなども指定できる
詳しくはMozilla先生に聞いてね developer.mozilla.org

② background-imageにhoverの時の画像も指定しよう

hoverしたときじゃない方のbackground-imageにhoverしたときの画像も指定して非表示にしておく

button {
    background-image: url(./images/normal.png), url(./images/hover.png);
    background-size: contain, 0; // 2枚目はsizeを0にしておく
    &:hover {
        background-image: url(./images/hover.png);
    }
}

(環境によるのかもだけど)preload指定してNetworkタブで事前に読み込まれてるのも確認してるのに、何故かチラつくことがあるので②のほうが確実だと思う

感想

正直俺は気にならん


*1:チラつかないときはブラウザキャッシュを削除してみてください

PHPUnit で作成したテスト項目をHTMLで出力する

PHPUnit--log-junit オプションでxmlを出力する

# ./vendor/bin/phpunit tests/Feature/SampleControllerTest.php --log-junit output.xml
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.901, Memory: 24.00 MB

OK (1 test, 1 assertion)

xsltproc を使用して html に変換する

# xsltproc phpunit.xslt output.xml > output.html 

(※ xsltproc コマンドがない場合は別途インストールする。Macにはデフォルトで入ってるはず。。)
出力用のテンプレ(phpunit.xslt)は以下よりDL

PHPUnit xslt · GitHub

htmlが出力されていることを確認
テンプレを変えたい場合は phpunit.xslt を任意で修正すればOK

参考

https://phpunit.readthedocs.io/ja/latest/textui.htmlphpunit.readthedocs.io

inokara.hateblo.jp

qiita.com


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。


Markdown でリストの中にコードブロックを含めると連番がリセットされる

問題

下記のようにリストの中にコードブロックが含まれる場合、リスト3 の番号が1になってしまう。

Markdown

1. リスト1
1. リスト2

\```php
<?php echo 1; ?>
\```
1. リスト3

*1

実際の表示

  1. リスト1
  2. リスト2
<?php echo 1; ?>
  1. リスト3

解決策

リスト内のコードブロックにインデントを設定しよう!

Markdown

1. リスト1
1. リスト2

   ```php
   <?php echo 1; ?>
   ```
1. リスト3

実際の表示

  1. リスト1
  2. リスト2

    <?php echo 1; ?>
    
  3. リスト3

※コードブロック前に3スペース入れています。

*1:※バックスラッシュはphpのコードブロックが親コードブロックの終了とみなされてしまうため入れています。

Mac で撮ったスクショの影を削除する

Mac でアプリケーションウィンドウ全体のスクショを撮ったときの影、邪魔じゃねって思ったときの備忘録

defaults write com.apple.screencapture disable-shadow -boolean true

Before

f:id:IlIIlIIIlIIlI:20211231143500p:plain

After

f:id:IlIIlIIIlIIlI:20211231143613p:plain


影ありに戻したいときはfalseにすればOK

defaults write com.apple.screencapture disable-shadow -boolean false

Mac に Xdebug をインストールして VSCode でデバッグする

経緯

ちょっとしたサンプルプログラムをホストマシンで試すときに、いつも var_dump() デバッグ使ってたけどちょっとしたサンプルプログラムだろうが何だろうが Xdebug 使ったほうがもっと楽になるよね、ハム太郎

手順

Debug Buildno になっていることを確認

$ php -i | grep 'Debug Build'
Debug Build => no

ついでに Xdebug がインストールされていないことも確認

$ php -m | grep xdebug

何も表示されなければOK

Xdebug のインストール

  1. 下記のダウンロードサイトから Xdebug をDLする。
    http://www.xdebug.org/download.php
    ※どのversionをDLすればいいかわからない場合は $ php -i | pbcopy を下記にペーストして調べる。
    https://xdebug.org/wizard
  2. 解凍して任意のディレクトリに移動

     $ tar -zxvf ~/Downloads/xdebug-xxx.tgz && mv ~/xdebug-xxx ~/{任意のディレクトリ} && cd ~/{任意のディレクトリ}/xdebug-xxx
    
  3. xdebug-xxx ディレクトリにいる状態で以下を順に実行していく

     $ phpize  
     $ ./configure  
     $ make  
    

    完了したら modules ディレクトリに xdebug.so があることを確認する
    ない場合はどこかの手順でエラーが出ているはずなので随時解消する

  4. php.ini の修正

    php.iniの場所を確認

     $ php --ini
     Configuration File (php.ini) Path: /opt/homebrew/etc/php/7.4
     Loaded Configuration File:         /opt/homebrew/etc/php/7.4/php.ini
     Scan for additional .ini files in: /opt/homebrew/etc/php/7.4/conf.d
     Additional .ini files parsed:      /opt/homebrew/etc/php/7.4/conf.d/ext-opcache.ini
    

    xdebug.so までのフルパスを追記

     zend_extension={xdebug.so までのフルパス}
    
  5. Xdebug が有効になっていることを確認する

     $ php -m | grep xdebug
     xdebug
    

    xdebug が表示されればOK

VSCodeの設定

  1. 拡張機能 PHP Debug をインストールする
    VSCode拡張機能php debug で検索、もしくは下記よりインストールする
    https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug
  2. プロジェクト直下に .vscode/launch.json を作成する
    ⌘ + Shift + D でデバッグメニューを表示すると初回は launch.json を作る、みたいなリンクがあるのでクリックする
    プロジェクト直下に .vscode/launch.json が作成されることを確認
  3. php.ini にconfigurations.portの番号を指定

     zend_extension={xdebug.so までのフルパス}
    
     [PHP]
     xdebug.mode=coverage,develop,debug
     xdebug.discover_client_host=1
     xdebug.client_port=9003 ; .vscode/launch.json の configurations.port の値を貼り付ける
     xdebug.start_with_request=yes
    

    Xdebug2と3で設定値の名前が結構変わっているのでversionごとの違いは下記を参照

    xdebug.org

確認

適当なプログラムにbreakpointを設定して止まればOK

参考

xdebug.org

qiita.com

www.aiship.jp


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。


Laravel でアクセストークンを header に含むときのAPIのテストを書く

f:id:IlIIlIIIlIIlI:20220129185719p:plain

いつ使うの?

  • SPAではないプロジェクト(アクセストークンの取得タイミングがMPAでのログイン時)
  • 一部画面でアクセストークンを含むAPIを叩いている

コード

<?php

use Tests\TestCase;

class SampleControllerTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();

        // ログイン処理
        $res = $this->post('/login', [
            'email' => 'hoge@example.jp',
            'password' => 'password'
        ]);
        // 取得したアクセストークンをプロパティに格納
        $this->accessToken = $res->baseResponse->getSession()->get('access_token');
    }

    public function testAPIリクエスト()
    {
        // プロパティに入っているアクセストークンを使用してリクエスト
        $res = $this->post('api/hoge', ['product_id' => 1], ['Authorization' => 'Bearer ' . $this->accessToken]);

        $res->assertOk()->assertJson(['succeeded' => true]);
    }
}

要点

  • setUp() 時にアクセストークンの発行処理を実施し、プロパティにアクセストークンを入れておく
  • テストの時にプロパティに入っているアクセストークンを含めてリクエストの発行をする
  • アクセストークン取得時のリクエストはAPIのエンドポイントではないのでアクセストークン自体は \Illuminate\Http\Response が入っている baseResponse から取得する
    • API経由で取得する場合は $res->json($key) で取得できるっぽい(未検証)
      (※decodeResponseJson()の引数にkeyを指定して取得できてたみたいだけどLaravel8からは引数を取らないみたい)

github.com

readouble.com

qiita.com


Laravel で画像をアップロードする Controller のテストを書く

Laravel で画像アップロードのController周りのテストを書いたことがなかったので備忘録

<?php

use Tests\TestCase;
use Illuminate\Http\UploadedFile;

class SampleControllerTest extends TestCase
{
    public function test画像アップロードができる()
    {
        $res = $this->post('image/upload', ['images' => UploadedFile::fake()->image('hoge.jpg')]);

        $res->assertRedirect('image/upload/completed');
        $res->assertSessionHas('success', 'アップロードに成功しました。');
    }
}

UploadedFile facadeのfake()を使えばOK
勝手に面倒くさそうと思ってたけどめちゃめちゃ簡単だった👌

readouble.com


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。

親のチェックボックスに紐付けたチェックボックスを全てチェックする

親のチェックボックスのチェック状態を親に紐付けた子供のチェックボックスにも反映させたい
↓こういうやつ

これをピュアJSで書いたときの備忘録

コード

解説

HTML

  1. チェックボックスに子供を紐付ける用のカスタムデータ属性(data-id="1")をつける
    (親であることを判別できるのであればclass名などで管理してもOK)
<label>親チェック1<input type="checkbox" data-id="1" class="check-parent"></label>
  1. 親に紐付ける子供となるチェックボックスに親のid(data-parent-id="1")を紐付ける
<label>親1子供1<input type="checkbox" data-parent-id="1"></label>

JavaScript

  1. 親となるチェックボックス要素のchangeイベントをループ処理で実施する
  2. 親のdataset.idに紐付いている子供の要素を取得して, ループ処理で親のチェック状態を子供のチェック状態と同じにする
Array.from(document.querySelectorAll('.check-parent')).map(checkParent => {
  checkParent.addEventListener('change', () => {
    Array.from(document.querySelectorAll(`[data-parent-id="${checkParent.dataset.id}"]`)).map(checkChild => {
      checkChild.checked = checkParent.checked
    })
  })
})

Carbon の diffInDays() は時間まで見ている

みんな大好きCarbonで対象日が今日の何日後かを知りたいときに, 想定していた挙動と違っていたのでメモ

対象日が本日の何日後かを知りたい

2021-11-15が本日(2021-11-14)の何日後かを知りたいとき

>>> now()->diffInDays(Carbon\Carbon::parse('2021-11-15'))
=> 0

期待値は1だったけど, 0が返ってきた

実装を見てみる

Carbon\Traits\Difference を見てみると, 継承元の DateTime クラスの diff() を見に行ってたので DateTime での挙動も確認してみる

>>> (int) (new DateTime())->diff(new DateTime('2021-11-15'))->format('%r%a')
=> 0

(※ intへのcastとformat()はCarbon準拠)

(当たり前なんだけど)同じく0が返ってくる

現在時刻の時間を指定してみる

>>> now()->setTime(0, 0)->diffInDays(Carbon\Carbon::parse('2021-11-15'))
=> 1
>>> (int) (new DateTime())->setTime(0, 0)->diff(new DateTime('2021-11-15'))->format('%r%a')
=> 1

期待値の1が返ってきた。

対応策

現在時刻と対象日時の日付だけを考慮してdiffを取りたいときは現在日時刻の時間もセットしよう!

感想

DateTime クラス関してはdiffっていう命名からしてまっとうな挙動だと思うんだけど, Carbon のdiffInDays命名ややこしすぎ
日時を指定されても日数のdiff返せや(横暴)
ちなみに自分は Laravel 触るまでCarbonの存在知らなかったマンです。

※実際のコードにはImmutableクラス使おうね


github.com


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。


PHPで半角数字を漢数字の単位付きの表記に変換したい

f:id:IlIIlIIIlIIlI:20211107203557p:plain

53000053万みたいに漢数字の単位を付けたかった。
タイトルに漢数字って書いてあるから詐欺ってるみたいだけど五三万への変換は今回はやりません。🙇🏿‍

早速コード

<?php

function convert($value) {
    // 1000以下の場合は単位を付けずに返却
    if ((int) $value < 1000) {
        return (string) $value;
    }

    $units = ['', '万', '億', '兆', '京'];

    // 右から桁数を分割していく
    $splits = array_reverse(str_split(strrev($value), 4));

    // 桁数によって使用する単位の調整
    array_splice($units, count($splits));
    $filterUnits = array_reverse($units);

    $convert = '';
    // 反転した数値を元に戻して単位をつける
    foreach ($splits as $index => $split) {
        // 0000の場合、表記を省略する
        $convert .= (int) $split === 0 ? '' : number_format(strrev($split)) . $filterUnits[$index];
    }

    return $convert;
}

assert('私の戦闘力は53万です。' === '私の戦闘力は'.convert('530000').'です。'); // true

感想

  • 単位が飛ぶ時の表記をどうしようか迷ったけど, 単位が0000の場合は省略するようにした。
    (100000001の場合, 1億0000万0001ではなく1億1の表記になる)
  • 反対に, 漢字(53万) → 半角数字(530000)に変換するのも考えたけど, 意外とやることが多くて諦めた。
    必要に迫られたらやる。(やらないフラグ)
  • 漢字単位への変換前に文字列に変換すれば京以上の単位も付けれるんだろうけど, お金周りの変換がしたかっただけだから考慮してない。PHP_INT_MAX を超過する数値を扱いたい人はこっち来ないで😭😭😭
  • 全体的にトリッキーなので誰か別の方法ご存知でしたらご指摘ください🙏🏻
  • JSでやったほうが需要ありそう

github.com

packagist.org



ブラウザの Console をタイマー代わりに使う

電卓使いたいときにブラウザの Console 使う人間なので、タイマーも Console で完結させたかった

1秒ごとに Console に秒数を表示する

let sec = 0;
const intervalId = setInterval(() => {
  ++sec;
  console.log(sec);
}, 1000);

特定の秒数になったらカウントを停止する

let sec = 0;
const intervalId = setInterval('countSec()', 1000);
const countSec = () => {
  if (sec === 5) {
    clearInterval(intervalId);
    alert(`${sec}秒が経過しました。`);
    return;
  }
  ++sec;
  console.log(sec);
}

特定の秒数になったら、ダイアログを押すまで通知音を鳴らす

let sec = 0;
const intervalId = setInterval('countSec()', 1000);

const audio = new AudioContext();
const oscillator = audio.createOscillator();
oscillator.type = 'sign'
oscillator.connect(audio.destination);

const soundStart = () => {
  oscillator.start();
}
const soundStop = () => {
  oscillator.stop();
}

const countSec = () => {
  if (sec === 5) {
    clearInterval(intervalId);
    soundStart();
    alert('タイマーを止める。');
    soundStop();
    return;
  }
  ++sec;
  console.log(sec);
}

いつ使うの?

PCがネットに繋がらない状況でカップ麺を作らなければならないとき

感想

こんなん書くくらいだったら普通にタイマーアプリ使うわ
最低限通知音は必須だけど毎回書いとれん😊

もっと簡潔に書ける方法あったら誰か教えて下さい 🙏🏻

Bootstrap を使ってテーブルの行をクリックした時にコンテンツを展開したい

テーブルの各行をクリックした時に行の下にコンテンツを表示する。
一覧に表示する列数が多いけど横スクロールしたくないときに使う。

tr > td の中に div を書いてたりするのでマークアップ警察は見るな

要点

① クリックする行の tr タグに開閉トリガーをつける

<tr data-toggle="collapse" data-target="#collapse-1">

② クリックする行の tr タグの直下に tr > td でラップした開閉コンテンツを設置する
td 要素は1つだけにして, 開閉トリガーの列数分の colspan で結合する

<tr>
    <td colspan="4" class="p-0">
        <div class="collapse" id="collapse-1">
            <p>開閉コンテンツ</p>
            <p>
                親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)
            </p>
        </div>
    </td>
</tr>

感想

個人的にはあまり好きなUIではないので必要に迫られた時以外使いたくない🤔

Laravel で ORDER BY を複数指定する

Laravel で SELECT * FROM samples ORDER BY column1 DESC, column2 ASC みたいに ORDER BY を複数指定したい場合の書き方

<?php
App\Models\Sample::orderBy('column1', 'desc')->orderBy('column1', 'asc')->get();

もしくは

<?php
App\Models\Sample::orderByDesc('column1')->orderBy('column1')->get();

何故か毎回連想配列でできると思いこんでApp\Models\Sample::orderBy(['column1' => 'desc', 'column1' => 'asc'])->get();みたいに書いてはエラー→ググる→修正のループを繰り返してたけどこれで覚えるだろ。。。

参考

readouble.com