【Laravel】Eloquentでhavingした結果をpaginateしたい

Laravelでhaving句を使って集計を行うとき、こんな書き方をする。

Model::withCount('xxxx')->having('xxxx_count', '>', 1);

ただ、paginateを付けたい場合

Model::withCount('xxxx')->having('xxxx_count', '>', 1)->paginate(20);

とやると、エラーが出る。

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'xxxx_count' in 'having clause' (SQL: select count(*) as aggregate from `hoges` having `xxxx_count` > 1)

エラー文にある通り、カラムをcount(*)に置き換えただけのselect文を発行してから処理を行うため、having句に使うカラムが消えてエラーになってしまっている。

対策

泥臭いけどこう

$ids = Model::withCount('xxxx')->having('xxxx_count', '>', 1)->get()->pluck('id');
Model::whereIn('id', $ids)->paginate(20);

もっといいやり方があったら教えて欲しい

【PHP】Carbonで月末日付をsubMonthしたら死んだ話

PHPerからしたらありふれすぎた話だけど、2021/07/31の1ヶ月前をCarbonで取得しようとして死んだ。

なにがおきたか

こうすると

$date = new Carbon('20210731')->subMonth(1);
echo($date);

こうなる

2021-07-01 00:00:00

2021-06-30 00:00:00じゃないの?

なぜか

CarbonはDateTimeのラッパー

7/31から1ヶ月減算すると6/31になるが、6/31という日付は存在しない。
なので、6月の月末日の6/30と6/31の差分を計算し、6/30に日付を1日加算する。
結果として7/1になる。

という仕様らしい。

解決策

subMonthsNoOverflowを使う

$date = new Carbon('20210731');
echo($date->subMonthsNoOverflow(1));
2021-06-30 00:00:00
$date = new Carbon('20210731123005');
echo($date->subMonthsNoOverflow(1));
2021-06-30 12:30:05

補足

翌月版もある

$date = new Carbon('20210831123005');
echo($date->addMonthsNoOverflow(1));
2021-09-30 12:30:05

9/31は存在しないがオーバーフローさせずに9/30日になっている

Next.jsの素振りをしたい

% node -v
v14.16.0

% npx create-next-app suburi-next
npx: installed 1 in 1.195s
Creating a new Next.js app in /Users/tagami/suburi-next.

Installing react, react-dom, and next using yarn...

yarn add v1.22.10
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
success Saved 199 new dependencies.
info Direct dependencies
├─ next@10.1.2
├─ react-dom@17.0.2
└─ react@17.0.2
info All dependencies
├─ @babel/code-frame@7.12.11
├─ @babel/helper-validator-identifier@7.12.11
├─ @babel/highlight@7.13.10
├─ @babel/runtime@7.12.5
├─ @babel/types@7.8.3
├─ @hapi/accept@5.0.1
├─ @hapi/boom@9.1.2
├─ @next/env@10.1.2
├─ @next/polyfill-module@10.1.2
├─ @next/react-dev-overlay@10.1.2
├─ @next/react-refresh-utils@10.1.2
├─ @opentelemetry/api@0.14.0
├─ @opentelemetry/context-base@0.14.0
├─ @types/node@14.14.37
├─ anser@1.4.9
├─ ansi-regex@5.0.0
├─ ansi-styles@3.2.1
├─ anymatch@3.1.1
├─ array-filter@1.0.0
├─ asn1.js@5.4.1
├─ assert@2.0.0
├─ ast-types@0.13.2
├─ babel-plugin-syntax-jsx@6.18.0
├─ big.js@5.2.2
├─ binary-extensions@2.2.0
├─ braces@3.0.2
├─ brorand@1.1.0
├─ browserify-aes@1.2.0
├─ browserify-cipher@1.0.1
├─ browserify-des@1.0.2
├─ browserify-rsa@4.1.0
├─ browserify-sign@4.2.1
├─ browserify-zlib@0.2.0
├─ browserslist@4.16.1
├─ buffer-xor@1.0.3
├─ buffer@5.6.0
├─ bytes@3.1.0
├─ chalk@2.4.2
├─ chokidar@3.5.1
├─ cipher-base@1.0.4
├─ classnames@2.2.6
├─ color-convert@1.9.3
├─ color-name@1.1.3
├─ commondir@1.0.1
├─ console-browserify@1.2.0
├─ constants-browserify@1.0.0
├─ convert-source-map@1.7.0
├─ core-util-is@1.0.2
├─ create-ecdh@4.0.4
├─ create-hmac@1.1.7
├─ crypto-browserify@3.12.0
├─ css.escape@1.5.1
├─ cssnano-preset-simple@1.2.2
├─ cssnano-simple@1.2.2
├─ data-uri-to-buffer@3.0.1
├─ debug@2.6.9
├─ depd@1.1.2
├─ des.js@1.0.1
├─ diffie-hellman@5.0.3
├─ domain-browser@4.19.0
├─ electron-to-chromium@1.3.704
├─ emojis-list@2.1.0
├─ encoding@0.1.13
├─ es-abstract@1.18.0
├─ es-to-primitive@1.2.1
├─ es6-object-assign@1.1.0
├─ escalade@3.1.1
├─ escape-string-regexp@1.0.5
├─ esutils@2.0.3
├─ etag@1.8.1
├─ events@3.3.0
├─ fill-range@7.0.1
├─ find-cache-dir@3.3.1
├─ find-up@4.1.0
├─ fsevents@2.3.2
├─ get-intrinsic@1.1.1
├─ get-orientation@1.1.2
├─ glob-parent@5.1.2
├─ glob-to-regexp@0.4.1
├─ graceful-fs@4.2.6
├─ has-bigints@1.0.1
├─ hash.js@1.1.7
├─ he@1.2.0
├─ hmac-drbg@1.0.1
├─ http-errors@1.7.3
├─ https-browserify@1.0.0
├─ iconv-lite@0.4.24
├─ is-arguments@1.1.0
├─ is-bigint@1.0.1
├─ is-binary-path@2.1.0
├─ is-boolean-object@1.1.0
├─ is-callable@1.2.3
├─ is-date-object@1.0.2
├─ is-extglob@2.1.1
├─ is-generator-function@1.0.8
├─ is-glob@4.0.1
├─ is-nan@1.3.2
├─ is-negative-zero@2.0.1
├─ is-number-object@1.0.4
├─ is-number@7.0.0
├─ is-regex@1.1.2
├─ is-symbol@1.0.3
├─ isarray@1.0.0
├─ isobject@2.1.0
├─ jest-worker@27.0.0-next.5
├─ js-tokens@4.0.0
├─ json5@1.0.1
├─ line-column@1.0.2
├─ loader-utils@1.2.3
├─ locate-path@5.0.0
├─ lodash.sortby@4.7.0
├─ lodash@4.17.21
├─ loose-envify@1.4.0
├─ make-dir@3.1.0
├─ merge-stream@2.0.0
├─ miller-rabin@4.0.1
├─ minimist@1.2.5
├─ ms@2.0.0
├─ nanoid@3.1.22
├─ native-url@0.3.4
├─ next@10.1.2
├─ node-fetch@2.6.1
├─ node-html-parser@1.4.9
├─ node-libs-browser@2.2.1
├─ node-releases@1.1.71
├─ normalize-path@3.0.0
├─ object-inspect@1.9.0
├─ object-is@1.1.5
├─ object.assign@4.1.2
├─ os-browserify@0.3.0
├─ p-limit@3.1.0
├─ p-locate@4.1.0
├─ p-try@2.2.0
├─ pako@1.0.11
├─ parse-asn1@5.1.6
├─ path-browserify@1.0.1
├─ path-exists@4.0.0
├─ picomatch@2.2.2
├─ pkg-dir@4.2.0
├─ platform@1.3.6
├─ pnp-webpack-plugin@1.6.4
├─ process-nextick-args@2.0.1
├─ process@0.11.10
├─ prop-types@15.7.2
├─ public-encrypt@4.0.3
├─ punycode@1.4.1
├─ querystring-es3@0.2.1
├─ querystring@0.2.1
├─ randomfill@1.0.4
├─ raw-body@2.4.1
├─ react-dom@17.0.2
├─ react-is@16.13.1
├─ react-refresh@0.8.3
├─ react@17.0.2
├─ readdirp@3.5.0
├─ regenerator-runtime@0.13.7
├─ safer-buffer@2.1.2
├─ scheduler@0.20.2
├─ semver@6.3.0
├─ setimmediate@1.0.5
├─ setprototypeof@1.1.1
├─ shell-quote@1.7.2
├─ stacktrace-parser@0.1.10
├─ statuses@1.5.0
├─ stream-browserify@3.0.0
├─ stream-http@3.1.1
├─ stream-parser@0.3.1
├─ string_decoder@1.3.0
├─ string-hash@1.1.3
├─ string.prototype.trimend@1.0.4
├─ string.prototype.trimstart@1.0.4
├─ strip-ansi@6.0.0
├─ styled-jsx@3.3.2
├─ stylis-rule-sheet@0.0.10
├─ stylis@3.5.4
├─ supports-color@5.5.0
├─ timers-browserify@2.0.12
├─ to-arraybuffer@1.0.1
├─ to-fast-properties@2.0.0
├─ to-regex-range@5.0.1
├─ toidentifier@1.0.0
├─ tr46@1.0.1
├─ ts-pnp@1.2.0
├─ tty-browserify@0.0.1
├─ type-fest@0.7.1
├─ unbox-primitive@1.0.1
├─ unpipe@1.0.0
├─ url@0.11.0
├─ use-subscription@1.5.1
├─ util-deprecate@1.0.2
├─ util@0.12.3
├─ vm-browserify@1.1.2
├─ watchpack@2.1.1
├─ webidl-conversions@4.0.2
├─ whatwg-url@7.1.0
├─ which-boxed-primitive@1.0.2
├─ which-typed-array@1.1.4
├─ xtend@4.0.2
└─ yocto-queue@0.1.0
✨  Done in 8.57s.

Initialized a git repository.

Success! Created suburi-next at /Users/tagami/suburi-next
Inside that directory, you can run several commands:

  yarn dev
    Starts the development server.

  yarn build
    Builds the app for production.

  yarn start
    Runs the built app in production mode.

We suggest that you begin by typing:

  cd suburi-next
  yarn dev

% cd suburi-next 
% yarn dev
yarn run v1.22.10
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - Using webpack 4. Reason: future.webpack5 option not enabled https://nextjs.org/docs/messages/webpack5
event - compiled successfully
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry

event - build page: /
wait  - compiling...
event - compiled successfully

f:id:iine_programming:20210401135407p:plain

はい。

最近のフロントエンドは環境構築が手軽でいいね。

t2.microからt2.nanoにしたらmysqldが起動しなかったメモ

現象

$ sudo service mysqld start
Redirecting to /bin/systemctl start mysqld.service
Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.

mysqld.log

2020-11-13T06:18:39.804582Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.17) starting as process 11077
2020-11-13T06:18:39.836009Z 0 [Warning] [MY-010122] [Server] One can only use the --user switch if running as root
2020-11-13T06:18:39.926149Z 0 [ERROR] [MY-012681] [InnoDB] mmap(137363456 bytes) failed; errno 12
2020-11-13T06:18:39.926193Z 1 [ERROR] [MY-012956] [InnoDB] Cannot allocate memory for the buffer pool
2020-11-13T06:18:39.926220Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Generic error.
2020-11-13T06:18:39.926240Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine
2020-11-13T06:18:39.926337Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2020-11-13T06:18:39.928100Z 0 [ERROR] [MY-010119] [Server] Aborting
2020-11-13T06:18:39.933309Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.17)  MySQL Community Server - GPL.

swap領域がない

$ free
              total        used        free      shared  buff/cache   available
Mem:         491212       74336      246564         532      170312      383356
Swap:             0           0           0

swap領域を作る

$ sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 14.8229 s, 72.4 MB/s

$ sudo mkswap /swapfile
mkswap: /swapfile: insecure permissions 0644, 0600 suggested.
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=*******************

$ sudo swapon /swapfile
swapon: /swapfile: insecure permissions 0644, 0600 suggested.
$ sudo service mysqld start
Redirecting to /bin/systemctl start mysqld.service

$ sudo service mysqld status
Redirecting to /bin/systemctl status mysqld.service
~
   Active: active (running) since Fri 2020-11-13 15:22:10 JST; 6min ago

解決

参考

qiita.com

Google Fit APIをFlutterアプリから呼び出すメモ

Google Fit APIをFlutterアプリに組み込むのに認証通すまでが大変だったのでメモ

  1. console.developers.google.comでFitness APIを有効化
  2. console.developers.google.comでOAuth同意画面を作成する
  3. Fitness API→認証情報からOAuth 2.0 クライアント IDを作成する
  4. manifestファイルにpermissionを追記
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>

HTTPリクエストヘッダーのフィールド名に"_"を使うと消える

リクエストヘッダーの独自フィールドを利用するWebAPIを作った際に、フィールド名にアンダースコア("_")を含むフィールドがリクエストから消えている現象が発生した。

HTTPの仕様としてアンダースコアを含む("_")フィールドは削除されるらしい。

RFC 3875 - The Common Gateway Interface (CGI) Version 1.1

プログラマーをする上での価値観を考える

脳内整理のメモ

こんな環境をめざしたい。

品質向上がプラスに働く環境

  • 自動テスト・CI/CD・リファクタリングなどの品質向上技術は"開発者にとって"の正しさの指標の一つ
    • 肌感として正しいことをしていると仕事がたのしい
    • 経営・営業的な正しさとは必ずしもならない
      • 経営・営業的にもプラスになるように上手く組み込めるといい
  • もちろんビジネス要件は満たした上での話

チームビルディングを実践している環境

  • チーム内でコミュニケーションを実施することの動機付けになる
  • 心理的安全性を相互に確保するので楽しく働ける
  • 方針をもってチームのスキルを向上させることができる
    • スキルの偏りによる属人化はつらい

育成にコミットすることでプラスになる環境

  • 開発>管理の場合、マイナスがあると動機付けが難しい
    • 今まで開発業務に使えてたコストを育成に使うことになる
    • 開発から管理にキャリアパスがシフトしていくのではという不安
  • 特に受託開発だと担当案件の取り合いの側面もある
    • 案件を増やせて社の業績が増えるので金銭的に還元されるというメリットもある
      • 上記に挙げたマイナス点との損益分岐点が近い環境でなら育成を行う動機付けになるか