OmniAICreator/Qiita-1.07M huggingface dataset:
【PHP】「戻り値をvoidとした関数からリファレンスを返すことは、 推奨されなくなりました。」とは？

# はじめに

PHPマニュアルの型に関するページを見ていると、このような記述が書いてあります。

> 戻り値を void とした関数からリファレンスを返すことは、 推奨されなくなりました。

https://www.php.net/manual/ja/language.types.declarations.php

一見すると「戻り値をvoidとした関数は推奨されなくなりました。」のように見えて、「void型怖い…」「void型を使うのはやめよう…」となってしまうかもしれません。しかし、ここで記述されていることは**リファレンスを返す関数の戻り値にvoid型を指定することが非推奨になった**ということであり、**void型が非推奨になったというわけではありません。**

# リファレンスを返す関数

そもそも、リファレンスを返す関数とは何でしょうか。PHPマニュアルでは以下のような例が挙げられています。

```PHP
<?php
class foo {
    public $value = 42;

    public function &getValue() {
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue は $obj->value へのリファレンス、つまり 42 となります
$obj->value = 2;
echo $myValue;                // $obj->value の新しい値である 2 を表示します
?>
```

https://www.php.net/manual/ja/language.references.return.php

メソッド``getValue()``の左側に``&``の記号がついています。これは、このメソッドがリファレンス(参照)を返すことを意味しています。``getValue()``からは``foo``クラスのプロパティ``$value``のリファレンスを受け取れるため、``$obj->value``の値を変更すると``$myValue``の値が変わることが確認できます。

# 返り値がvoid型のリファレンスを返す関数

対して、返り値がvoid型のリファレンスを返す関数とは何か。PHP 8.1 の RFC、Return by reference with void type の項目を確認すると以下のような例が挙げられています。

```PHP
function &test(): void {}
```

https://wiki.php.net/rfc/deprecations_php_8_1#return_by_reference_with_void_type

* 関数名``test()``の左側に``&``の記号がついているのでリファレンスを返す：**値を返す**
* 戻り値の型がvoid：**値を返さない**

これは **「値を返す」と「値を返さない」のどちらの意味も含む、矛盾した書き方になっています。** PHP 8.1.0 からはこの**矛盾した書き方を避けるために、返り値がリファレンスかつvoid型の関数を非推奨にした**ようです。

# void型を使用するメリット

void型はPHP 7.1.0 で追加されました。そのときのRFC、Void Return Type を確認すると以下のようなことが書かれています。

> (戻り値の型を省略することで) 任意の値を返すことを指定する手段はすでにありますが、戻り値の型を持つ他の多くの言語とは異なり、値を返さないように指定する方法はありません。これは文書化やエラーチェックの目的で役立つ可能性があるため、これは残念です。特に、関数が結果を生成するのではなく、アクションを実行することが明確になります。

https://wiki.php.net/rfc/void_return_type

void型を使用すると、このようなメリットを享受することができそうです。

* 文書化やエラーチェックの目的で役立つ可能性がある
* 関数が値を返すのではなく、処理を実行するだけであることが明確になる

例えば、void型の関数が何らかの値をreturnしたとすると、実行時に ``Fatal error: A void function must not return a value`` とエラーが出てくれます。

```PHP
<?php

function test(int $number): void // void型なのに
{
	return $number + 1; // 値を返している
}

var_dump(test(5));
```

# まとめ

* PHP 8.1.0 で非推奨になったのは、返り値がリファレンスかつvoid型の関数
  * 理由は矛盾した書き方だから
  * 返り値がリファレンスではない関数でvoid型を使用することは問題ない
* void型を使用するのにはメリットがある
  * 文書化やエラーチェックの目的で役立つ可能性がある
  * 関数が値を返すのではなく、処理を実行するだけであることが明確になる
【Laravel備忘録】「Target class [○○Controller] does not exist.」

# 【Laravel備忘録】
Laravelを学習中のエンジニア5年目社会人です。
今まで設計やテスト案件ばかりでしたが今年から開発案件に携われるようになったので自己学習とともに備忘録つけます。
今回の内容は下記です。

## 「Target class [○○Controller] does not exist.」が出る
某参考書を用いながら環境作って学習進めておりますが、結構な序盤でこのエラーに悩まされました。
理由から伝えますとPHPのバージョンと書き方の問題でした。
まず参考書のPHPのバージョンは7.2でした。
自分の環境のPHPは8.1でした。
```
PHP 8.1.12 (cli) (built: Oct 25 2022 18:16:21) (ZTS Visual C++ 2019 x64)
Copyright (c) The PHP Group
Zend Engine v4.1.12, Copyright (c) Zend Technologies
```

でエラーになったコードが下記です。
```
Route::get('hello', 'HelloController@index');
```
この書き方はPHPのバージョンが7.Xまでの書き方らしく8.1の環境ではエラーになるようです。

修正したコードがこちら
```
Route::get('hello', 'App\Http\Controllers\HelloController@index');
```

絶対パスという言い方で正しいかはわかりませんが、このような書き方をしないといけないようです。

ということで無事エラー解消されました。
エラー原因がなかなかわからないとイライラしますよね。。。

ではみなさん、良きエンジニアライフを。
ventoy (USBマルチブート作成ツール)

## USBメモリ作成ツール

> Ventoyは、ISO / WIM / IMG / VHD ( x ) / EFIファイル用の起動可能なUSBドライブを作成するためのオープンソースツールです。


* https://ventoy.net/en/index.html

## 使い方

* https://www.gigafree.net/system/os/Ventoy.html

`Ventoy2Disk.exe`でUSBメモリを初期化して、USBメモリにISOファイルを置くだけ。
Databricks Reposのリポジトリがワークスペース配下に移動しました

これまではサイドメニューの**ワークスペース**の隣に**リポジトリ**がありましたが、ワークスペース配下に統合されました。

![Screenshot 2023-06-13 at 9.13.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/05ab0fd8-c536-e96c-e1f6-4c920e3a670c.png)
![Screenshot 2023-06-13 at 9.16.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/42511059-cd6c-3a28-cd82-645c4ec1d187.png)

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Flutter 🧢 LINE とTwitterでシェアするコードのベストプラクティス

# 本編

ライン、Twitter には、複数のシェア用 REST API が用意されているが、Android, iOSにネイティブ対応されたものを以下に示した。（その他のAPI は、ディープリンク対応していなかったり、ハッシュタグが機能しなかったりする。）

```

Future<void> shareByLine(String text) async {
  final lineUrl = Uri(
    scheme: 'https',
    host: 'line.me',
    path: 'R/msg/text/' + text,
  );
  await launchUrl(lineUrl, mode: LaunchMode.externalApplication);
}

Future<void> shareByTwitter(String text) async {
  final tweetQuery = <String, dynamic>{
    'text': text,
    // 'url': 'https://...',
    // 'hashtags': ['tag1', 'tag2'],
  };

  final twitterUrl = Uri(
    scheme: 'https',
    host: 'twitter.com',
    path: 'intent/tweet',
    queryParameters: tweetQuery,
  );

  await launchUrl(twitterUrl, mode: LaunchMode.externalApplication);
}

String? encodeQueryParameters(Map<String, String> params) {
  return params.entries
      .map((MapEntry<String, String> e) =>
          '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
      .join('&');
}

```

カンペキ！💜
Tree of Thoughtというプロンプトが面白いということで、GitMindを使ってみたら、まさにTree構造で視覚化された！

有名なYouTuberさんが、Tree of Thoughtというプロンプトを紹介していました。
詳しい内容は[こちら](https://arxiv.org/abs/2305.10601)にあるそうです。(英語の論文で難しい。。。)

そのYouTube動画の中で紹介されていたプロンプトを仮想人物を想定して少し修正し、GitMindのAI機能(GPT-xを使っている模様)で、MindMapを書いてもらいました。

ChatGPTのナラティブな文章も読んでいて楽しいのですが、MindMapの形式で整理されると読む負荷が軽減されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3373806/ab6f636d-15a4-40df-50d0-189e2439dad4.png)
SOQL for Admins  > Create Relationship Queries with Custom Objects


[SOQL for Admins  > Create Relationship Queries with Custom Objects](https://trailhead.salesforce.com/content/learn/modules/soql-for-admins/create-relationship-queries-with-custom-objects?trailmix_creator_id=bmayo&trailmix_slug=jr-crm-sys-admin)


# Method does not exist or incorrect signature: void newListedProperties() from the type PropertyUtility

+ [Execute Anonymous Error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000QNpMg)

:::note
Make sure you have an Apex class called PropertyUtility saved.
:::

+ [04t8b000001FBRGのパッケージがインストールできない](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000J7XsH)

:::note alert
his package can’t be installed.

There are problems that prevent this package from being installed.

Package Not Found | The requested package doesn't yet exist or has been deleted. If this is a recently created package version, please try again in a few minutes or contact the package publisher.
:::
LWC : ページの編集時に、コンポーネント リストにデプロイされたコンポーネントが表示されない



+ [Don't see the deployed component in Components list when editing the page](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000QOI3N)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/12b9a075-d3a1-b2dd-fee5-dafb164a42ba.png)


:::note
You need to use the  js-meta.xml file as show below and push the changes 

Refer this links 
https://rajvakati.com/2018/12/22/lightning-web-components/ 

``` 
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
  <apiVersion>45.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
    <target>lightning__RecordPage</target>
    <target>lightning__HomePage</target>
  </targets>
</LightningComponentBundle>
```

https://developer.salesforce.com/forums/?id=9062I000000QvQUQA0
:::
DockerFileからイメージ作ってテストするメモ

ローカルでDockerイメージ立ててテストしたかったのでメモ。
DockerFileは既にできているものとする

##### 1.UbuntuにDockerをインストール


素直に公式ページを見よう

https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/ubuntu/

##### 2.イメージ作成
以下のページの2つ目を参考に作る。名前は適当。

https://pointsandlines.jp/server-infra/docker/docker-beginner-4

```
$ docker build -t sample-image .
```

##### 3.テスト
docker run につづけて実行したいコードを書く。今回はテストを回したいので最後に"npm run (test)"的なの（自分で設定したスクリプト指定）をつける。

```
$docker run -w /(ディレクトリ) ...(略) sample-image -c "npm run test"
```
Improve Data Quality for a Recruiting App >Create Formula and Roll-Up Summary Fields

[Improve Data Quality for a Recruiting App >Create Formula and Roll-Up Summary Fields](https://trailhead.salesforce.com/content/learn/projects/improve-data-quality-for-a-recruiting-app/formula-roll-up-summary-fields)

# We couldn't find the correct settings for the field 'Number of Reviews'.

+ [Improve Data Quality for a Recruiting App Create Formula and Roll-Up Summary Fields](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Pf7nl)

これだと思うけど解決していない。

:::note
To resolve that follow the steps below.
1. click on object manager.
2. select Job Application.
3. Go to the fields and relationships.
4. check out the "Number of Reviews" Roll-Up Type as the "Count". 
5. check out the "Total Review Score" Roll-Up Type as the "Sum ".

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfNm0SAF
:::


:::note
Before you can do this project, you must complete the [Build a Data Model for a Recruiting App](https://trailhead.salesforce.com/projects/build-a-data-model-for-a-recruiting-app) and [Customize the User Interface for a Recruiting App](https://trailhead.salesforce.com/projects/customize-the-ui-for-a-recruiting-app) projects. 

Can you please confirm if you have completed the above projects.
:::


# We couldn't find the aggregate expense item amount

+ [I am unable to complete the challenge "Create a Roll-Up Summary Field" because of the error "We couldn't find the aggregate expense item amount.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007O26mB)

:::note
Thank you for the suggestions and additional items of research. I checked all of the field-level securities and object configurations. Unfortunately, I was not able to find a solution. I decided to start a new playground and work through the steps of the trail again. Once I got to this step in the 2nd playground, it passed without issue. I submitted a case to Salesforce support. Perhaps my original playground was corrupt in some way.
:::
難しいことは考えずにもっと気楽にChatGPTを使ってみる

巷ではプロンプトエンジニアリングが非常に流行っています。
こんな方法でChatGPTの能力を120%引き出せるのかと思うと、ChatGPTと人間の探究心には、驚くばかりです。

ただ、もっと気楽な使い方があってもいいと思いました。
私が最近やっている使い方をご紹介します。

最近はSlackやTeamsなど、メールよりチャットツールを使うことが多くなりました。
メールに比べ気楽に書いていることも多く、相手にとって失礼なことを書いていないか気になることがありました。

そこで自分が書いた内容をChatGPTに評価してもらうのです。
やり方はとても簡単です。こんな風に入力します。
```
これを作成した人の性格を判断してみてください。
***
(ここに自分の書いた内容をそのままコピペします)
```
さらに続けて、
```
今後のコミュニケーションをスムーズにために、修正した方が良いところがあれば修正をお願いします
```
たった、これだけです。

ChatGPTからの返信はとても参考になります。
結果、ひねくれ者の私がちょっと正確の良い人間になれました。以上です。
【CS業務の自動化】GAS、ChatGPT、SlackAPI、SalesforceAPIの組み合わせで顧客対応を効率化する方法（コード公開版）

本記事はNote側で公開している下記記事で触れているサンプルコードを記載します。

https://note.com/subland_/n/n4b3268c6b65b

記載までしばらくお待ちください
憂鬱な梅雨も新しい服を買って外に出よう！ #Makeで簡単に新しい服を提案してくれるLINEBot作成しました

## 新しい服装を提案してほしい
最近、子供が少し成長したため、オシャレな洋服着たい！という気持ちが湧いてきました。
自分が選ぶといつもワンパターンになってしまうため、アドバイスしてもらえたら嬉しいなと思っています。
しかし、お店に行ってからいきなりアドバイスを受けるとこれって本当に私に似合うのかな？と考える時間がなく、他の商品と比較したいと思い買えないことがあります。
そこで服装を提案してくれるLINEBotを作りました:smile:

## 実装イメージ
LINEBotは剛くんと命名しました:grin:
全てMakeで作ります！
![スマホ時間を快適に (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/747e9723-9679-7e57-2681-57d26fff710e.png)

## 実装結果
コードを書かずに設定するだけで実装することができました:laughing:

https://twitter.com/yuko6891/status/1668136357418655745

## 実装環境
Make
LINEmessagingAPI
ChatGPT
LINEBot

## 手順

### MakeでLINEBotを作成する
以下の記事を参考にしました。
- [ChatGPTとMakeで料理に合うお酒を提案してくれるLINE BOTを作ってみた](https://note.com/_spaj_/n/nb8d63c022510)

<details><summary>MakeでLINEBotを作成する</summary><div>
LINEMessagingAPIに登録するWebhookはこちらからこピーします。

![スクリーンショット 2023-06-13 7.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/c9da6fc4-f11c-c6f2-3491-6f304697169e.png)
OpenAIでMessagesの部分に「服装を１００文字くらいで提案してください」と指定しました。ここの指定を変えてみると、提案が変わるため面白いです。
![スクリーンショット 2023-06-13 7.05.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/21f8d582-4926-17b5-beea-f05064c2345c.png)
３つ目のLINE Send a Reply Messageには以下の通り指定します。
![スクリーンショット 2023-06-13 7.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/3856467d-c3a5-ac27-b4cd-e74e313fdf09.png)
以下実行結果の中身です。Contentに回答が返ってきていることがわかります。設定を変更してどの部分に回答が入っているのかわからない時は実行してみてここで確認して下さい。
![スクリーンショット 2023-06-13 7.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/1305f075-0e54-a9c1-fb96-d389d7afd59f.png)
</div></details>
実行します。
Ran Onceボタンを押します。処理が終わるとそれぞれに①が表示されます。
ログも下に表示されています。

![スクリーンショット 2023-06-13 7.07.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/41f111b0-b032-4054-9ba6-8dcb26c7d948.png)

上記のだと1回の実行になります。
動かし続けたい時は以下の部分をONにします。
パソコンを閉じても動き続けます！
![スクリーンショット 2023-06-13 7.10.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/631540f2-2342-2e7a-0569-e8a23d27e973.png)


### リッチメニューを作成
私がよく買うお店の公式サイトをリンクにつけました。毎回検索するのが面倒でしたが、これでサクッと調べることができます。

<details><summary>リッチメニューの作成</summary><div>

リッチメニューから作成を選択します。
![スクリーンショット 2023-06-13 6.40.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/677c0665-3b5d-fb8b-528a-103144e5c8ad.png)
テンプレートを選択します。
![スクリーンショット 2023-06-13 6.44.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/6c22f56b-0e13-acaf-6e69-c25931c59034.png)
エリアごとの画像を作成を選びます
![スクリーンショット 2023-06-13 6.46.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/542e770b-5a28-fde1-4416-bcc4b1c5f125.png)
アクションではタイプリンクを選択します
![スクリーンショット 2023-06-13 6.47.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/2b59bf96-7e2f-43de-d53b-58c54e6dda58.png)
</div></details>




## 最後に
ChatGPTにわざわざ聞くのは手間ですが、LINEBotならスマホで簡単に聞くことができます。手軽にChatGPTを使えるのは便利ですね:thumbsup:お気に入りの洋服がすぐに検索できるため、調べる頻度が増えそうです！
一方で、文章だけだとイメージが湧かないという印象がありますね。今後は文章から画像を生成してもらい、イメージが湧くようにしたいと思いました:relaxed:

こちらの記事にも丁寧に解説がありました。
- [ChatGPT × LINE Bot × Make ノーコードで対話できるChatBotを作成する](https://qiita.com/watanabe-tsubasa/items/8342595d641143b780f7)
Arduino IDEとPlatformIO IDE

sketch(Arduino IDE)やPlatformIO IDEの統合開発環境について知らずに触っていたので、調べてみることにしました。

## 1.統合開発環境(IDE:Integrated Development Environment)
統合開発環境は、テキストエディタ、コンパイラ、リンカ、デバッカーなど開発に必要な機能を一つにまとめたソフトウエアです。開発環境がまとめられていることで、対象のデバイスに書き込むプログラム、コンパイラの状態を残すことができます。そうすることで、開発環境を再構築しやすくなり、開発環境構築にかかる時間を省くことができます。

## 2.Arduino IDEと PlatformIO IDE
マイコンをコンパイルする際に使用するIDEには、Arduino IDEと PlatformIO IDEがあります。[platformio](
https://docs.platformio.org/en/latest/faq/arduino-vs-platformio.html)のサイトからの引用ですが、どちらを使用するかは、プロジェクトやユーザーによって変ってきます。Arduino IDEは、初心者やシンプルなプロジェクトを進めていくのに適していて、 PlatformIOは、高機能な開発環境をつくることができ、より高度で複雑なプロジェクトを進めていくことに適しています。

> Arduino IDE is a simple and easy-to-use development environment that is specifically designed for the Arduino platform. It provides a straightforward and intuitive interface for writing and uploading code to the board. The Arduino IDE is well-suited for simple projects and for users who are new to the world of microcontrollers.
> 
> PlatformIO IDE, on the other hand, is a more powerful and feature-rich development environment. It supports a wider range of microcontroller platforms and development boards, and provides a comprehensive set of tools for Library Management, Continuous Integration, Unit Testing, and Debugging. PlatformIO IDE is well-suited for more complex projects and for experienced users who need more advanced features.

## 3. Arduino IDEの開発環境
![スクリーンショット 2023-06-13 8.07.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/83c8aa6e-8323-41d2-a2bf-93d8dce1799c.png)


Arduino IDEで行っていることをブロック図にしてみました。ボードマネージャーでは、特定の製品群をまとめているパッケージを最初に登録します。パッケージの中には、製品群からさらに詳細に分かれた製品に対して特化したプログラムが記述されています。製品ごとにボード内に使用されているマイコンが変わるのでそれに合わせたプログラムが関数としてまとまっているものがライブラリになります。そのライブラリを実行させるコードで使用するには、includeでライブラリを読み込むことで関数を使用できることになります。コードが完成し、書き込みたいマイコンを選択するのにボードの設定をしてコンパイルと書き込みをします。プログラム内でデバックとしてシリアルアウトしておけば、実行されたときの結果がシリアルモニタを介して確認することができます。
エンジニアとしてつけるべき習慣

何も考えずにエンジニアとして働いていると会社の往復で1日が終わりますよね。
私も最近までそうでした。ただ将来のことを考えるとこれではダメだと思い、最近は家に帰った夜の時間と朝の時間を使って活動しています。

今日はそんな時間を使ってエンジニアとしてつけるべき習慣というのを考えてみました。

## 1日の目標設定
毎日勉強しようと思って、まず始めるべきはその日の目標を立てることです。
ただ闇雲にやっても、だんだんとやる気が削がれていったり、次何しようって迷います。
それに思い立ってやり始めたことは、効率が悪かったり、今身につける必要がないものだったりします。

何かやろうと思ったらまずは今自分は何を学んで何を伸ばすべきなのか考えて計画を立てましょう！

## アウトプット
これはよく言われることですが、アウトプットの習慣をつけようということです。
インプットの量よりもアウトプットの量のほうが大事で、名著である「アウトプット大全」という本にも書かれていました。

技術書を買っても読むだけで終わっていませんか？
技術書に関しては読むだけではほぼ身についていません。そこに書いていることを実践して初めて技術は身についていきます。

アウトプット先は業務でも個人開発でもいいですし、ブログやQiitaなどの投稿サイトでもいいです！
内容はきれいにまとめる必要はないので、まずは気楽にアウトプットしていきましょう！

## コーディング
開発業務をやっている方なら仕事以外でコーディングをする時間は作りましょう。
業務内だけだと業務に偏った知識しかつかず、コーディングも特定の設計手法のもとでしか書けません。

自分でプロジェクトを作って自分で考えたディレクトリ構成で何かを作ったり、
業務では自分の担当外のところもコーディングができるので、業務と同等かそれ以上にプライベートでコーディングの時間を作るのは大事なことです。

まずは書籍に書いているサンプルソースやネット上にあがっているものでもいいので写経からはじめましょう！

## 新しい言語を学ぶ
私が過去に参画した案件はほぼほぼJavaで今までのまわりのエンジニアもJavaだけって人が結構いました。
確かにJavaを使っているところは多いので、Javaが出来れば特段困ることもありません。

ただし、それだけではエンジニアとしては勿体なくないですか？
他の言語をやってみると、言語ごとの特性が見えてきて面白いです。
特に言語には人によって好き嫌いもあるので、Javaだけやっている人でもJava以外で好きな言語が見つかるかもしれません。

あとは別の言語を学ぶことで将来Javaが廃れたとしても対応できますし、参画できる案件も増えます。

私は最近GoやPythonを勉強しようと考えてます！

## 便利なツール調査
VSCodeの入力補完やリンターのプラグインやブラウザのプラグインなど探してみると開発に便利なツールが結構あります。

フロント系であれば、コピペで使えるUIコンポーネントを公開しているサイトもあって非常に参考になります。

既にあるものなら一から作らずに有効活用していきたいですよね。
それにコーディングをしていて手動でインデントを揃えたり、改行を加えたりといった作業はなんの生産性もありません。
最低でもPrettierなどの自動フォーマッターは入れておきたいところです。

## 自分でプロフェッショナルと言える技術を身につける
転職活動をしていてよく言われたのが、「あなたが一番得意としている技術はなんですか？」というもの。

広く浅くというもの大事ですが、何か人よりも特出して得意なものを持っておくというのも大事です。
特にその領域に秀でていれば、会社としては非常に頼りになる存在となり重宝されます。

自分じゃないと分からないこと・自分が社内で一番詳しいことを身につけることで自分の存在価値というのをあげることができます。

なんでもいいのでこれを極めようと思うものができたら、毎日それについて学ぶ時間を設けましょう。

## 1日のふりかえり
1日の目標を立てて、それを実行に移した後はそのふりかえりをやることも重要です。

もし予定よりも出来なかったのなら、どうしたらできるようになるか、目標設定が厳しすぎたから目標を見直すなどを考えましょう。

目標達成できなかったときには「もういいや」と諦めモードになってだんだんとやめてしまいます。
逆に目標達成できたなら、達成感を味わえて今日も頑張ったとプラスに考えることができます。

私は最近はその日の目標が早めに達成できると、残りの時間は何しようかなって考える時間が好きで、明日やることを前倒ししてやったりしています。

## まとめ
最初にいろいろやるのはハードルが高いと思うので、本を1日10ページ読むだけ、Paizaなどのスキルチェックサイトでコーディングの問題を1問やるだけでもいいので、まずは毎日何かをやることの習慣をつけましょう！

だんだん習慣づくとそれが楽しく思えてくるはずです！
あとは何もしなかったときも1日が長く感じて充実してきます！

今日この記事を書いたのも私のアウトプットの習慣をつけるための一つでもあります。
個人的にはちょっと時間かけすぎですが、20分ぐらいで書き上げました。
しばらくは1日最低1記事をQiitaにあげようと思います！
React dnd-kit  draggableコンポーネント内のボタンが動かない時の対処

Reactの[dnd-kit](https://dndkit.com/)を使ってドラッグ＆ドロップを実装した時の話。
draggable(正確には`useSortable`)にしたコンポーネント内の削除ボタンが10回に1回くらいしか動かなかった。

## 原因

原因を調べたところ、ボタンを押した際のマウスの動きが「ドラッグ」と判定され、
削除ボタンの押下と判定されていなかった模様。

下記記事に`DragOverlay`を使った時に同様の事象が見られた報告があり、
おそらく原因としては一緒かなと。

https://github.com/clauderic/dnd-kit/issues/355


## 対処法

`Sensors`を利用する。

https://docs.dndkit.com/api-documentation/sensors

`Sensors`を利用すると、dragする際の細かな挙動を制御することが可能。
今回はこれを利用して、「掴んだ瞬間ではなく、掴んでから10px動かしたらドラッグと判定」という状態を実現する。

`DndContext`と同じコンポーネントに下記のように記述する。

```react
import {
  DndContext,
  MouseSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core';

function App() {
  const mouseSensor = useSensor(MouseSensor, {
    // Require the mouse to move by 10 pixels before activating
    activationConstraint: {
      distance: 10,
    },
  });
  
  const sensors = useSensors(
    mouseSensor,
  );
  
  return (
    <DndContext sensors={sensors}>
      {/* ... */}
    </DndContext>
  )
}
```

これで削除ボタンが効くようになった。

上記では`MouseSensor`のみ利用しているが、他にもKeyboardSensorやTouchSensorなどもあります。
docker.errors.DockerException: Error while fetching server API versionの対処法

初歩的なミスですがエラー文だけだと意外とわかりにくかったりします。

# エラー内容
```
$ docker-compose up

（省略）

docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
[3854] Failed to execute script docker-compose
```

# 原因
**Docker Desktopが起動していなかった。**

それだけです。。
たまにやってしまう単純なミスです。

# 解決
Docker Desktopを起動して再度```docker-compose up```したら無事起動できました！


# 参考

https://yuyuublog.com/dockererrorsfetching/
【Eclipse】サーバーが起動しないときの解決方法

## はじめに
Java サーブレット＆JSPでプロジェクトを作成していますが、
サーバーが起動しないエラーが度々起こっていたので、
備忘録としてまとめておきます。

| 環境| | 
|:--:|:--:|
| OS       | Windows10 22H2 
| エディター | Eclipse(ver.4.26.0)|


## 起きていること
・サーバー(今回はTomcat9_Java17を使用しています)を右クリックして
「開始」を押しても特にエラーなどは見当たらない
しかし、webapp内に置いたjspファイルが表示されない(URLなどは正しい)

・デバッグモードで起動すると以下の画像のようなエラーが出る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/05139d09-1ace-94cc-6a49-e7666ed2798d.png)

## 対処法
・サーバーを右クリックし、「追加および除去」を選択
・全て追加を押下し、Java_JSPを構成済みにし、完了を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/95bb4d64-b6ca-d809-71df-f0d05471d677.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/10dfb381-7c9c-dad6-8edc-2ee2f8f1aa37.png)

## 最後に
「サーバーは起動に失敗しました」の文しか出ないので、
何が原因なのか突き止めるのに苦労しました。

Eclipseで複数のサーブレット＆JSPのプロジェクトを作成しており、
サーバーを停止したり開始したりを繰り返していたせいかと思います。
他のプロジェクトを削除する必要もなく起動できたので、良かったです。
2023/6/13主にITとかセキュリティの記事

Minecraftプラグインにマルウェア発見、スキャンで感染の確認を(6/11)
https://news.mynavi.jp/techplus/article/20230611-2700794/

Google Chromeのゼロデイ脆弱性が積極的に悪用されている、確認と更新を(6/11)
https://news.mynavi.jp/techplus/article/20230611-2699370/

“マイナンバートラブル続出” ヒューマンエラーの実情とは？ デジタル化の必要性とは？【谷龍哉】(6/11)
https://www.kk-bestsellers.com/articles/-/2032823/

「マイナ保険証」に潜むデメリット“更新手続き怠り医療費10割負担”の悲劇、“高齢者の暗証番号持ち歩き”もリスク(6/11)
https://news.yahoo.co.jp/articles/7a72b5f3bd93ee78041c736f55d248d265c3fe84

「プリズム事件」は米国の「ハッカー大国」の本性を暴いた―中国外交部(6/10)
https://www.recordchina.co.jp/b915509-s12-c100-d0165.html

あなたのビジネスはAIに対応できていますか？まずはデータ管理プラクティスのチェックを【Cohesity JAPAN 笹岳二氏】(6/11)
https://news.mynavi.jp/techplus/article/20230611-2701843/

Z世代とは - 定義や特徴、ミレニアル世代との価値観や行動様式の違いを解説(6/11)
https://the-owner.jp/archives/14650

元総務省谷脇氏が説く、「データ駆動社会」づくりに必要な3要素とは(6/12)
https://xtech.nikkei.com/atcl/nxt/column/18/01651/060200041/
spaCyのmatcherでIPアドレスの置換

# 背景
spaCyは自然言語処理ライブラリとして使用でき、単語単位で分解して、品詞などで
分類することができます。また、mathcerを使用して、品詞や正規表現、数字、文字列の形式などで
マッチした部分を抜き出して処理したりすることができます。

今回は、spaCyでIPアドレスを一致した個所を置換する方法を記述します。

# 環境準備
以下のpython3とpipが使用できるようにしておくことが前提です。

言語: python3

以下のライブラリをインストールします。
ライブラリ: spaCy,ja_ginza(統計モデル)
```ライブラリインストールコマンド
pip install -U ja_ginza,ginza,spacy
```


# 実装

```ipreplace.py
import spacy
from spacy.matcher import Matcher

def ipreplace():
    # ja_ginzaモデルをロードして、モデル内のvocabオブジェクト(言語素やstrigstore)を基にマッチルールを作成します。
    nlp = spacy.load("ja_ginza")
    matcher = Matcher(nlp.vocab)
    message = "このIPアドレスは 192.168.3.2 と 10.3.3.4 が割り振られています。"
    # nlpで処理結果を保持する中核のオブジェクトを作成。docオブジェクトが生成されます。
    doc = nlp(message)
    # ここでは、「d,dd,dddのいずれかの形に数字が一致＋.」を繰り返したパターンを作成します。
    # 例えば、1,12,123のような形のいずれか
    pattern = [
        {"SHAPE":{"IN":["d","dd","ddd"]}},
        {"TEXT":"."},
        {"SHAPE":{"IN":["d","dd","ddd"]}},
        {"TEXT":"."},
        {"SHAPE":{"IN":["d","dd","ddd"]}},
        {"TEXT":"."},
        {"SHAPE":{"IN":["d","dd","ddd"]}}
    ]
    # 作成したパターンと一致したときのインデックスをmatcherに追加します。
    matcher.add("IPADDRESS",[pattern])
    # docオブジェクトのうち、patternに一致した文字列の開始、終了位置、インデックスを
　　# 一致した単語部分をリスト型として取得します。
    matches = matcher(doc)
    newMessage = message
    #　一致した情報(開始位置、終了位置、インデックス)がmatches[]に追加されているので、
    #　for分で取り出す。
    for match_id,start,end in matches:
        #docオブジェクトは開始、終了位置でsliceオブジェクトとして取り出せる。
        matchWord = str(doc[start:end])
        #テキストを一致した単語と置換する。
        newMessage = newMessage.replace(matchWord,"***.***.***.***")
    print(newMessage)

if __name__ == "__main__":
    ipreplace()
```
```
実行結果
>>> ipreplace.py 
このIPアドレスは ***.***.***.*** と ***.***.***.*** が割り振られています。
```


# ちょっと解説
コード内のコメントのほとんど書いているので補足程度


patternですが、dは数字を表します。
以下は、d,dd,dddの形のうち一つを含む形があることを示します。
なので、1,12,123のような数字の組み合わせのうち一つを検出します。
```
{"SHAPE":{"IN":["d","dd","ddd"]}
```
以下はIPアドレスの.(コンマ)を検出します。
```
{"TEXT":"."}
```
なので、この組み合わせを使用して、XXX.XXX.XXX.XXXやXX.X.XXX.XXなどの組み合わせを
検出するパターンを作成できます。

matcherに、docオブジェクトを渡し、patternに一致した
docオブジェクトの配列の位置とmatcher.addで設定したインデックスIDをmatchesに代入します。
```
matches = matcher(doc)
newMessage = message
```
for分でmatches内のオブジェクトを取り出して、docをstart位置、end位置でdocから切り抜きます。
切り抜いた単語を元のテキストより、置換します。
```
for match_id,start,end in matches:
        matchWord = str(doc[start:end])
        newMessage = newMessage.replace(matchWord,"***.***.***.***")
```
これで、置換が完了するので、置換後のテキストnewMessageを返すか、表示させるなどして使用します。

# 補足
match_idは、nlp.vocab.strings[match_id]で、mathcer.addで設定したインデックス名に変換できます。
```
for match_id,start,end in matches:
        print(nlp.vocab.strings[match_id])
```
```
表示結果
>>> IPADDRESS
>>> IPADDRESS
```
patternをいくつも作り、mathcer.addを複数化実施する際に、それぞれのmathcer.addにインデックスを別にして、
if分などで条件分岐をさせると、マッチした内容で処理を変えることができます。

# 参考URL
https://spacy.io/api/matcher
【Maven】ミラーサーバからMaven3.6.3がダウンロードできなくなった件について

## ミラーサーバ(Mirror Server)とは

インターネット上でデータやソフトウェアのコピーを提供するためのサーバ。
元のデータやソフトウェアを保持している「オリジナルサーバ」と連携して動作する。
（勝手に「オリジナルサーバ」って呼んでるけど、正式名称はわからない...😇）

## 今回の事象

`2023-06-09 10:13(JST)`にミラーサーバから`Maven3.6.3`が削除されたことで、ミラーサーバからバージョン3.6.3をダウンロードできなくなった。

正確に言うと...
オリジナルサーバから`Maven3.6.3`が削除され、それと連携してミラーサーバからも`Maven3.6.3`が消えた。

以下のサイトからも、`2023-06-09`時点でバージョン3.6.3のダウンロード情報が消えていた。
https://maven.apache.org/download.cgi

## Maven3.6.3をダウンロードする方法

以下にバージョン3.6.3がアーカイブされているから大丈夫😉
https://archive.apache.org/dist/maven/maven-3/

なんなら、ミラーサーバからダウンロードできる`3.8.8`と`3.9.2`もアーカイブからダウンロード可能。
（[オリジナルサーバ](https://downloads.apache.org/maven/maven-3/)から削除されるタイミングでアーカイブされるものかと思ってた）

## DockerfileでMaven3.6.3をダウンロードしている場合

Dockerfileで`Maven3.6.3`をミラーサーバからダウンロードするようになっている場合、
デプロイされてもMavenがダウンロードできないため、コンテナは起動しない......

対策としては、以下のようなものが考えられる
1. ダウンロード先をアーカイブにする
1. S3などのストレージサービスにダウンロードしてきて、それをダウンロード先にする
1. ミラーサーバからダウンロードできない場合に、アーカイブからダウンロードするようにする（3.8.8や3.9.2の場合）
📜Private Diary【AWSのRDS経由でMySQLクライアントをインストールするまで】

## はじめに
これは手順を記載した投稿ではありません。日々の個人日記になります。

## 導入
PF作成のため、環境開発に伴う学習を進めています。本日は、デプロイのためのデータベース学習を行いました。

## 内容
AWSのRDSを使い、MySQLをインストールすることができました。

<details><summary>RDSとは</summary>

「RDS（Relational Database Service）」は、AWSが提供するクラウド型のデータベースサービスです。データベース管理システムは、それ自体がソフトウェアですので、EC2サーバーにインストールすればデータベースサーバーを構築できます。MySQLとの互換性を持つAmazonAuroraやPostgreSQLとの互換性を持つAmazon Aurora、MySQL、MariaDB、PostgreSQL、Oracle、SQL Server の 7 つの人気エンジンから選択し、Amazon RDS on AWS Outposts でオンプレミスデプロイが可能です。
</details>

### 注意点①
RDSに限らずですが、AWSのサービスは無料枠と従量課金枠があります。無料枠の中で収めるためには必ず説明を理解した上で行う必要があると改めて感じました。
今回の利用するRDSは無料枠のため料金は発生しませんが、課金枠はEC2インスタンスと比較すると高額になるそうです。

### 注意点②
**RDSのDBインスタンスは停止から7日間、経過した後、8日目には自動的にインスタンスが起動します。
インスタンスを停止しただけですと、忘れている間にインスタンスが起動して課金されていくことがありますので十分注意してください。**

## 締め
現状、構築をしたのみでどういう仕組みで作成が出来たのかやはりわかっていません。そのため、この日記とともに振り返り忘れないようにしていきたいと思います。
毎日が勉強。これからも勉強。楽しく勉強。
以上
RailsGem kaminari利用について

最近開発でkaminariを触れる機会があったので、備忘録を作成しました。

### インストール
まずはGemfileに以下の行を追加し、bundle installコマンドを実行します。

```Ruby
gem 'kaminari'
```

### コントローラーの設定
ページネーションを適用したいアクションがあるコントローラーを開きます。例えば、app/controllers/items_controller.rbのようなファイルです。

そして、その中の一覧表示のアクション（通常はindexアクション）に対して、以下のように.page(params[:page])を追加します:
```ruby
def index
  @items = Item.order(:name).page(params[:page])
end
```
このコードは、:nameでソートされたItemを取得し、params[:page]に基づいてページネーションを適用します。

### ビューの設定
次に、ページネーションリンクを表示したいビューを開きます。これは一覧表示のビューであることが多いです。例えば、app/views/items/index.html.erbのようなファイルです。

そして、そのビューファイルの適切な位置に、以下のコードを追加します:

```ecr
<%= paginate @items %>
```

このコードは、コントローラーで設定した@itemsに基づいてページネーションリンクを表示します。



### ロケールの設定
Kaminariの表示文字列をカスタマイズするには、アプリケーションのロケールファイル（例：config/locales/ja.yml）に以下のように追記します：

```yaml
ja:
  views:
    pagination:
      first: "最初"
      last: "最後"
      previous: "前"
      next: "次"

```
この例では、日本語の翻訳を設定しています。"最初"、"最後"、"前"、"次"といった表示文字列を任意の文字列に変更できます。

なお、英語など他の言語についても同様に設定することができます。例えば、英語の場合は以下のように設定します：
```yaml
en:
  views:
    pagination:
      first: "First"
      last: "Last"
      previous: "Prev"
      next: "Next"
```
これらの設定を適用すると、Kaminariのページネーションリンクの表示文字列が変更されます。
Android Emulatorで「Cleartext HTTP traffic to ${IP} not permitted」エラーが出た場合の対応方法

# エラー内容
Cleartext HTTP traffic to ${IP} not permitted

# 原因
Android9からHTTP通信がデフォルトで無効になっている模様。

# 対策
AndroidManifest.xmlに「usesCleartextTraffic=true」を設定することで回避できる

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:usesCleartextTraffic="true" ← 追加
        tools:targetApi="31"> 

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
```
【JavaScript】JavaScriptの基本の基本

### JavaScriptの基本の基本の備忘録

・テキストエリアに記入したテキストが、アラートボタンを押すと表示される
  
```a.html
<script src = "a.js" ></script>
<!-- jsファイルを読み込む -->

<textarea id="textarea"></textarea>
<!-- textareaというidを持つテキストエリア -->

<button id="button">アラート</button>
<!-- buttonというidを持つアラートボタン -->
```

```a.js
document.addEventListener('DOMContentLoaded', () => {
// ウェブページが完全に読み込まれた後に特定の処理を実行するためのイベントリスナーを追加

  const buttonAlert = document.getElementById("button")
  // アラートのDOMを定義

  const textarea = document.getElementById("textarea")
  // テキストエリアのDOMを定義

  buttonAlert.addEventListener("click", () => {
  // アラートボタンをクリックした時というイベントを設定

  alert(textarea.value)
  // アラートの内容を設定
  })
});
```
Protocol Buffers定義を書かずにBigQuery Storage Write APIを使う (Node.js/TypeScript)

# ネタバレ

Node.js の `@google-cloud/bigquery-storage@3.4.0` で、テーブル名だけで Write API が使えるアップデートが入ったので、Protocol Buffersの定義を書かなくても使えるようになりました。

# BigQuery Storage Write API ってなあに

これを読んでください → https://cloud.google.com/bigquery/docs/write-api

BigQueryのテーブルにストリーミングでデータを入れるためのgRPCのAPIです。従来の`tabledata.insertAll`より安くて効率的。

ただし、Protocol Buffersのためのあれこれを書く必要があるなど、コード量が増えがちな印象です。外部テーブルとかWebコンソールとかで十分なら、そっちを使ったほうが楽で幸せ。

今回のこのアップデートで、Node.jsでは体感5割くらい手軽になりました。今までは1テーブルずつProtocol Buffersを書いていたのが、テーブル名を指定するだけになったので、共通化をちゃんとすれば複数のテーブルに送る手間が激減した印象です。

# 試し方

1. ↓にアクセス
https://www.npmjs.com/package/@google-cloud/bigquery-storage
2. Append_rows_table_to_proto2 [「OPEN IN GOOGLE CLOUD SHELL」](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigquery-storage&page=editor&open_in_editor=samples/append_rows_table_to_proto2.js,samples/README.md) を押すと、リポジトリがCloud Shellにクローンされます。
3. 指示通りインストールします。
    1. `cd samples`
    1. `npm i`
    1. `cd ..`
4. サンプルを動かすためのテーブルを作成します。
    1. [BigQuery](https://console.cloud.google.com/bigquery) で、テスト用データセットを作成
    1. 下のクエリでテーブルを作成
5. Cloud shell にて、`node samples/append_rows_table_to_proto2.js <your_project_id> <your_dataset_id> <your_table_id>` で実行

```sql
create table tmp.sample_data (
  bool_col bool,
  bytes_col bytes,
  float64_col float64,
  int64_col int64,
  string_col string,
  date_col date,
  datetime_col datetime,
  geography_col geography,
  numeric_col numeric,
  bignumeric_col bignumeric,
  time_col time,
  timestamp_col timestamp,
  int64_list array<int64>,
  struct_col struct<sub_int_col int64>,
  struct_list array<struct<sub_int_col int64>>,
  row_num int64
);
```

# TypeScript での使い方

サンプルはJavaScriptですが、TypeScriptで使いたいですよね。

普通にサンプルのJavaScriptのコードをTypeScriptっぽくしても、次の部分がすんなりとは動きません。`fromDescriptor`の型が定義されていないためです。


```typescript
import { Type } from 'protobufjs'
require('protobufjs/ext/descriptor')

const SampleData = Type.fromDescriptor(protoDescriptor)
```

これは、https://github.com/protobufjs/protobuf.js/issues/1499 を参考にすると、interfaceを自分で定義します。

```typescript
import { Type } from 'protobufjs'
require('protobufjs/ext/descriptor')
import { protos, adapt } from '@google-cloud/bigquery-storage'
// interfaceを定義
import { IFileDescriptorSet } from 'protobufjs/ext/descriptor'
interface Descriptor {
    fromDescriptor(
      descriptor: IFileDescriptorSet | protobuf.Reader | Uint8Array | protos.google.protobuf.DescriptorProto
    ): protobuf.Type;
}

const SampleData = (Type as unknown as Descriptor).fromDescriptor(protoDescriptor)
```

これ以外の部分は、TypeScript固有の難しいところはないと思います。
さくらのレンタルサーバーでPHPを使用する際の注意点

# はじめに
さくらのレンタルサーバー上で動いているWordPressの保守作業時にエラーを多発させてその対処をしていたのですが、その中で割と癖が強いと感じる要素があったのでメモとして残そうと思います。

# デフォルトのPHP用のメモリ上限が貧弱
ある処理をさせたときに

**「このサイトで重大なエラーが発生しました。対応手順については、サイト管理者のメール受信ボックスを確認してください。」**

と表示され、より詳細を確認するためにwp-config.php内で

```
define('WP_DEBUG', true);
```

と設定したところ**Fatal error: Allowed memory size of 134217728 bytes exhausted**と表示されました。

つまりデフォルトではPHP用のメモリの上限は128MBということで、プラグインの組み合わせや処理の中身によっては足りません。

# php.iniの挙動の癖がかなり強い

というわけでメモリの上限の設定を変更するわけですが、方法としてはwww内にphp.iniを作成し

```
memory_limit = 512M
```

と記載すればOKです。
そのphp.iniはコントロールパネル上に「スクリプト設定」->「php.ini設定」という項目があるのでそこから作成できます。

が、そこでphp.iniを作成して上記のメモリ上限の設定のみを記述すると**WPのテーマによってはログインすらできないほどに壊れます。**

その際に表示されるメッセージが以下のようなものです。
```
Warning: Cannot modify header information - 
headers already sent by (output started at （中略）functions.php:***) 
in /home/（中略）/pluggable.php on line ***
```

functions.php内に余計な空白を入れたときなどによく出るエラーですが特に何も編集はしていないので疑わしいものはphp.iniしかありません。

そこで「もともと存在しなかったのだからphp.iniを削除しよう」としてもなんと**元に戻りません。**

## 解決方法
php.ini内に

```
output_buffering = On
```

の記述を追加する。

意味合いとしては「Warningを画面に出さない」ということです。あくまでErrorではなくWarningなので出力さえしなければ普通に動きます。WPのテーマによってはそれを前提に動いているようです（それはそれでどうかと思いますが）。

## 逆に何故今まで動いていたのか
web.iniが無い場合、デフォルトではoutput_buffering = Onになっている？

## 何故web.iniを作っただけで動かなくなったのか
web.iniをコンパネで作成した場合、書いていない情報はデフォルトを反映**ではなく場合によってはOFFとして扱われる？**

## 何故web.iniを削除しても直らなかったのか
web.iniをコンパネで作成した場合、削除したとしてもデフォルトの設定を反映ではなく**www内しか参照しないようになる？**

# おわりに
なんとか対処はできましたが正直納得できていない挙動が多いです。十分なパターンを試したわけではないので憶測の域を出ないところもおそらく多いです。同様のトラブルが発生した際に参考にしていただければと思います。
【基本情報技術者】擬似言語の記述形式

# 擬似言語の記述形式
擬似言語を使用した問題では、各問題文中に注記がない限り、次の記述形式が適用されているものとする。

#### [擬似言語の記述形式]
|記述形式|説明|
|-|-|
|◯<INS>`手続名又は関数名`</INS>|手続又は関数を宣言する。|
|<INS>`型名`</INS> `:` <INS>`変数名`</INS>|変数を宣言する。|
|/* <INS>`注釈`</INS> */|注釈を記述する。|
|// <INS>`注釈`</INS>|注釈を記述する。|
|<INS>`変数名`</INS> ← <INS>`式`</INS>|変数に<INS>`式`</INS>の値を代入する。|
|<INS>`手続名又は関数名`</INS> (<INS>`引数`</INS>, ... )|手続又は関数を呼び出し、<INS>`引数`</INS>を受け渡す。|
|if (<INS>`条件式１`</INS>)<br> 　<INS>`処理1`</INS><br>elseif (<INS>`条件式2`</INS>)<br>　<INS>`処理２`</INS><br>elseif (<INS>`条件式n`</INS>)<br>　<INS>`処理n`</INS><br>else<br>　<INS>`処理n + 1`</INS><br>endif|選択処理を示す。<br>　<INS>`条件式`</INS>を上から評価し、最初に真になった<INS>`条件式`</INS>に対応する<INS>`処理`</INS>を実行する。以降の<INS>`条件式`</INS>は評価せず、対応する<INS>`処理`</INS>も実行しない。どの<INS>`条件式`</INS>も真にならないときは、<INS>`処理n + 1`</INS>を実行する。<br>　各<INS>`処理`</INS>は、0以上の文の集まりである。<br>　elseifと<INS>`処理`</INS>の組みは、複数記述することがあり、省略することもある。<br>　elseと<INS>`処理n + 1`</INS>の組みは一つだけ記述し、省略することもある。|
|while (<INS>`条件式`</INS>)<br>　<INS>`処理`</INS><br>endwhile|前判定繰り返し処理を示す。<br>　<INS>`条件式`</ins>が真の間、<INS>`処理`</INS>を繰り返し実行する。<br>　<INS>`処理`</INS>は、0以上の文の集まりである。|
|do<br>　<INS>`処理`</INS><br>while (<INS>`条件式`</INS>)|後判定繰り返し処理を示す。<br>　<INS>`処理`</INS>を実行し、<INS>`条件式`</INS>が真の間、<INS>`処理`</INS>を繰り返し実行する。<br>　<INS>`処理`</INS>は、0以上の文の集まりである。|
|for (<INS>`制御記述`</INS>)<br>　<INS>`処理`</INS><br>endfor|繰り返し処理を示す。<br>　<INS>`制御記述`</INS>の内容に基づいて、<INS>`処理`</INS>を繰り返し実行する。<br>　<INS>`処理`</INS>は、0以上の文の集まりである。|

# 参考
https://www.amazon.co.jp/%E5%85%A8%E6%96%87%E9%9B%BB%E5%AD%90%E7%89%88%E4%BB%98-%E3%81%8B%E3%82%93%E3%81%9F%E3%82%93%E5%90%88%E6%A0%BC-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E4%BA%88%E6%83%B3%E5%95%8F%E9%A1%8C%E9%9B%86-%E4%BB%A4%E5%92%8C5%E5%B9%B4%E5%BA%A6/dp/4295015741/ref=sr_1_19?keywords=%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85+%E9%81%8E%E5%8E%BB%E5%95%8F%E9%A1%8C%E9%9B%86&qid=1686580668&sprefix=%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85+%2Caps%2C178&sr=8-19
LINEトーク履歴集計アプリ開発③

## ユーザーに返す（ビュー）
前回まではサーバー側での一連の集計処理を作成したが、ユーザーに結果をみせなければならない

処理は単純で、txt_post.phpにて結果を出力するためのコードを加えていく
```txt_post.php
<?php
        ini_set("display_errors", 1);
        error_reporting(E_ALL);
        //ファイルが送信されていない場合はエラー処理
        if(!isset($_FILES['txt'])){
            echo 'ファイルが送信されていません。';
            exit;
        }
 
        $save = '../save/' . basename($_FILES['txt']['name']);
 
        //move_uploaded_fileで、一時ファイルを保存先ディレクトリに移動させる
        if(move_uploaded_file($_FILES['txt']['tmp_name'], $save)){
           echo 'アップロード成功！';
           sleep(2);
           $filename='/var/www/html/save/result/result.html';
 
           $fp=fopen($filename, 'r') or die("error");
 
           while(!feof($fp)){
              echo fgets($fp);
           }
           fclose($fp);
        }else{
           echo 'アップロード失敗！';
           exit;
        }
?>
```
filenameに代入したファイルのデータを出力するという内容だ


以上で完成だ

なお、ディレクティブのアクセス制御など細かい部分は記載していない

## 最後に
今回のアプリは最低限の機能しか実現できていない

セキュリティ面や排他制御に関しても未熟である

しかしながら、サーバの構築からここまで仕上げたのはとても大変であった
LINEトーク履歴集計アプリ開発② - 後編 -

[前回](https://qiita.com/shutax/items/6198a8200ca8d5ab774e)の続きだ
## コマンドライン引数を利用するためシェルスクリプトの作成
前半での記述の通り、testを実行するにはテキストファイル名も引数として渡さなければいけない

シェルスクリプトの内容は

- /saveディレクトリに存在するテキストファイルの名前を取得し、環境変数FILEに代入
- test実行時に引数として指定する
- 実行後はテキストファイルを削除する

とする


```hoge.sh
#!/bin/sh
 
 
export FILE=`find /var/www/html/save/*.txt`
echo "$FILE"
 
 
/var/www/html/save/test "$FILE"
 
rm -f  "$FILE"
```

:::note warn
パスは相対にしてしまうとincronでの設定時に読み込めなくなってしまう
絶対パスにするか、絶対パスを読み込むコマンドを指定するべし
:::


これにて./hoge.shをするだけで```test $FILE```を実行できるようになった

次はhoge.shを自動で実行する設定を作成する
## incronのインストール
incronはファイルシステムの変更をトリガーに、決められた処理を実行するコマンドである

ユーザーがアップロードしたファイルをリアルタイムで処理する必要があるため使用する

```$sudo apt update```

```$sudo apt install incron```
## crontabにて処理の流れを登録
```$incrontab -e```

設定を登録する画面になる

監視対象のディレクトリ      イベント      実行する処理・コマンド

と記述する

```incrontab
/var/www/html/save      IN_CREATE           /var/www/html/save/hoge.sh
```
**/var/www/html/saveにファイルが作成されたらhoge.shを実行する**

という処理だ

:::note warn
incronでは必ず絶対パスで記述されたし 
:::
LINEトーク履歴解析アプリ開発①

前回の記事より、今回は一つ目の処理である**スマホからエクスポートしたテキストファイルをフォームからアップロード**についての記事だ
# テキストファイルのアップローダー作成
投稿フォームはPHPで作る
PHPのインストール方法は[こちら](https://qiita.com/shutax/items/88ca17ce03bdee61dfbc)を参考にされたし
## 手順
①ディレクトリを作成
②投稿用フォーム、**txt_form.php**を作成・編集
③投稿後の処理をする, **txt_post.php**を作成・編集

構造は以下に

/save
      |- txt_form.php
      |- txt_post.php
      |- アップロードされた.txt
### ディレクトリ作成
PHPファイル、およびアップロードされたファイルを保存するディレクトリを作成する

筆者はドキュメントルート下にsaveというディレクトリを作成し、そこにPHPファイルとアップロードされたテキストファイルを保存する

```$sudo mkdir save```
### txt_form.phpの編集
txt_form.phpに記述する
```txt_form.php
<!DOCKTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=yes" />
<title>暫定版LINE解析アプリ</title>
</head>
<body>
 
<form action="txt_post.php" method="POST" enctype="multipart/form-data">
    <p>
        <input type="file" name="txt">
    </p>
    <p>
        <input type="submit" value="送信する">
    </p>
</form>
 
</body>
</html>
```
スマホ・パソコンでも最低限見やすい（レスポンシブ対応）ページになっている

パソコン↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3418025/00521dc7-863d-016e-e39e-8334f2577486.png)

スマホ↓
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3418025/8b472bca-b221-498a-9c65-6425aa26038f.png"/>

### txt_post.phpの編集
```txt_post.php
<?php
        ini_set("display_errors", 1);
        error_reporting(E_ALL);
        //ファイルが送信されていない場合はエラー処理
        if(!isset($_FILES['txt'])){
            echo 'ファイルが送信されていません。';
            exit;
        }
 
        $save = '../save/' . basename($_FILES['txt']['name']);
 
        //move_uploaded_fileで、一時ファイルを保存先ディレクトリに移動させる
        if(move_uploaded_file($_FILES['txt']['tmp_name'], $save)){
           echo 'アップロード成功！';
        }else{
           echo 'アップロード失敗！';
           exit;
        }
?>
```
$save変数に、アップロードされたテキストファイルを保存するディレクトリのパスを代入する

またbasenameを使うことにより、/var/www/html/save/txt_post.phpに直にアクセスされた場合は「ファイルが送信されていません」と出力するようになっている
Flexboxを使用した複数カラムレイアウトの作成方法

## 概要
HTMLとCSSを使用して複数カラムレイアウトを作成する方法を紹介します。ここではFlexboxを用いてレイアウトを作ります。

## 2カラムレイアウトの場合
### 1. HTMLの記述

まず、以下のようなHTMLを記述します。

```html
<!DOCTYPE html>
<html>
<head>
  <title>Two Column Layout</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>

<body>
  <div id="container">
    <div id="left-column">
      <!-- Left column -->
      Left Column
    </div>
    <div id="right-column">
      <!-- Right column -->
      Right Column
    </div>
  </div>
</body>
</html>
```

このコードでは、`id="container"`のdiv内に2つのdivを作り、それぞれ左カラムと右カラムを表現しています。

### 2. CSSの記述

次に、`styles.css`という名前のCSSファイルを作成し、以下のようにCSSを記述します。

```css
#container {
  display: flex;
}

#left-column {
  width: 25%;
  background-color: #f8f9fa; /* Light gray */
  padding: 20px;
}

#right-column {
  width: 75%;
  background-color: #fff; /* White */
  padding: 20px;
}
```

このCSSでは、`#container`に`display: flex;`を適用することで、その子要素（`#left-column`と`#right-column`）をフレックスアイテムとして並べています。また、`#left-column`と`#right-column`にはそれぞれ異なる背景色とパディングを適用し、幅もそれぞれ指定しています。

了解しました。タイトルを`複数のカラムのレイアウトの作成方法`に変更し、3カラムレイアウトの作成例も追加します。

## 3カラムレイアウトの場合
### 1. HTMLの記述

まず、以下のようなHTMLを記述します。

```html
<!DOCTYPE html>
<html>
<head>
  <title>Multi Column Layout</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>

<body>
  <div id="container">
    <div id="left-column">
      <!-- Left column -->
      Left Column
    </div>
    <div id="center-column">
      <!-- Center column -->
      Center Column
    </div>
    <div id="right-column">
      <!-- Right column -->
      Right Column
    </div>
  </div>
</body>
</html>
```

このコードでは、`id="container"`のdiv内に3つのdivを作り、それぞれ左カラム、中央カラム、右カラムを表現しています。

### 2. CSSの記述

次に、`styles.css`という名前のCSSファイルを作成し、以下のようにCSSを記述します。

```css
#container {
  display: flex;
}

#left-column {
  width: 20%;
  background-color: #f8f9fa; /* Light gray */
  padding: 20px;
}

#center-column {
  width: 60%;
  background-color: #e9ecef; /* Slightly darker gray */
  padding: 20px;
}

#right-column {
  width: 20%;
  background-color: #fff; /* White */
  padding: 20px;
}
```

このCSSでは、`#container`に`display: flex;`を適用することで、その子要素（`#left-column`, `#center-column`, `#right-column`）をフレックスアイテムとして並べています。また、各カラムにはそれぞれ異なる背景色とパディングを適用し、幅もそれぞれ指定しています。

## 注意点
以上の方法を元に複数カラムレイアウトが実現できますが、スクリーンサイズに応じたレスポンシブデザインを適用するためには、メディアクエリ等を用いてスタイルの調整を行う必要があります。具体的なレスポンシブデザインの実装方法は、プロジェクトの要件に応じて適切に設計してください。
LINEトーク履歴集計アプリ開発　～概要～

興味本位で作ってみた

①～③の構成で投稿しようと思う

まずは概要から
## 処理の流れ
処理は大まかに以下の３つ

①スマホからエクスポートしたテキストファイルをフォームからアップロード
↓
②アップロードされたテキストファイルを読み込み、集計、出力
↓
③ユーザーに返す（ビュー）

## 環境
- Ubuntu Server22.04 LTS
- Apache2.4
- PHP8
- gcc11
Laravel基本の流れ② 認証画面を作ろう。(Laravel Breezeを導入する）

　前回で、環境設定と基本画面、データベースの作成が終わりました。現在は下のページ`welcome.blade.php`だけが存在している状況です。

![名称未設定のデザイン (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959841/cb417c59-81df-71c6-c8d4-6f4d1c297c55.png)

　これに必要なページや機能をつけていくことになりますが、認証機能（ユーザー管理・ログイン管理）は多くの場合必要となるため、ライブラリが用意されています。これを導入すると簡単に認証管理を行うことができます。今回はLaravel Breezeというライブラリを使用します。

### Step.1 ファイルをダウンロード、インストールする
　まずは忘れずにprojectへ移動しておきましょう。
```
cd Laravelproject
```
この状態で、必要なファイルをダウンロードします。
```
./vendor/bin/sail composer require laravel/breeze --dev
```
続いてこれをインストールします。
```
./vendor/bin/sail php artisan breeze:install
```

・「使用する言語は何にしますか？」　-> 今回は「blade」を指定します。
・「ダークモードを使用しますか？」 -> お好みで。
最後にもう1問ありますが、これは「no」で大丈夫です。

### Step.2 npmをインストール、ビルドする
　その他に必要なパッケージをインストールし、ビルドします。次のコマンドを順に実行しましょう。
```
./vendor/bin/sail npm install
./vendor/bin/sail npm run build
```

### Step.3 migrateを実行し、Breezeを実装する

　処理が終わったら、次のコマンドを実行してBreezeを実装します。
```
./vendor/bin/sail php artisan migrate
```

　`localhost`にアクセスしてみると、

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959841/500ef393-6154-0138-6abf-d614217da71d.png)

　分かりにくいですが、右上に`Log in` と`Register`があり、すでに「ログイン機能」と「ユーザー登録機能」が実装されています。例えば、`Log in`をクリックしてみると

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959841/e112d612-1fe5-bd63-fe0e-97f2f2771997.png)

　このようなログイン画面ができていることが分かります。　
　当然このページのコードもproject内に出来ているので、そこを書き直せばデザイン・機能を変更・追加することが可能です。

　また、「localhost:8080」にアクセルしてデータベースを見てみると、
`failed_jobs`
`migrations` 
`password_resets` 
`personal_access_tokens` 
`users`
の５つのテーブルができています。このうち`users`が登録したユーザーを管理するテーブルとなります。

### Step.4 テストユーザーの作成（※任意）
　Laravelには「seeder」という機能があり、テスト用のユーザーを簡単に作成することができます。必須ではありませんが、開発する際には便利ですので、そのやり方も記しておきます。

project内
　database -> seeders -> DatabaseSeeder.php　を次のように編集します。


```php:DatabaseSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run()
  {
    // 🔽 この行がコメントアウトされているので、アクティブにする
    \App\Models\User::factory(10)->create();

    // 🔽 こちらはそのまま
    // \App\Models\User::factory()->create([
    //     'name' => 'Test User',
    //     'email' => 'test@example.com',
    // ]);

  }
}
```

1行分のコメントアウトを外すだけです。
文章も「Modelを介してUsersテーブルに10個のデータをcreateしてね」という感じに読めますね。

できたら、ターミナルで

```
php artisan db:seed
```
を実行します。

データベースを確認してみると、10人分の架空のユーザーが登録されています。
Step.3で作ったログイン画面からログインできるか確認をしてみましょう。
下のような画面に移ることができればログインできています。この画面もあとでデザインなどを変更していきましょう。

:::note info
パスワードは「ハッシュ化」といって暗号化されていますが、全員「password」です。
:::

![phpmyadmin image phpmyadminphpmyadmin links - mysqlmysql ports - 808080 environment MYSQL_USERNAME ${DB_USERNAME} MYSQL_ROOT_PASSWORD ${DB_PASSWORD} PMA_HOST mysql networks - sail (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959841/f1f84efb-9a5d-93fe-7478-109d5775125f.png)

次の記事

https://qiita.com/taisuke-m/items/d2e556d5de0c2352bae6
【備忘録】転職活動で感じたこと

# 初めての転職活動で感じたこと

２人目の出産時期前に挑んだ、人生初の転職活動で感じたことがたくさんあったので備忘録としてここに残していきたい。（10年後くらいに自分でこの記事を読んで恥ずかしくなりたい）

Qiitaはマークアップで書かれていることを知らなかったので、いきなり技術的な話から書いていくよりは、こういったポエム的な記事から書くことから始められて良かったと思う笑
10年後はGPT系のAIが勝手にアウトプットしてくれるんでしょうか。。それまでにアウトプットの習慣を身につけて、AIに入力する過程のみで脳に学習した知識を刻み込みたいものです。。

# 目次<br>

・自分のスペック
・失敗したこと
・得たもの・こと
・次回の転職活動で継続してやっていきたいこと・新たにやりたいこと
・最後に


結論としては、スキルアップを名目としたこの転職活動は大失敗であったし、収穫も多かった活動になったと思う。

## 自分のスペック

まずは本文への導入として、自分のスペックから書いていこうと思う。

・20代、新卒から4年目
・妻子持ち、妻はアメリカ人、今月２人目出産予定
・新卒未経験でSES事業の派遣大手(?)会社に就職
・現在は請負部隊にて、インフラの構築、移行を主に担当

大学を休学してインドのバンガロールに行ったときに感じたUberやMaaSの普及によるインド人の雇用生産を感じITエンジニアに夢見て、現在はインフラエンジニアとしてやっております。

## 失敗したこと

今回失敗したこととして、

・技術的知識が不足しているところがかなり面接中に露呈してしまった

というところが一番大きいところとしてあるかなと感じました。エンジニアとして大反省です。

## 得たもの・こと

失敗したことの裏返しではありますが、

・3年後までに代表的なパブリッククラウドのアソシエイトレベル、5年後までにはプロフェッショナルレベルの資格を取得し、国内国外関係なく働けるエンジニアというところが言語化できたこと。できれば、海外でインフラエンジニアとして働いている人をモデルとして見つけたい<br>
・今やるべきことは、毎日インプットしてしっかり言葉に出せるようにする。英語学習、筋トレと同じように毎日何かに触れるように環境、習慣を作る。その環境、習慣作りのツールとして、今後Qiitaを活用していきたい。<br>
・AWSのBlackBeltや、developersIOのリアルイベントの存在等を知れたことは、今後活用していきたいと思いました。


## 次回の転職活動で継続してやっていきたいこと・新たにやりたいこと

今回はエージェントさんを通じての転職活動だったので、次回また使いたい（企業さんとの面談調整、課題提出、知らない企業さんの求人票選定と思った場合）場合の備忘録を記載する。


・エージェントさんは、忙しくない人に担当してもらう（存在するかは不明）
・出産時期と転職活動時期はずらすべき（人生に大きく関わることを同時に進行すると、ストレス過多⇦わかってはいたけど、強烈）
・モンスター飲んでエンジンかける
・1ヶ月半を見込んでの活動を心がける（あまり落ちすぎるとエージェントさんが気を遣って求人のレベルを落としてくれる気がした）
・書類選考は数打つこと
・書類選考が通った後は、企業さんによって事前課題の提出が求められる
・求人票に書いてある面接の情報は、実際は出社しての面接等がwebでできる場合があるので、エージェントの担当の方によく面接情報を聞くこと
・面接の練習は１回でも多い方が良い
・エージェントの方から伝授される企業様から質問されるであろうリストの信頼率は50％。あまり鵜呑みにし過ぎず、しっかり自分のことを言語化できるようにしておくこと。
・現職で意識的に課題を解決しておくこと。何にぶつかって、それに対してどう解決するのかを考える。

## 最後に
また1年後を目標に転職活動をしていきたいので、多少3年後の目標を早めてでも達成し、次に転職活動するまでには、子育てをしつつ、環境・習慣作りのところを頑張っていきたいと思います。まずは14日のAWS re:Invent参加するぞー！！
個人勉強用クラウドの利用料金が1月5万くらいかかってしまった話("マネージドサービス"は起動してるだけでお金がかかる)

## ことの発端
個人用Google Cloudを使っていて、通常1,000円くらいの利用料だったのだが4月分としていきなり51,976円の請求書が来て焦ってしまった。

↓こんな請求書がきた
![スクリーンショット 2023-06-12 20.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3311265/25c878a7-ab4a-8bf0-bf32-0828971d19d6.png)

慌ててCloud Billingを確認したところ課金の要因はAlloyDB(Google CloudのマネージドPostgreSQL)だった。
4/13くらいからずっと起動していて、毎日2,500円くらいずつ課金が発生してしまっていたのだ。

↓こんな感じ
![スクリーンショット 2023-06-12 20.42.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3311265/1d7da022-9ae5-c45c-cc80-e36d65ff85f6.png)

## 高額課金を引き起こした直接原因
第３者視点で見ると、起動していたのだからお金がかかって当然ではないかと思われるかもしれないが、その時期は業務で他のGoogle Cloudサービスも合わせて調査しており、BigQueryやCloud Run等利用した分だけ課金がされるサーバレスサービスも多く目にしていた。

そこで、AlloyDBも起動した時間ではなく利用した分(クエリした分、保管したデータ分)だけ課金と思い込んでしまったのだ。
(リソース作ったとしても、特に触っていなければ微課金で済むだろうと思い込んでいた。)

しかし、[PostgreSQL 向け AlloyDB の料金](https://cloud.google.com/alloydb/pricing?hl=ja)を見ればわかるように、AlloyDBは起動した時間だけ課金される料金体系であり(vCPUだけ見ても「$0.08458 / vCPU hour」と記載してある。)、初歩的なミスによる自業自得なのである。

## サーバレスとマネージドサービスの違いを意識していなかったことが根本原因
課金に関わることなので、きちんと課金体系を確認すべきであったのだが、なぜ確認できていなかったのだろうか。
それは、サーバレスとマネージドサービスの違いを意識できていなかったことにあると考える。

両者の違いは以下のブログ等で触れられているが、自分がわかりやすいようにデフォルメして解釈すると以下の違いがあると考える。

・サーバレス→サーバはユーザーの元に __ない__(サーバレス)。使いたい時にクラウド事業者からリソースを借用する。
・マネージドサービス→サーバはユーザーの元に __ある__。運用管理をクラウド事業者が代行してくれているだけ。(マネージド)

マネージドサービスはあくまで運用管理がマネージドなだけで、__(仮想)サーバが確かにユーザーの元に存在するため、IaaS(VM)と同じように起動した分だけ料金がかかる__ のである。


そこの理解が曖昧でサーバレスのサービスとマネージドサービスをなんとなくクラウド事業者が管理してくれる便利な代物くらいの認識でいたため、全てのサービスがサーバレスのような"実際に利用した分"だけ払えば良いものだと都合の良い解釈をしていたのである。

https://cloud.google.com/blog/ja/topics/developers-practitioners/serverless-vs-fully-managed-whats-difference

## 最後に(所感)
ある程度クラウドに慣れてきたかなという驕りがあり思い込みで進めてしまったため、なるべくして発生してしまった事象かと反省。
仁和寺の和尚の教えではないが、安心しそうになる時こそ一層注意をすることを再度心がけようと思う。
(ちなみに、会社のアカウントでも同時期に同様のミスをしていて、会社の方でも数万円の費用を使ってしまってました。。。謝って許してもらいました。。。)