LaravelでCSVのインポート時のバリデーションをFromRequestで完結する方法

LaravelでCSVのインポート時のバリデーションをFromRequestで完結する方法

外部からデータを入れる際のゲートとしてFormRequestにまとめたかった
FormRequestのバリデーション前にCSVを取り込んでパラメータに加えて上げればうまくできた。

//実装例

class ProductRequest extends FormRequest
{

    //バリデーション実行まえにCSVを読み込んでパラメータにセットする。
    protected function prepareForValidation()
    {
        //既存のパラメータを取得しておく
        $params = $this->all();

        //アップロードファイルからエンコードを推定
        $upload = $this->file('csv');
        $detectEncoding = mb_detect_encoding($upload->getContent(), ['SJIS-win', 'SJIS', 'UTF-8'], true);

        //SplFileObjectにしてから読み込んで行く(ExcelCSVのセル内改行など処理etc)
        $csv = new \SplFileObject($upload->path());
        $csv->setFlags(
            \SplFileObject::READ_CSV |
            \SplFileObject::READ_AHEAD |
            \SplFileObject::SKIP_EMPTY |
            \SplFileObject::DROP_NEW_LINE
        );
        $collection = collect();
        foreach ($csv as $value) {
            $collection->add(mb_convert_encoding($value, "UTF-8", $detectEncoding));
        }
        
        //読み込んだデータからパラメータをセット
        $params['header'] = $collection->shift();
        $params['data'] = [];
        $headerNames = ['id','name','price'];
        foreach($collection as $idx1 => $row){
            foreach ($headerNames as $idx2 => $name) {
                $params['data'][$idx1][$name] = $row[$idx2];
            }
        };
        $this->merge($params);
    }


    public function rules(): array
    {
        if (request()->method == Request::METHOD_GET) {
            $rules = [];
        } else {
            $rules = [
                'csv' => ['required', 'mimes:csv', 'mimetypes:text/plain,text/csv'],
                'header' => ['required', 'regex:/^id,name,price$/'],
                'data.*.id' => ['required'],
                'data.*.name'=>['required'],
                'data.*.price'=>['required'],
            ];
        }
        return $rules;
    }

    public function attributes()
    {
        return [
            'csv' => 'CSVファイル',
            'header' => 'ヘッダー行',
            'data.*.id' => '商品ID',
            'data.*.name'=>'商品名',
            'data.*.price'=>'価格',
        ];
    }

}

Mac HomeBrewのphp8.1からphp7.4に戻すと動かなかった

切り替えてみるとエラー、libicuio.70.dylibが無いみたい。
最新は libicudata.72.dylibとなっているらしい。→でエラー

$ brew unlink php@8.1
$ brew link php@7.4
$ vim .back_profile
--------------
#export PATH="/usr/local/opt/php@8.1/bin:$PATH"
#export PATH="/usr/local/opt/php@8.1/sbin:$PATH"
export PATH="/usr/local/opt/php@7.4/bin:$PATH"
export PATH="/usr/local/opt/php@7.4/sbin:$PATH"
--------------
$ php -v
dyld[80101]: Library not loaded: '/usr/local/opt/icu4c/lib/libicuio.70.dylib'
  Referenced from: '/usr/local/Cellar/php@7.4/7.4.28_1/bin/php'
  Reason: tried: '/usr/local/opt/icu4c/lib/libicuio.70.dylib' (no such file), '/usr/local/lib/libicuio.70.dylib' (no such file), '/usr/lib/libicuio.70.dylib' (no such file), '/usr/local/Cellar/icu4c/72.1/lib/libicuio.70.dylib' (no such file), '/usr/local/lib/libicuio.70.dylib' (no such file), '/usr/lib/libicuio.70.dylib' (no such file)
Abort trap: 6

brew tapで公式以外の formulaを持ってくる必要あり

$ brew tap-new yama/taps
$ brew extract icu4c yama/taps --version 70

エラー、Xcode:CommandLineToolsが古い?

$ brew install yama/taps/icu4c@70
==> Fetching yama/taps/icu4c@70
==> Downloading https://github.com/unicode-org/icu/releases/download/release-70-1/icu4c-70_1-src.tgz
==> Downloading from https://objects.githubusercontent.com/github-production-release-asset-2e65be/49244766/2b364418-d38d-4d23-b918-11d1194d4cb6?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20230428%2Fus-east-1%2
######################################################################################################################################################################################################################################## 100.0%
==> Installing icu4c@70 from yama/taps
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences.

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/all/.
You should download the Command Line Tools for Xcode 14.2.

Xcode:CommandLineToolsを再インストール、icu4c@70をいインストール成功

$ sudo rm -rf /Library/Developer/CommandLineTools
$ sudo xcode-select --install
$ brew install yama/taps/icu4c@70
$ ll /usr/local/Cellar/ | grep icu
$ ll /usr/local/opt/ | grep icu4c

リンクを貼る

$ cd /usr/local/opt/icu4c/lib/
$ ln -s ../../../icu4c@70/70.1/lib/libicuio.70.1.dylib libicuio.70.dylib
$ ln -s ../../../icu4c@70/70.1/lib/libicui18n.70.1.dylib libicui18n.70.dylib
$ ln -s ../../../icu4c@70/70.1/lib/libicuuc.70.1.dylib libicuuc.70.dylib
$ ln -s ../../../icu4c@70/70.1/lib/libicudata.70.1.dylib libicudata.70.dylib
$ ln -s ../../../icu4c@70/70.1/lib/libicutest.70.1.dylib libicutest.70.dylib
$ ln -s ../../../icu4c@70/70.1/lib/libicutu.70.1.dylib libicutu.70.dylib
//確認
$ ll | grep '70.1'
lrwxr-xr-x   48 taka admin 28 4 18:03  libicudata.70.dylib -> ../../../icu4c@70/70.1/lib/libicudata.70.1.dylib
lrwxr-xr-x   48 taka admin 28 4 18:02  libicui18n.70.dylib -> ../../../icu4c@70/70.1/lib/libicui18n.70.1.dylib
lrwxr-xr-x   46 taka admin 28 4 18:02  libicuio.70.dylib -> ../../../icu4c@70/70.1/lib/libicuio.70.1.dylib
lrwxr-xr-x   48 taka admin 28 4 18:03  libicutest.70.dylib -> ../../../icu4c@70/70.1/lib/libicutest.70.1.dylib
lrwxr-xr-x   46 taka admin 28 4 18:03  libicutu.70.dylib -> ../../../icu4c@70/70.1/lib/libicutu.70.1.dylib
lrwxr-xr-x   46 taka admin 28 4 18:03  libicuuc.70.dylib -> ../../../icu4c@70/70.1/lib/libicuuc.70.1.dylib

復旧できました。

$ php -v
PHP 7.4.28 (cli) (built: Mar  1 2022 09:40:23) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v3.1.3, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v7.4.28, Copyright (c), by Zend Technologies

MacでScreenShot(スクショ)&GIF化メモ

MacでScreenShot(スクショ)&GIF化メモ

Cmd + Shift + 5 で画面収録

$ ffmpeg -i input.mov -r 10 output.gif

RK ROYALキーボードの入力モード切替

FN+Ctrol で入力モードが切り替わる

矢印キーの無効は、Fn+Enter で有効化できる
(https://drive.google.com/drive/folders/11_IkTfy9uLe9-DNFtWLBiKS6m5tFVMZq)

いくつか要約すると

Fn + P 長押しでペアリングモードに入りBluetoothで接続できるようになります。Fn+Q, W, Eであらかじめ機器のキーを割り当てておく

USBとBluetoothの切り替えは、FnキーとTABキーを押し、ペアリングは FnキーとPキーを押す。
Bluetoothホスト機器の切り替えは、Fnキーを押しながら、Q, W, E のいずれかを押す。

Fn + =+キー でバックライトの点灯、光量のup 光量は0~4の5段階あります。

LEDイルミネーションの明るさは、Fnキーを押しながら、 「[{」キーか「]}」キーを押す。
LEDイルミネーションの種類を選ぶには、Fnキーを押しながら、「|」キー。
LEDイルミネーションの速度を変えるには、Fnキーを押しながら、「;:」キーか「'”」キーを押す。

Fn + -ーキー で光量のdown
Fn + winキー でwinキーのロック
Fn + 左のCtrl でファンクションキーの有効化 1を押したらF1、2を押したらF2のように3~0まで同様 他にもEscの無効化など
Fn + ← で デリートキー
Fn + 左のAltを5秒押しで工場出荷状態にリセット

というようにFnキーとの組み合わせが多いですが、慣れれば打鍵感の良いキーボードです。

Amazonからの引用では以下のようなややこしい仕様になっています。

数字キーとファンクションキーのデフォルトを入れ替えるには、Fnキーを押しながら左Ctrlキーを押すことで
数字キーとファンクションキー(正確にはFnキーを押してでてくるキー)が入れ替わる。
もう一度、Fnキーと左Ctrlキーを押すと、アルファベットキーに割り当てられたFnキーのキーが解除になり
数字キーとファンクションキーだけが入れ替わった状態になる。つまり3モードトグルになっている。

https://guitarsk.com/pc/archives/1516\

Fn + Enterで、カーソールキーをFn有無を切り替え

フォーム送信の2重を一括で防止するJavaScrpt

フォーム送信の2重を一括で防止するJavaScrpt

これを書いておけばおけなはず。
(※formのsubmitイベントの衝突/前後は考慮していまっせん。)

document.querySelectorAll('form').forEach(function(form){
    form.addEventListener('submit',function(e){
        if(form.dataset.isSubmit){
            e.preventDefault();
            return;
        }
        form.dataset.isSubmit = '1';
        e.currentTarget.querySelectorAll('button,input[type="submit"],input[type="image"]').forEach(function(el){
            el.style.pointerEvents = 'none';
            el.style.opacity = '0.7';
        });
    });
});
  • 基本ブロック、送信ボタン類のCSS pointer-events: none にして押せなくする。(ついでに透明度さげて押せない感をアピール
  • 入力フィールドでエンターを連打するツワモノがいるので、送信時にデータセット data-is-submit を追加してフラグが立っていれば、送信しない。

PhpStormでソースコード(エディタ)からプロジェクトバーのツリーにジャンプする方法

PhpStormでソースコード(エディタ)からプロジェクトバーのツリーにジャンプする方法。

  1. Alt + F1
  2. Select In のダイアログ表示
  3. 1のProject Viewを選択
title
title

Macのキーリピートスピード調整

Macのキーリピートスピード調整

ターミナルで以下に設定

defaults write -g KeyRepeat -float 1.8
defaults write -g InitialKeyRepeat -int 10

現在の設定値の確認はreadで

$ defaults read -g KeyRepeat
$ defaults read -g InitialKeyRepeat

ローカル開発環境のLaravel(sail)から、ステージングのLaravel経由でAPIを叩く。

ローカル開発環境のLaravel(sail)から、ステージングのLaravel経由でAPIを叩く。

決済APIが特定のIP(ステージング環境)からしか受け付けない状況で、スムーズに開発をしたいため簡易プロキシを作ってみました。

リクエストの流れ

  • 送って (ローカル開発環境) → (プロキシ:ステージング環境) → (APIサーバー)
  • 帰ってくる (ローカル開発環境) ← (プロキシ:ステージング環境) ← (APIサーバー)

利用パッケージ(guzzle)

$ composer require guzzlehttp/guzzle

API用のルーティング

APIのディレクトリをプロキシようのコントローラーに送る。

Route::match(['POST','GET'],'/api/{any}',[\App\Http\Controllers\Dev\ProxyController::class,'index']);

プロキシ部分

  • ProxyController.php
<?php

namespace App\Http\Controllers\Dev;

use GuzzleHttp\Client;
use GuzzleHttp\Psr7;
use App\Http\Controllers\Controller;

class ProxyController extends Controller
{
    public function index()
    {
        $request = Psr7\ServerRequest::fromGlobals();
        $proxyUri = $request->getUri()
            ->withHost('api.example.com')
            ->withPort(433)
            ->withScheme('https');
        $client = new Client;
        dd($proxyUri,$client);
        $response = $client->send($request->withUri($proxyUri), ['http_errors' => false]);
        echo $response->getBody();
    }
}

Docker(sail)利用時にMacでLaravelのデバッグ画面からPhpStormのソースコードにジャンプできない。

Docker(sail)利用時にMacでLaravelのデバッグ画面からPhpStormのソースコードにジャンプできない。

Laravelのデバッグ画面のソースコード表示からPhpStormへのリンクができるがエラーとなる。

title
j
– ※デバッグ画面(ingnition)が/var/www/html/appを参照している
– .envにパスを記載してあげればOK

IGNITION_LOCAL_SITES_PATH='/Users/path/to/your/project'

Laravelの配列(Array)のValidationの項目名に行を表示する。

Laravelの配列(Array)のValidationの項目名に行を表示する。

配列のバリデーションでメッセージを表示する場合に以下のように名前を割り当てていただけど。

    public function attributes()
    {
        return [
            'stock.*.jan' => 'JANコード',
            'stock.*.grade_id' => '商品グレード',
            'stock.*.location_id' => '場所',
            'stock.*.note' => 'メモ',
        ];
    }

複数行でえらーだと以下のようにバグっぽくなってしまう&どこかよくわかんなくなるので、行数をどうにかいれられないかあと

・このJANコードの値は既に存在しています
・このJANコードの値は既に存在しています
・このJANコードの値は既に存在しています
・このJANコードの値は既に存在しています

MessageBag($erros)を配列にtoArray()してKeyを見て強引に行数をいれる

もう少しスマートにできないかどうか。

<div class="alert alert-danger">
    <ul>
        @foreach( $errors->toArray() as $key => $errors)
            @foreach( $errors as $error)
                @if(preg_match('/(\.)([\d]+)(\.)/',$key,$matches))
                    <li>{{ sprintf('%s(%s行目)',$error,intval($matches[2])+1) }}</li>
                @else
                    <li>{{ $error }}</li>
                @endif
            @endforeach
        @endforeach
    </ul>
</div>

Page 2 of 46

Powered by WordPress & Theme by Anders Norén