OmniAICreator/Qiita-1.07M huggingface dataset:
トラブルを上手に生かす方法～プロジェクトを最大限活用する～

## はじめに
プロジェクトが無事に完了。しかし、その過程で必ずトラブルに見舞われたはず… 全てのプロジェクトが上手く進めば良いのですが、これは避けられない宿命でもあります。

プロジェクトが完了した後には、忙しくてつい次に進んでしまいがちです。しかしながら、完了後にこそプロジェクトの神髄が隠されているというもの

単に次に進むのではなく、一旦立ち止まって総括することが大切です。問題点を洗い出し、改善するべき点は何だったのか。チームとしてどう対応できたか。個人個人の行動を見つめ直す。


そうした振り返りがあってこそ、某サイヤ人や某シャーマンの王のように死線をくぐった経験を次に活かすことができるのです。
## 目次

- 振り返りの前に…メンバーを称え合う
- 振り返りとフィードバック
- 取捨選択をして次につなげる
- まとめ

## 振り返りの前に…メンバーを称え合う
プロジェクトは1人では成し遂げられません。多くのメンバーの協力があってこそ完遂することができるのです。

その中でメンバーへの感謝を忘れてはいけません。これは、チームの仲を深めるという目的以上に次のプロジェクトにも大きく関わってきます。

会社で進めていく以上、同じメンバーで次のプロジェクトを担当することも珍しくないと思います。そのような時にこそ、メンバーのことをどれだけ把握できているかで成功度に直結します。

メンバーのことを把握できていることで、配役や仕事を振る際の粒度などを調整することも難しくないと思います。そのような状況だとメンバーも仕事を進めやすくなります。

また、トラブルを乗り越えたメンバーと仕事をする際には、「このままではまずい」と過去の事例からトラブルに対する嗅覚とセンスが身についており、話が早く進み結果的にトラブルを回避できることもあるでしょう。

しかし、プロジェクトが終わり即解散。という形でメンバーを称えたり、ねぎらったりしない場合リーダーはメンバーのことを的確に把握できないですし、メンバーもリーダーに協力してくれなくなります。

次のプロジェクトをトラブルなく進めるためにも、まずは具体的に言葉でメンバーに感謝を伝え、お互いにたたえ合うことで「厳しい状況だったけど最後は良かった」という状況をメンバーと共有しておくことが、次につながります。

## 振り返りとフィードバック
メンバーを称え合い、打ち上げをして次も頑張ろう！と終わらせるとプロジェクトは次に進めません。

称え合いの後は、プロジェクト全体を振り返る作業に入ります。トラブルの発生経緯と原因、対処の試行錯誤の過程、チームとしての対応など、できる限り詳細に振り返ることが重要です。

プロジェクトの当初は何が起こるのか、どうしていけばいいのかわからない状態でした。しかし、完了後は「何が起きたか」「どうすべきであったか」が自分の経験で理解できているはずです。

この経験を思い出しつつ、「もう一度プロジェクトをやり直すなら何をするか？」を考えます。こうすることで事前に何を準備し、どのような判断が必要かが経験を通して理解できます。

このように個人の経験を元に振り返りを実施した後は、組織へのフィードバックも大切です。背景や根本的原因、解決へのアプローチ、組織としての課題をまとめて組織としても協議する。

自分の経験を組織全体にも共有することで、次のプロジェクトへのトラブル防止を組織単位で見直すことができるでしょう。

## 取捨選択をして次につなげる
振り返りとフィードバックを経て、次のプロジェクトに向けて取捨選択を行う必要があります。トラブルから得た教訓の中でも、優先順位を付けることが重要です。全ての課題に取り組むのは現実的ではありません。

チェックリストなどを作成するのが一般的ですが、総合的にプロジェクトを振り返り他でも応用ができるのか？発生の確率はどの程度か？など不要なものを全て組み込むのではなく選択した上で次につなげるのが大切です。

## まとめ
プロジェクトのトラブル解決後、チームで振り返り、フィードバックを行い、取捨選択をすることで、次のプロジェクトに向けた糧を得ることができます。お互いを称え合い、絆を深めることから始まるこのプロセスは、成長と改善に向けた大切なサイクルなのです。

失敗は決して無駄ではありません。そこから学び、前に進む原動力としましょう。チームの力を最大限に活かし、プロジェクトから得た教訓を次に確実につなげていくことが何より重要なのです。

## 一緒に働く仲間を募集しています！
株式会社コネクター・ジャパンでは一緒に働いてくれる仲間を募集しています！

事業拡大に伴い、エンジニアを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/cnctor/about
▼代表メッセージ
https://cnctor.jp/10years-anniversary/
▼応募はこちら
https://www.wantedly.com/companies/cnctor/projects
PythonのUnionをなるべく使わないで欲しい件について

## はじめに
Pythonの型ヒントにおいて、`Union`は複数の型を受け入れることができる便利な機能です。しかし、`Union`の過度な使用は、コードの可読性や保守性を低下させる可能性があります。本記事では、`Union`をなるべく使わないようにすべき理由について説明します。


## 内容
ここでは2つの`Union`を使って欲しくないケースについて説明します。

### ケース1
```main_union.py: 
from typing import Union

U = Union[str, int] # str | int でも可

def test_union_change(p: U):
    if isinstance(p, str):
        p = 1

v = "1"
test_union_change(v)
```

上記のプログラムに対して`mypy`で静的解析すると、もちろん通ります。

```bash
% mypy main_union.py
Success: no issues found in 1 source file
```

上記についてあまり問題に思わない方もいるかもしれませんが、変数の役割を考えた時に、変数の型の変化を許容した方が良いケースは稀有なのかなと思います。（筆者は入力時点で型を複数許容するケースは良いと思っています。）

変数の型の変化を許容しない場合は、ジェネリック型を用いて以下のように書けます。

```main_typevar.py:
from typing import TypeVar

T = TypeVar("T", str, int)

def test_typevar_change(p: T):
    if isinstance(p, str):
        p = 1

v: str = "1"
test_typevar_change(v)
```

上記のプログラムに対して`mypy`で静的解析すると、エラーを返してくれます。

```bash
% mypy main_typevar.py
main_typevar.py:7: error: Incompatible types in assignment (expression has type "int", variable has type "str")  [assignment]
Found 1 errors in 1 file (checked 1 source file)
```

### ケース2
次に`Union`が使われると想定される例として、辞書型のケースを紹介します。

```main_union_dcit.py
from typing import Union

U = Union[str, int]

def test_union_change(p: U):
    if isinstance(p, str):
        p = 1

d: dict[str, U] = {'name': 'Alice', 'age': 20}
test_union_change(d['name'])
```

上記のプログラムに対して`mypy`で静的解析すると通ります。

```bash
% mypy main_union_dict.py
Success: no issues found in 1 source file
```

上記の問題は`name`に`int`型が入るケースと`age`に`str`型の変数が入るケースを静的解析で対策できないことです。

`Union`を使わずに`dataclass`などを使うと変数の型の変化を許容しません。

```main_dataclass.py
from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

def test_dataclass_change(person: Person):
    if isinstance(person.name, str):
        person.name = 1

alice = Person(name='Alice', age=20)
test_dataclass_change(alice)
```

上記のプログラムに対して`mypy`で静的解析すると、エラーを返してくれます。

```bash
% mypy main_dataclass.py
main_dataclass.py:10: error: Incompatible types in assignment (expression has type "int", variable has type "str")  [assignment]
Found 1 error in 1 file (checked 1 source file)
```


## `Union`を使わなければいけないケース/使った方がいいケース
上記で`Union`を使わずに、ジェネリック型や`dataclass`を使って欲しいと書きましたが、`Union`を使わなければならないケースもあります。

例えば返り値が`Union`になっている既存ライブラリや過去実装を使うケースです。

次に`dataclass`を定義している時間がないというケースです。ただこのケースで`Union`を使っているのならば、静的解析をしている意味が半減していると思いますし、そもそもスピード重視ならば`Union`などの型アシスト自体をつけない方が良いんじゃなかろうか、というのが個人的な意見です。（一方でスピード重視と型重視の中間で`Union`を使うというのが主張な気もしますし、一定理解はできます。)

最後に@Yosh31207様からコメントいただいた`Union`を使った方が良いケースについて紹介します。

```python 
Command = Union[Move, Stop, Attack] # Move | Stop | Attack

def make_commands() -> list[Command]:
```

上記例のように複数の型を許容する配列に関しては、ジェネリックスは適さず、`Union`を使った方が良いです。
(`Move | Stop | Attack`の上位クラスを定義し、その上位クラスを型アシストで用いた場合、`Union`よりも型安全性が落ちてしまうので、`Union`が最適となります。)

@Yosh31207様、ありがとうございます！

## おわりに
いかがだったでしょうか。

`Union`を使わない方がよい場面では、ジェネリック型や`dataclass`を検討していただければと思います。
SAP BTP 宛先サービスからプロパティ情報を取得する方法

お疲れ様です。

今回はSAP BTP Cockpitの宛先サービスからプロパティ情報を取得する方法について調査しました。

## やりたいこと
1）Javaから宛先サービスに接続し、宛先サービスに設定している情報を取得する

## 事前準備
・宛先サービスに必要情報を設定する。
１）コネクティビティ＞宛先
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/198c4388-6e74-bc4b-0320-f1e9131a7990.png" width=80%>

## サンプルコード
・mail.smtp.portを取得するサンプルコード
＜test.java＞
```
@Component
@RestController
public class Test {

    @GetMapping("/sendTest")
    public String sendTest() {
        // 宛先サービスからプロパティ情報を取得
        DestinationService service = new DestinationService();
        DestinationProperties individualProperties = service.getDestinationProperties("mail_destination");
        String smtpHost = individualProperties.get("mail.smtp.port").toString().substring(5, individualProperties.get("mail.smtp.port").toString().length() - 1);
        return smtpHost;
    }
}
```

## 結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500270/67050dec-1d2f-06e3-b93c-fe4dae4e3e98.png" width=80%>

宛先サービスに設定している内容が無事取得できましたね。
あとはこれを使って焼くなり煮るなり。。。
私はこれを使ってSAP BTPからメール送信する仕組みの一部を構築しました。
その際のお話はまた次回にでも

## 参考サイト
・SAP Cloud SDK
https://sap.github.io/cloud-sdk/docs/java/features/connectivity/btp-destination-service
【コピペ用】Flutterでよく使うpackageをいっぺんにinstall

駆け出しFlutterエンジニアのこたです。

個人的によく使うpackageをコピペでいっぺんにinstallできるように下にまとめてみました。
yamlファイルはコピペしづらかったり、バージョンを最新にできなかったりないので、terminalで実行する方を選んでいます。
※fvmを使うことを想定しています。

**追記**：
[osakiさん](https://zenn.dev/motu2119)の親切なご指摘を参考にして、`freezed`や`build_runner`はdev_dependenciesに追加するようにしました。
僕みたいにpubspec.yamlファイルのdev_dependenciesとdependenciesの違いがわかっていない人はこちらの記事を参考にされると良いと思います（僕も参考にさせていただきました🙇）
簡単に引用させて頂くと、以下のような理解で良いのかなと思います。

>dependencies
>->チーム開発において、みんな使わないとエラーが出てしまうPackage
>dev_dependencies
>->->チーム開発において、アプリのビルドの時に必要にならないPackage

https://qiita.com/isekiryu/items/123f1f2835af1ffc3423

# コード
```
fvm flutter pub add -d freezed
fvm flutter pub add -d build_runner
fvm flutter pub add flutter_hooks
fvm flutter pub add hooks_riverpod
fvm flutter pub add riverpod
fvm flutter pub add flutter pub add shared_preferences
fvm flutter pub add auto_route
fvm dart pub global activate flutter_gen
```
他によく使うpackageがあれば教えてください！
基礎的なHTML

HTMLを実際に入力して結果を返してみました。
基本的に以下のHTMLタグを押さえておきます。<br>
<table>
  <caption>HTMLのタグ</caption>
  <thead>
    <tr>
      <th>名前</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> h1~h6 </td> <td>見出し</td>
  </tr>
  <tr>
    <td> p </td> <td>テキストの段落</td>
  </tr>
   <tr>
    <td> ul </td> <td>順序なしリスト</td></tr>
     <tr>
    <td> ol </td> <td>順序付きリスト</td></tr>
    <tr>
    <td> li </td> <td>リストの項目を表示する</td></tr>
    <tr>
    <td> br </td> <td>改行</td></tr>
    <tr>
    <td> a </td> <td>リンク設置</td></tr>
    <tr>
    <td> img </td> <td>画像埋め込み</td></tr>
    <tr>
    <td> !-- -- </td> <td>コメントアウト</td></tr>
     
</table>
<br>

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>試しにやってみた</title>
</head>
<body>
    <h1>タグの見出し１</h1>
    <h2>タグの見出し２</h2>
    <h5>タグの見出し５</h5>
    <h6>数が大きいほど字が小さくなります。</h6>

    <p>ここに1つ目の段落を記述</p>
    <p>ここに2つ目の段落を記述</p>
    <ul>
       <li>順序無しリスト１</li> 
       <li>順序無しリスト２</li>
    </ul>

    <ol>
        <li>順序付きリスト1</li>
        <li>順序付きリスト2</li>
    </ol>
    改行文章1<br>
    改行文章2<br>

    <!-- Ctrl＋C＋Kでもコメントアウトできます -->

    <a href="https://qiita.com/">QIITAへのリンク</a>
    <br>
    <img src="https://cdn.pixabay.com/photo/2023/08/19/13/42/water-8200502_1280.jpg" alt="">

</body>
</html>
```

以下のように記載されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765031/43ff0cb8-7ba5-dc4c-1b4b-11f93322dc96.png)
レスポンスデータの設計


3.1 データフォーマットはどうする?

A.現在の主流は、「JSON」である。
理由は、Web業界で主流のJSやその他の言語で扱いやすいデータ構造であり
*シンプルでかつサイズが小さい*からである。

時と場合に応じて、「XML」に適用させるデータ構造の方が理想である。

3.1.1 データフォーマットの指定方法

Q.JSON以外のデータフォーマットを扱わなければいけない時はどうする?

A.真っ先に考慮しなければならない時は、「*クライアントにどのように取得したい形式を指定させるべきか*である。」

EX
クライアントにXMLデータを取得させたい。→どのようにサーバにそれを伝えるべきだろう??

-1 クエリパラメータを使う方法

クエリパラメータを使うURIを用意して、「データ形式を指定する方法である。」

EX
URI
「https://api.example.com/v1/japan?fromat="json"」のような形式をとるパターンである。
    
-2 拡張子を使う方法

拡張子
「https://api.exaple.com/japan*?user.json*」

拡張子を上記のようにして指定する方法もある。


-3 リクエストヘッダでメディアタイプを指定する方法
リクエストヘッダを扱う方法

EX
 ------- | ---------------- | ---  | 
| GET:    | /v1/users        |     | 
| Host:   | api.example.com  |     | 
| Accept: | application/json |     | 



Acceptでデータ形式を指定することで、指定したデータ形式の情報を取得できる。
**複数指定することができ、順序は左から順番に取得することができる**


複数使うなら、メディアタイプを使う方法/一つのパラメータ・・クエリパラメータ


3.4 各データのフォーマット

データ名前のルール

-1 多くのAPIで同じ意味に利用されている。 (わかりやすくするため)
-2 なるべく少ない単語数で表現する　(わかりやすくするため)
-3 複数の「単語を連結する場合、その連結方法はAPI全体を通して統一。（説明は省略→単純に　わかりにくくなるから)
-4変な省略形は使用しない。　(説明は省略→ 単純に、他者へ通じにくいから)

:::note 
ただし、APIを社内など限定的に利用する場合は例外として短縮形で利用することがある。あくまでも例外である。
:::
※
※**コラム**
LSUDsとSSKDSで区分させる。
LSUDSは大規模なAPI→さまざまな開発者にも使ってもらえるようなAPI設計にすることが必須

SSKDSは社内向けなどの規模が限られてるAPI

LSUDSより、SSKDSの方が考慮するポイントは少ない。
性別情報のユースケース

sex「生理的な性別」だと値が数値で表記されることがある。

1男性
2女性
3その他

　一方で、genderで表記されることもある、
その際はテキストがたで表記する。

LSUDSは、テキストが好ましい。と言うのも、一目でわかりやすいからである。

-5 単数系、複数形に気を付ける


3.4.3 日付フォーマット
ここでは簡潔に表現・説明する。

LSUDSでは、「**RFC 3339 **」
これまでに日付フォーマ


ットの問題を解決し、読みやすく、使いやすいものを目指してインターネット上で用いる標準形式であるから。

μsまできちんと表記される。
(省略)

3.5レスポンスデータの設計

結論、APIのユースケースごとによく考え、「ユーザが最もシンプルに扱うことができる構造設計を考えた方がベストである。」
APIが不便だと、使いにくいAPIという認識に陥る。クライアントがエラー発生について分かっても
どんなエラーが生じたのか、わからないとどう対応すれば良いかわからなくなるからである。

3.6   エラー表現
では、どんなエラー表現がベストだろうか??
まずはステータスコードが明記されているエラーである。ステータスコードは、今何が起こってるのかわかりやすいデータである。
200, 300,400,500番。それぞれに理由がありわかりやすいため、ステータスコードはポイントである。
VSCode でのタブキーでの半角スペースの数を変更する

# これなに
できるだけデフォルトで使用しているものの、でもこれは欲しいと思う設定がいくつかある。
会社で新しいマシン供給された時などにタイムマシーン使えないとかだとツラいので、念のための備忘録。

# 設定手順
## Settings を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/e0a309c3-3df0-188a-272a-87cad0919626.png)

## 以下の設定を行う、以上
- Tab size = 2 (Default: 4)
- Detact Indentation = false (Default: true: そのファイルの書き方に合わせるか否か)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/7a12f1cc-5f51-9c1f-48be-7d6630b5a8ae.png)
TypeScript + Jestをdocker環境で構築する

# はじめに
TypeScript+Jestをdocker環境で構築したときのメモ記事です。
コードをぺたぺた張っていきそこにメモを残していく。


# 内容
## Dockerfile
イメージはnode:20を使用当時のLTS。
ENVでnode_modulesを環境変数に指定しないとTypeScriptがコンパイルできなかった。
`COPY ./app/package*.json ./`これがないと`RUN npm install`時にpackage.jsonから依存関係を取得できない。
```dockerfile
FROM node:20

WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY ./app/package*.json ./

RUN npm install
```


## docker-compose.yaml
build：contextは特に気にせずルートディレクトリ、Dockerfileを使うのでdockerfileも追加
tty：コンテナの終了を防ぐ。
volumes：localの内容をすぐにコンテナ環境に反映するため。node_modulesをマウントの対象から外すために`/app/node_modules`を記述。
woring_dir：Dockerfileで`WORKDIR`書いてるからいらないかも？
```yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    volumes:
      - ./app:/app
      - /app/node_modules
    working_dir: /app
```

## package.json
jestのところだけメモ。
transform：テストファイルが実行される前に特定の処理を行う。.ts,.tsxの拡張子にts-jestを適用する。
ts-jestは、JestをTypeScriptに対応させるためのものです。ts-jestを入れると、TypeScriptで書いたテストコードを、コンパイルの手間なしにそのまま実行できるようになる。

testRegex：テストと認識するファイルを正規表現で定義。今回はtestsディレクトリ内のすべてのファイルもしくは特定の拡張子の場合。
```json
{
    "name": "typescript-jest-app",
    "version": "1.0.0",
    "description": "",
    "scripts": {
      "test": "jest"
    },
    "dependencies": {
      "@types/jest": "^26.0.23",
      "jest": "^26.6.3",
      "ts-jest": "^26.5.6",
      "typescript": "^4.2.4"
    },
    "jest": {
      "transform": {
        "^.+\\.tsx?$": "ts-jest"
      },
      "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
      "moduleFileExtensions": [
        "ts",
        "tsx",
        "js",
        "jsx",
        "json",
        "node"
      ]
    }
  }
```
# GitHub
- https://github.com/motoo1789/jest-example/tree/main

# 追記
TypeScriiptだけでなにかアプリを作るのは難しいので、
別記事でフレームワークを使ったJest環境の記事を作るかも
Tableau ダッシュボード作成Tips

# 概要
ここではTableauのダッシュボード作成に関する基本的なことや小技などを書き留めていきます。

# ダッシュボードの画面設定を変える
- sizeからかえることができる。基本Automaticでいいかも
![スクリーンショット 2024-04-07 15.30.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/58f48d61-72cc-7e93-67f8-96a8814df3ca.png)

# 最初の初動について
タイルで垂直オブジェクトや水平オブジェクトを配置するとサイズを変更したり、自由に動かすことができない。
一番最初は垂直オブジェクトもしくは水平オブジェクトをタイルで置いて、そのあとはフロートでオブジェクトを置いた方がいいかもしれない。
しかしフロートだと自動的にサイズ調整などがされない(手動ですることになる)のでタイルで行った方がきっちりダッシュボードの大きさに合ったものができる


# 水平オブジェクトと垂直オブジェクトについて
関連するオブジェクトを一緒にグループ化し、ユーザーの操作時にダッシュボードでサイズ変更を微調整できる、レイアウト コンテナを提供します。

# 水平オブジェクトと垂直オブジェクトに枠線をつける
以下画像のようにフォーマットからボーダーなどで枠線をつけることができる
![スクリーンショット 2024-04-07 15.33.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/37a9b36c-c415-88bd-812f-db6d314a4475.png)

# コンテンツごとに大きさを揃える
以下の画像のようにする
![スクリーンショット 2024-04-07 15.54.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/80a93c16-f4e5-d85a-bff5-f612cee6ffa6.png)

# 元のシートのタイトルの位置について
- 真ん中にすると
![スクリーンショット 2024-04-07 15.58.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/4be84da1-8249-6b01-3924-87db5a0164fb.png)

- ダッシュボードのところも真ん中になる(以下画像はfit>entire viewも使用している)
![スクリーンショット 2024-04-07 15.59.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/4bd1a19d-a88b-9ef6-da95-bf075841ed6e.png)

# 数値をシートタイトル名の真下に来るようにしたい
- テキスト>alignment>holizontalの真ん中の3本線が描かれているものをクリック
![スクリーンショット 2024-04-07 16.03.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/bdb01c5e-eac6-b97a-3651-705f2af58f76.png)

そうするとダッシュボードで真ん中になります。
![スクリーンショット 2024-04-07 16.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/ba6f40f8-04e4-a5f4-8e15-05117ed6e1a5.png)

# ダッシュボードの背景を塗る
- Dashboard>format>Dash board shading>Defaultの色をかえる
![スクリーンショット 2024-04-07 16.16.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/0cfccc66-8410-0d9f-ab31-4c52c68dca81.png)

- 以下画像のように背景が塗られる
![スクリーンショット 2024-04-07 16.17.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/820a53a9-603c-465e-328c-ca705b82c2fa.png)

# シートごとに背景を塗りたい
- 以下のようにformatからバケツマークを選び、default>worksheetで色を塗ることができる、ダッシュボードの色と同じにすると統一感がでる
![スクリーンショット 2024-04-07 16.19.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/fbd06d1c-36ca-b6ce-237a-976cc30f0cfd.png)

# 簡単なフィルターの付け方
- フィルターしたい値のフィうルターをオンにする
![スクリーンショット 2024-04-07 16.30.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/80bc9718-b811-74aa-d305-ad9199bb7c71.png)

- ダッシュボード内のフィルターをつけたいvizのフィルターをオンにする
![スクリーンショット 2024-04-07 16.31.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/60c80973-60cf-66d2-0ae6-45f0f198de95.png)

- 他のvizの項目をクリックすることで他のvizも連動してビューが変わるようになりました
![スクリーンショット 2024-04-07 16.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555220/0807402a-3f3a-dfd0-fa71-99b844931097.png)

上記で作ったviz
https://public.tableau.com/app/profile/.18056109/viz/ADVANCEDTABLEAUDASHBOARD1/Dashboard1?publish=yes
# 参考資料
webhookとweb APIについてなんとなく理解する

## この記事を読んでわかること
webhookとAPIの違いについてなんとなく理解できるかも..?

### API
クライアント（ユーザーのブラウザやアプリケーション）がTwitterのAPIエンドポイントにリクエストを送信します。
Twitterのサーバーがそのリクエストを受け取り、即座にレスポンスを返します。

コード例（Twitter APIから最新のツイートを取得）：
```ruby
require 'twitter'

client = Twitter::REST::Client.new do |config|
  config.consumer_key        = "YOUR_CONSUMER_KEY"
  config.consumer_secret     = "YOUR_CONSUMER_SECRET"
  config.access_token        = "YOUR_ACCESS_TOKEN"
  config.access_token_secret = "YOUR_ACCESS_SECRET"
end

tweets = client.user_timeline('twitter_user')
puts tweets.first.text
```
```css
[クライアント] ------> [Twitter API エンドポイント] -----> [Twitter サーバー] -----> [クライアント]
    リクエスト          リクエストを処理してレスポンスを返す            レスポンス
                   イベントのデータ                   イベントの処理
```

### Webhook
Twitterのサーバーが特定のユーザーが新しいツイートを投稿したときに、あらかじめ設定されたWebhookエンドポイントに通知を送信します。
クライアント側のWebhookエンドポイントはその通知を受け取り、対応する処理を実行します。

コード例（RailsでWebhookを受け取るエンドポイントを設定）：
```ruby
# config/routes.rb

Rails.application.routes.draw do
  # Webhookを受け取るエンドポイントを定義
  post '/twitter/webhook', to: 'twitter_webhook#receive'
end

# app/controllers/twitter_webhook_controller.rb

class TwitterWebhookController < ApplicationController
  skip_before_action :verify_authenticity_token

  def receive
    # Webhookからのデータを処理する
    webhook_data = JSON.parse(request.body.read)
    
    # 特定の処理を実行する（例：新しいツイートがあった場合）
    if webhook_data['event'] == 'tweet'
      tweet_text = webhook_data['data']['text']
      puts "New tweet: #{tweet_text}"
    end

    # 応答を返す
    head :ok
  end
end
```

```css
[Twitter サーバー] -------> [Webhook エンドポイント] -------> [クライアント]
      イベント通知                       イベントのデータ                   イベントの処理
```

### まとめ
このように、APIはクライアントがリクエストを送信し、サーバーが即座にレスポンスを返すのに対して、Webhookはサーバーがイベントが発生したときにクライアントに通知を送信し、クライアントがその通知を受け取って対応する処理を実行する仕組みです。
CSV/JSONを扱う際にオススメのVSCode拡張機能

#### 背景

仕事や個人開発でVSCodeを利用しておりますが、開発中もそれ以外でもCSVやJSONデータファイルを扱うことが多く、VSCodeでデータ内容を確認する機会も増えました。
そこでデータ内容の確認に便利な拡張機能をいくつか紹介したいと思います。

先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが**自分のメモ**として、こちらへまとめておきます。

## CSVやJSONデータファイルを扱うために便利な拡張機能一覧

1. [Rainbow CSV](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#raibow-csv)
1. [CSV to Table](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#csv-to-table)
1. [CSV to JSON Converter](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#csv-to-json-converter)
1. [Excel Viewer](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#excel-viewer)
1. [Data Wrangler (Preview)](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#data-wrangler-preview)
1. [Edit CSV](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#edit-csv)
1. [JSON Crack](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#json-crack)
1. [JSON formatter](https://qiita.com/_whitecat_22/items/63cc60228853d97edb06#json-formatter)

## Raibow CSV

https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv

主な機能：
- カンマ (.csv)、タブ (.tsv)、セミコロン、パイプで区切られたファイルの列を異なる色でハイライトします
- 組み込みのSQLライクなクエリー言語（RBQL）を使ってテーブルを変換し、フィルタリングします
- ホバー時にカラムに関する情報を表示します

## CSV to Table

https://marketplace.visualstudio.com/items?itemName=phplasma.csv-to-table

主な機能：
- CSV/TSV/PSVファイルをASCII形式の表に変換します
- CSV関連のデータをメールやSlackルームに貼り付けたいときは重宝します

## CSV to JSON Converter

https://marketplace.visualstudio.com/items?itemName=Chukwuamaka.csvtojson-converter

主な機能：
- 「CSVをJSONに変換」または「JSONをCSVに変換」します

## Excel Viewer

https://marketplace.visualstudio.com/items?itemName=GrapeCity.gc-excelviewer

主な機能：
- 拡張子：.csv、.tsv、.tabのファイルについて、エクスプローラのコンテキストメニューまたはエディタのタイトルメニューから「プレビューを開く」コマンドを呼び出すことでファイルの内容がFlexGridコントロールに表示され、カラムヘッダーによるソートやフィルタリングがサポートされます

## Data Wrangler (Preview)

https://marketplace.visualstudio.com/items?itemName=ms-toolsai.datawrangler

主な機能：
- データクリーニングを行うデータサイエンティストの生産性を向上させることを目的としており、Pandasコードを自動的に生成し、洞察に満ちたカラム統計とビジュアライゼーションを表示するリッチなユーザーインターフェイスを提供します  
2024/04/07時点ではpreview版ですがとても高機能です
 (python実行環境が必要です お持ちの方はぜひ試してみてください）

## Edit CSV

https://marketplace.visualstudio.com/items?itemName=janisdd.vscode-edit-csv

主な機能：
- エクセルのようなテーブルUIでcsvファイルを編集できます

# JSON Crack

https://marketplace.visualstudio.com/items?itemName=AykutSarac.jsoncrack-vscode

主な機能：
- 複雑なJSONデータセットを情報豊富で視覚的なグラフに簡単に変換できます データ構造の確認に便利です

## JSON formatter

https://marketplace.visualstudio.com/items?itemName=ClemensPeters.format-json

主な機能：
- JSONデータを階層別にフォーマットして表示します


---
#### (編集後記)

拡張機能は各々好みがあるかと思います。今回紹介したもののうち [Reainbow CSV](https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv) はいろいろなところで紹介されていますが、それ以外の拡張機能は意外と！？紹介例が少なかったため、実際に利用して便利と感じたものを掲載しました。
python使いとして、csvデータはついついpandasデータフレームにして確認してしまうのですが、コードを書く手間も省きたいときは拡張機能で確認することで、時間短縮、効率化につながりました。
もちろん容量の大きなデータは拡張機能を利用しても表示しきれなかったり、そもそも表示できなかったりすることもありますのでそこはpythonやExcel、Accessなどとの使い分けが必要です。

みなさまがお使いの拡張機能で、これも良き！というものがありましたらコメントなどでご教示いただけると嬉しいです:pray:
brewでghostscriptのインストールが失敗する場合の対処

現在(2024/04/03時点)`brew install ghostscript`を実行すると以下のエラーで失敗する場合があります。

```sh
./pdf/pdf_sec.c:187:20: error: incompatible integer to pointer conversion assigning to 'int *' from 'int'; take the address with
```

このエラーは既に報告され、失敗する原因となっているコードは下記のリンクで修正されています。

https://bugs.ghostscript.com/show_bug.cgi?id=707649

しかし、まだこの修正を行ったバージョン(10.04)はまだリリースされておらず、新バージョンが出るまでは一工夫が必要です。

## 対処法

一番簡単なのは、`--HEAD`オプションを使って最新のソースコードをインストールすることです。

```sh
brew install ghostscript --HEAD
```

`--HEAD`オプションはリポジトリの最新のコードを取得するオプションです。
通常の開発ではあまり使わないオプションですが、頭の片隅に入れておくと今回のケースの場合などで役に立ちます。
AWS Systems Managerのステートマネージャーの関連付けを適用させ、Amazon Inspecter v2の検出結果にアップデート後の内容を反映させる

# 経緯

Amazon Inspecter v2（以降は『Inspecter』と呼ぶ）が検出した脆弱性に対応するため、ライブラリのアップデートを実施した。しかし Inspecter の検出結果にはライブラリを更新した結果が反映されていなかった。

1時間後に Inspecter の検出結果を再確認すると、ライブラリアップデートで対応した脆弱性は検出されなくなっていた。これでもよいのだが、上司や顧客に対応済であることをすぐに証明できるよう、Inspecter の検出結果にライブラリアップデートした内容がすぐに反映できるようにしたい。

# 結論

AWS Systems Manager （以降は『SSM』と呼ぶ）のステートマネージャーにある、 **InspectorInventoryCollection-do-not-delete** の関連付けを今すぐ適用させることで、スキャン結果をすぐに表示できる。


# 補足

AWS公式サイトによると、Inspecter の EC2 スキャンには２通りの方式があるとのこと。

https://docs.aws.amazon.com/ja_jp/inspector/latest/user/scanning-ec2.html

今回ライブラリのアップデートを行った EC2 インスタンスは、SSM のエージェントがインストールされたマネージドインスタンスであったため、Inspecter はエージェントベースのスキャンを実施していた。

またエージェントベースのスキャンでは、Inspecter は EC2 インスタンスのソフトウェアアプリケーションインベントリ収集のため、SSM のステートマネージャーの InspectorInventoryCollection-do-not-delete という名前の関連付けを自動作成し利用する。

>Amazon Inspector では、ソフトウェアアプリケーションインベントリを収集するために、お客様のアカウントに Systems Manager ステートマネージャーの関連付けが必要です。まだ存在しない場合は、Amazon Inspector によって InspectorInventoryCollection-do-not-delete という名前の関連付けが自動的に作成されます。

ただ自動作成された InspectorInventoryCollection-do-not-delete の関連付けはデフォルトだと30分毎に実施されるため、検出結果にはすぐに反映されない。

>Amazon Inspector は、初回スキャンが完了すると EC2 インスタンスの [最終スキャン日] フィールドを更新します。この後、Amazon Inspector が SSM インベントリを評価したとき (デフォルトでは 30 分ごと)、またはインスタンスに影響を与える CVE が Amazon Inspector データベースに新たに追加されたためにインスタンスが再スキャンされたときに、[最終スキャン日] フィールドが更新されます。

よって検出結果にスキャン結果をすぐに反映したい場合は、関連付け今すぐ適用させると反映できる。

Inspecter は v2 になってからは SSM マネージドインスタンスに対して自動スキャンしてくれる便利な機能なので、随時使いこなしていきたい。

# 参考文献

https://docs.aws.amazon.com/ja_jp/inspector/latest/user/what-is-inspector.html

https://docs.aws.amazon.com/ja_jp/inspector/latest/user/scanning-ec2.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-state.html
GoogleMobileAds周りでシミュレータでのビルドができなかった

# 起こったこと
とあるプロジェクトを久しぶりにXcodeひ開いて、ビルドしてシミュレータで動作確認しようとしたところ、下記のようなエラーが表示されてビルドができませんでした。

```
あとでやり直してください。 
Failed to load Info.plist from bundle at path /[パス]/GoogleMobileAds.framework;
Extra info about "/[パス]/GoogleMobileAds.framework/Info.plist": Couldn't stat /[パス]/GoogleMobileAds.framework/Info.plist: No such file or directory
```

調べてみたところ、XcodeがGoogleMobileAds.frameworkのInfo.plistファイルをロードしようとして失敗しているっぽい。

# 試したこと
* とりあえず、Clean Build Folder（shift + cmd + K）
    * 解消せず
* Xcode 再起動
    * 解消せず

# 解消方法
GoogleMobileAdsが問題っぽいので、[GoogleMobileAds](https://github.com/googleads/swift-package-manager-google-mobile-ads)をアップデートしました。

Swift Package Manager でライブラリを管理していたため、
File > Packages > Update to Latest Package Versions
で、GoogleMobileAds をアップデートしました。
これによって、9 → 11.2.0 まで上げました。

これで再度ビルドしたところ、正常にシミュレータで動作確認することができました！
Git操作コマンド集

よく忘れるコマンドを自分用に整理。都度更新します。

# Remote repo関連
```bash: 登録されているリモートリポジトリを確認
git remote -v
```

```bash: originのURLを変更
git remote set-url origin new_git_repository_url
```

```bash: originにリポジトリURLを追加
git remote set-url --add origin {New git repository url}
```

# Branch関連
```bash: remote branchを元にlocal branchを作成
git checkout -b local_branch_name origin/remote_branch_name
```
```bash: 削除済みでlocalに残っているremote branchを削除
git fetch --prune
```
# Add関連
- HEAD(直前のコミット)まで`git add`の変更履歴を取り消す

```bash: 特定のファイルのみ取り消し
git reset HEAD file_name
```

```bash: 全てのファイルを取り消し
git reset HEAD
```

- git init直後まで`git add`の変更履歴を取り消す ※初期化されるので注意

```bash: 特定のファイルのみ取り消し
git rm --cached -r file_name
```

```bash: 全でのファイルを取り消し
git rm --cached -r .
```

# Commit関連
```bash: 直前のコミットを取り消し
git reset --soft HEAD^
```

```bash: 直前のコミットメッセージ変更
git commit --amend -m 'Change message'
```

- 引数の説明
  - `--soft`: ワークディレクトリの内容はそのままでコミットだけを取り消したい場合に使用
  - `--hard`: コミット取り消した上でワークディレクトリの内容も書き換えたい場合に使用
  - `HEAD^`: 直前のコミットのこと
  - `HEAD~{n}`: n個前のコミットを意味する

# Push関連
```bash: Push便利コマンド
git push -u origin branch_name
```
- 引数の説明
  - `-u`: `--set-upstream`の省略形。リモートリポジトリのブランチを追跡するように設定。次回から`git push`だけでリモートリポジトリにpushできるようになる。


# 参考 - Special Thanks
- [【git-remote】 複数のリモートリポジトリへ同時に Push する](https://www.coppla-note.net/posts/git-multi-remotes/)
- [[Git]コミットの取り消し、打ち消し、上書き](https://qiita.com/shuntaro_tamura/items/06281261d893acf049ed)
- [git add を取り消す](https://qiita.com/yukure/items/89562e5eb1d03995dc5b)
StackViewをコードだけで実装してみた

### はじめに

アプリ開発に興味があり、主にSwiftやUIkitの勉強しています。
自分が詰まったところなどを中心に発信していこうと思っています。

StackViewをコードだけで実装してたことがなかったので
今回チャレンジしてみました。

### サンプルコード

```Swift:
import UIKit

final class UIStackViewVC: UIViewController {

    private let redLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .systemRed
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private let greenLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .systemGreen
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private let yellowLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .systemYellow
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private let blueLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .systemBrown
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private let stackView: UIStackView = {
        let stackView = UIStackView()
        stackView.backgroundColor = .systemCyan
        stackView.distribution = .fillEqually
        stackView.alignment = .center
        stackView.spacing = 8
        stackView.axis = .horizontal
        stackView.translatesAutoresizingMaskIntoConstraints = false
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        stackView.addArrangedSubview(redLabel)
        stackView.addArrangedSubview(greenLabel)
        stackView.addArrangedSubview(yellowLabel)
        stackView.addArrangedSubview(blueLabel)
        view.addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -24),
            stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 24),

            redLabel.heightAnchor.constraint(equalToConstant: 50),
            greenLabel.heightAnchor.constraint(equalToConstant: 50),
            yellowLabel.heightAnchor.constraint(equalToConstant: 50),
            blueLabel.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
}

```


StackViewの制約はどこを変数にするのか考えながらやるといいのかなと思います。
今回はlabelのwidthを変数にすることでlabelの数を変更した場合でも
柔軟に対応できるようになってます。
PDO トランザクション

# PDO トランザクション `beginTransaction`, `commit`, `rollback` の3種類のメソッドを使用する

__●__ トランザクション: まとめて処理

- 参考: [PDOクラス](https://www.php.net/manual/ja/class.pdo.php) 

- 使用されるシチュエーション例:
銀行ATM: 残高を確認->Aさんから引き落とし->Bさんに振込などこれらを全部まとめて処理をする（もし、何か問題があれば元に戻す）。

```php:index.php
<?php

require 'db_connection.php';

$sql = 'select * from contacts where id = :id'; // ? を付けるか : を付ける(プレースホルダ)

// トランザクション: まとめて処理 beginTransaction, commit, rollback
$pdo->beginTransaction(); // トランザクションを始める

try {
    // sql処理
    $stmt = $pdo->prepare($sql);
    $stmt->bindValue('id', 2, PDO::PARAM_INT);
    $stmt->execute();
    // 他にもsql処理があればこの中で追加していく
    $pdo->commit(); // 処理をまとめて実行
} catch (PDOException $e) {
    $pdo->rollBack(); // 更新のキャンセル(元に戻す)
}
```

例外で書く `try{} catch(){}`
tscとvite-plugin-checkerの型チェックの違いについて理解する

:::note
# 結論
vite-plugin-checkerとtscコマンドの違いは型エラーでビルドを中止させるかどうかということでした
:::

# 1. 背景

業務でViteを使っています。

Viteはデフォルトでは型チェックはしてくれません。

https://vitejs.dev/guide/features#typescript

あるプロジェクトでは型チェックに`vite-plugin-checker`を使用しています。

https://www.npmjs.com/package/vite-plugin-checker

他のプロジェクトでは`tsc`コマンドを使用しています。
```package.json
"scripts": {
    "build": "ENV=DEV tsc --noEmit && vite build --mode localdev",
```
https://www.typescriptlang.org/tsconfig#noEmit

それで2つの違いを理解しようと思いました。

# 2. tscとvite-plugin-checkerの違い

https://vite-plugin-checker.netlify.app/checkers/typescript.html

Documentを見ましたがtscとvite-plugin-checkerの型チェックの違いは分かりませんでした。

## 型エラーでビルドを中止させるかどうか

https://saunabouya.com/2023/08/08/vue-js3-laravel-typescript-plugin-checker

`tsc --noEmit`の際は型エラーが起きたらビルドを中止してくれます。
一方でvite-plugin-checkerの場合はターミナルで型エラーを表示しますが、ビルド自体は完了します。

# 3. 最後に
- vite-plugin-checkerとtscコマンドの違いは型エラーでビルドを中止させるかどうかということでした
- tscコマンドをviteとは別で実行する方式の方がCIで異変に気付けるかなと思いました

# 4. 参考
- [WebpackからViteに移行する](https://tech.iimon.co.jp/entry/2023/03/17/000000)
- [15日目: vite-plugin-checker を探訪](https://furikake555.hatenablog.com/entry/2023/12/07/000000)
- [Laravel x Vue.js x TypeScript x Viteでvite-plugin-checkerを入れて型チェックを行う](https://saunabouya.com/2023/08/08/vue-js3-laravel-typescript-plugin-checker)

本記事を読んで頂き、ありがとうございました。
いいねいただけると記事執筆の励みになりますので、参考になったと思われた方は是非よろしくお願い致します🙏

:::note
弊社は積極採用活動中です。
もし気になっていただけたら[採用ページ](https://recruit.iimon.co.jp/)までよろしくお願いします。
:::
ITパスポート 情報資産と脅威

・情報資産
組織が保持しているすべての情報
・脅威
損失を与える原因
・脆弱性
情報資産に内在している弱点

・脅威の種類
物理的脅威、人的脅威、技術的脅威
・共連れ
正規の認証を受けた人がセキュリティエリアに入室する際に、別の人が認証を受けずに共に入室すること
・アンチパスバック
入室の記録がない人を退室させないようにすること
・セキュリティゲート
一人ずつしか通れない
・ソーシャルエンジニアリング
コンピュータを使わずに人の心理や行動の隙を突いて機密情報を入手する行為
・ショルダーハッキング
画面を肩越しからのぞき見する
・トラッシング
ゴミ箱に捨てられた紙から機密情報を入手する
・クリアスクリーン
離席時に画面をロックする
・クリアデスク
書類などが盗まれてもすぐわかるように机を整理しておく
・不正のトライアングル理論
不正行為は、機会、動機、正当化の三つの条件が揃ったときに行われる

・マルウェア
悪意をもって作成されたソフトウェア
・コンピュータウィルス
感染、潜伏、発病の機能をもつ
・ワーム
自己増殖しながら、ネットワークを介して拡散する
・マクロウィルス
表計算ソフトなどのマクロの機能を悪用する
・トロイの木馬
利用者に有用なソフトウェアとみせかけてインストールさせ、裏では不正な処理を行う
・スパイウェア
利用者に気づかれないように、個人情報やアクセス履歴などを収集する
・キーロガー
キーボード操作の内容を不正に収集する
・ボット
感染した端末を外部からの指令で操り、特定サイトへのDos攻撃、DDos攻撃などを行う
・ランサムウェア
端末内のファイルを暗号化し、戻すためのパスワードと引き換えに金銭を要求する

・ウィルス対策ソフト
コンピュータウィルスの検知、駆除、隔離などができるソフトウェア
ウィルスの検知には、既知のウィルスの特徴を識別できるシグネチャコードを記録したウィルス定義ファイルを使用する
・ファイルレスマルウェア
ファイルを生成しないタイプのマルウェア

・ゼロデイ攻撃
脆弱性が存在するソフトウェアのセキュリティパッチが事業者から提供される前に、その脆弱性を悪用した攻撃
・セキュリティホール
OSやソフトウェアの設計ミスなどで生じた、セキュリティ上の欠陥
・バッファオーバーフロー攻撃
プログラムが用意している入力用のデータ領域を超えるサイズのデータを送り付け、想定外の動作をさせる

・ダークウェブ
通常の検索では表示されず、またアクセスのために専用ソフトが必要なウェブサイト
WSLセットアップ個人的ベストプラクティス

# 前提
WSLを便利に使うための設定をまとめました。  
Ubuntuを選択しているため、Ubuntuの設定についても最低限まとめています。  
他にもオススメの設定があれば、ぜひ教えてください。  

## 動作環境
```:コマンドプロンプト
C:\Users\pon2g>wsl --version
WSL バージョン: 2.0.0.0
カーネル バージョン: 5.15.123.1-1
WSLg バージョン: 1.0.57
MSRDC バージョン: 1.2.4485
Direct3D バージョン: 1.608.2-61064218
DXCore バージョン: 10.0.25880.1000-230602-1350.main
Windows バージョン: 10.0.22621.3374
```

# WSLの設定
`/etc/wsl.conf`を変更する設定を紹介していますが、コマンドプロンプト or PowerShellから`wsl --shutdown`を実行し、WSLを再起動する必要があります。  
設定の詳細は、当たり前ですがMicrosoftのリファレンスが詳しいです。  
https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config

## Windowsのファイルにパーミッションを設定できるようにする
デフォルトではWindows側のファイルのパーミッションが`777`になっているため、コンソールの見た目がよろしくありません。  

```:/etc/wsl.conf
[automount]
options="metadata"
```

## Windowsのパスを引き継がないようにする
`echo $PATH`を叩くと、`/mnt/c/Program Files (x86)/...`がずらずら表示されます。  
見た目がよろしくありません。  

```:/etc/wsl.conf
[interop]
appendWindowsPath=false
```

## systemdを有効にする
WSLでは、systemd以外の独自のinitプロセスが動いているらしい。  
そのため、systemdに依存したアプリケーションを動かせず不便です。  
WSLバージョン0.67.6以上であれば、以下によりsystemdを有効化できます。  

```:/etc/wsl.conf
[boot]
systemd=true
```

## hosts、resolv.confを初期化されないようにする
せっかく編集した`hosts`、`resolv.conf`も、WSLを再起動するたびに初期化されます。  

```:/etc/wsl.conf
[network]
generateHosts=false
generateResolvConf=false
```

## VPN環境下での名前解決
テレワーク中、自宅からVPNで社内LANに接続し、社内サーバのGitリポジトリにアクセスしようとすると、名前解決ができないようで困りました。  

https://zenn.dev/xeres/articles/2023-10-05-install-wsl-vpnkit

# Windowsの起動に合わせてWSLを自動起動させる
UTF-8以外のロケールを設定しているときや、お気に入りのターミナルがある場合、WSL上のLinuxにSSHアクセスしたくなります。  
WSLを起動して、ssh.serviceが起動されるまで待って…というのが面倒です。  
以下のファイルをWindowsのスタートアップに追加しておきます。  

```vb:runWSLbackground.vbs
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c wsl", vbhide
```

# Ubuntuの設定
## プロキシ設定
WSLからの通信は、Windowsで設定したプロキシ設定が適用されません。  
プロキシ環境下でWSLからインターネット接続する際には、以下の設定を行います。  

```shell:bash.bashrc
export ftp_proxy="http://<proxy URL>:<port>"
export http_proxy="${ftp_proxy}"
export https_proxy="${ftp_proxy}"
export FTP_PROXY="${ftp_proxy}"
export HTTP_PROXY="${ftp_proxy}"
export HTTPS_PROXY="${ftp_proxy}"
```

## aptのプロキシ設定
aptは、環境変数で指定したプロキシ設定を読み込まないらしい。  

```:/etc/apt/apt.conf
Acquire::ftp::proxy "ftp://<proxy URL>:<port>/";
Acquire::http::proxy "http://<proxy URL>:<port>/";
Acquire::https::proxy "https://<proxy URL>:<port>/";
```

## aptの接続先を変更する
archive.ubuntu.comはロンドンにあるので、デフォルトのままaptを実行すると遅いです。  
日本のミラーサーバを設定します。  

```shell:JAISTに変更する例
sudo sed -i.bak -e "s%http://[^ ]\+%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g" /etc/apt/sources.list
```

ミラーサーバの一覧はこちら。  
https://www.ubuntulinux.jp/ubuntu/mirrors
楽に技術記事を書く3つのポイント

## みなさんアウトプット継続できてますか？
これから頑張って記事投稿継続するぞ！
毎日投稿がんばるぞ！
と思って、技術記事の投稿を意気込んだものの途中で挫折してしまった・・・

そういう方ってたくさんいると思います。
かくいう私もその一人でした。

## アウトプットが続かない原因
何故アウトプットの習慣ってなかなか身につかないんだろうって考えたときに結論に至った原因は **「がんばっているから」**

がんばって記事を書いているとその分 **時間** と **労力** がかかります。

そんなにがんばって書いた記事なのに「いいね」が全然つかない・・・ってなると、やる気がなくなってしまいますよね・・・

## アウトプットを継続するポイントは「楽をすること！」
記事を書くのにがんばりすぎているから、記事投稿のハードルがあがってしまうんです。

みなさんもっと気楽に記事を投稿しましょう！

ということで今回は楽に技術記事を書く３つのポイントを紹介します。

## 1. メモをそのまま記事にする
なにかを学習するときや調べ事をするときってメモを書きますよね。

私の場合はだいたいNotionというアプリを使って、メモを書いています。
この記事も書こうと思ったときにNotionのネタリストに書いておきました。

https://www.notion.so/ja-jp

まずはメモ書きしているものがあれば、それをそのまま記事にしてみましょう！

## 2. スクショはクリップボードで保存
書く内容によっては言葉ではなく画像でみせたほうがわかりやすいものってありますよね。

私は今までスクショは一旦保存したあと、コピーして貼り付けていました。

画像が1枚とかならいいんですが、何枚もあるとこの作業がかなり面倒くさい・・・

そこでスクショは撮ったらクリップボードに保存できるツールを使いましょう！
私の場合は「ScreenPresso」というツールを使っています！

```
「範囲選択して保存」→「コピー」→「貼り付け」→「保存した画像を削除」
```
↓
```
「範囲選択してクリップボードにコピー」→「貼り付け」
```
というように2工程も減るのでかなり楽になります。

## 3. 説明に迷ったらAIを使う
この用語をどう説明しようかなって思ったときにネットで調べたり、自分なりの言葉でまとめようとしていませんか？

それを短時間でできているなら構いませんが、そこにあまりに時間をかけすぎていると1記事あたりに要している時間が長くなり、結果やらなくなるという悪循環になります。

言葉に迷ったらAIを使いましょう！
比較的きれいにまとまった文章で返してくれます！

https://chat.openai.com/

https://claude.ai/
サクッとS3からローカルにダウンロードする

# 概要
1個2個のファイルならともかく、20個以上のS3のファイルをサクッとローカルにダウンロードしたいということありませんか？私はありました。そんなときのための覚書。phpのペライチで実現。


# 前提
プロダクトにs3のキーを持つテーブルがある、ないし別でs3のキー一覧を手元に持っていたとする


# 事前準備
①VisualStudioCodeをインストール
②拡張機能、PHP Serverをインストール
これにより、ペライチのphpを簡単にブラウザで実行できる。業務効率化にめちゃ便利
③composerをインストール
④composerでaws-sdkをインストール
```
composer require aws/aws-sdk-php
```


# コード

S3からキーを利用して、ローカルにファイルを落とす場合
```php
<?php

//----------------------------------
// SDK読み込み
//----------------------------------
require_once('/Users/XXXXXX/Desktop/php-workspace/vendor/autoload.php');
use Aws\S3\S3Client;

//----------------------------------
// S3の情報
//----------------------------------
$AWS_ACCESS_KEY_ID = 'XXXXXXXXXXXXXXXX';
$AWS_SECRET_ACCESS_KEY= 'XXXXXXXXXXXXXXXXXXXXXXXXX';
$REGION = 'ap-northeast-1';
$BUCKET = 'xxxxxxxxxxxxxxxxxxxx';

$s3_client = S3Client::factory([
  'credentials' => [
        'key'    => $AWS_ACCESS_KEY_ID,
        'secret' => $AWS_SECRET_ACCESS_KEY,
  ],
  'region'  => $REGION,
  'version' => 'latest',
]);


//----------------------------------
// １.対象データのs3_keyのリスト
// 手元にある場合はファイルの読み込み、などで取得
// ローカルDBなどにぶち込んで、ここでSQLで引くなども良い
//----------------------------------
$s3_key_list = ['s3のkey_1', 's3のkey_2', 's3のkey_3'];

//----------------------------------
// ２.s3_keyから画像を取得
//----------------------------------
$i = 0;
foreach($s3_key_list  as $k => $v){
  // 画像取得
  $result = '';
  $result = $s3_client->getObject([
    'Bucket' => $BUCKET,
    'Key'    => $v // オブジェクトのキー
  ]);
  
  //----------------------------------
  // ３.ファイル名、パスを指定してローカルに保存
  //----------------------------------
  
  // ファイル名は好きなものを。s3_key_listと紐づけたいならs3_key_listを連想配列にするもヨシ。
  $file_name = 'ファイル名';
  
  // 拡張子決定
  $content_type = $result['ContentType'];
  $content_type = explode("/",$content_type);
  $file_extension = $content_type[1];
  
  // リンク作成＆ダウンロード
  $cmd = $s3_client->getCommand('GetObject', [
    'Bucket' => $BUCKET,
    'Key'    => $s3_key 
  ]);
  
  $request = $s3_client->createPresignedRequest($cmd, '+1 hour');
  // 署名付きURLを取得
  $presignedUrl = (string) $request->getUri();
  // 画像ダウンロード
  $image_data = file_get_contents($presignedUrl);
  
  // ローカルに保存
  file_put_contents('/Users/XXXXX/Desktop/php-workspace/images/'.$file_name.'.'.$file_extension, $image_data);
  echo "<h1>$i</h1>";
  $i = $i + 1;
}
  
?>
```
[AWS]個人的に調べた用語やサービス

こんにちは！れーあです。
ここはAWSの勉強をする中で自分が個人的にわからなかったり気になったりした用語やサービスについて、記載していくメモ帳のような記事です。調べるたびに随時更新していきます。

## 調べたこと

- <b> CloudWatch </b>
AWSリソースと、AWS で実行されているアプリケーションをリアルタイムで監視する。
監視した内容に対して通知を送信したり、リソースを自動的に変更できるアラームを作成したりできる。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html
***
- <b> Data Firehose </b>
旧Kinesis Data Firehose。(2024/2/9：名称変更された)
エンドポイント宛てにリアルタイムストリーミングデータ配信をする
フルマネージドサービス。
アプリケーションの作成やリソースの管理は必要なし。
データを送信するようにデータプロデューサーを設定すると、指定した送信先にデータが自動的に配信できる。
データを配信する前にデータを変換するように設定も可能。
転送にはFirehose ストリームを作成する。

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/what-is-this-service.html
***

※随時更新
【Streamlit】AxiosError: Request failed with status code 403の対処

Streamlitで作成したアプリにて、ファイルをアップロードした時にこのエラーが発生します。
```
AxiosError: Request failed with status code 403
```

このエラーの解決策としては公式のフォーラムで投稿されていました。
↓

https://discuss.streamlit.io/t/axioserror-request-failed-with-status-code-403/38112/8

一旦、Streamlitのバージョンを1.24.0に下げました。これで問題なく動作しました。
ちょっと前にチャットアプリを作成した時、バージョンを更新したのが原因ですね。

https://qiita.com/sugimochi_1019/items/ede15dcacddfde36df4e

最新のバージョンではfile_uploadは使えないのかもしれません。
とりあえずメモ代わりに書いておきますが、詳細な原因はまた投稿するかもしれません。
How was AWS AppRunner

AppRunner is super easy to deploy app, infra including log base, monitoring base.
Its monitoring base enable to watch enough metrics.
Built infra is decoupled from the other services.(it will need to open peering conection to other VPC if you want it to connect to db and so on)
AppRunner can deploy code from console editor like AWS Lambda or GitHub repogitory somoothly, And also can deploy container app via AWS ECR. but it does not have sidecar container concept. so if you want to use DB or cache server, you need to open VPC peering connect.

If you want to release simple lightweight app, AppRunner is smart option rather than AWS Lambda or AWS Fargate.
But it needs to use RDS or Aurora if you want to use DB, it will be more expensive rather than EC2 for small start.
【脆弱性】攻撃の種類とその対策について解説されているサイトの紹介

こんにちは！
新卒の方とか最初の週末何してるんでしょう？
上京してきた方は都内探索とかですかね？

さて、今日は[Hack Splaining](https://www-hacksplaining-com.translate.goog/lessons?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=sc)の紹介をしようと思います。

無料で、かつハンズオンで有名な攻撃（XSSなど）とその対策が学べるサイトです。
(英語なので~~グーグル翻訳つかったり~~英語のお勉強してください)

以前の職場でSOCのオペレータになった時、仕事でたくさんのアラート（ほぼ誤検知）を眺めていて情報資産を守るという意識・感覚が麻痺しかかっていました。

その時機器にログインして攻撃内容を見に行った時、攻撃に対する知識がないと見逃すよな、でも通勤合わせて一日14時間で家帰って疲れて勉強する時間がなかなか取れないからしょうがない。。。
という言い訳をしていた時に見つけたサイトです。

これなら仮想環境作って攻撃せずとも攻撃の手法と対策が学べちゃいます。

勉強時間が作れなかったら使えるものは全部使って方法をつくるのがいいと思います。

多分ハッキングの勉強をする人にとって最初の関門が一から仮想環境を作成することだと思うので、そこすっ飛ばしてハンズオンで攻撃の勉強ができるサイトということで紹介しました。

※もちろん本当は仮想環境の構築から始めた方が自分の経験になります。


とりあえず短いですが次回までのつなぎとします。
Ruby でかけっこのパズルを解く

https://qiita.com/jpwgad/items/5431e452b4a65cba3862
 # 問題
>一郎、二郎、三郎の三人で駆けっこをして、その結果を次のように言っています。
>
>一郎：「僕は一番じゃない」
>二郎：「僕は一番だ」
>三郎：「僕は二番だ」

三人のなかで一人だけウソをついています。それは誰でしょう？

# Ruby で解いてみる
総当りで解いています。
0, 1, 2 でそれぞれ一郎、二郎、三郎を表しています。

```ruby
names = %W(一郎 二郎 三郎)
(0..2).each do |usotsuki|    #嘘つきを選びます
  table = [-1, 1, 2]    #与えられた条件（否定は負にします）
  #嘘をつかせます
  table[usotsuki] = -table[usotsuki]
  #可能性のある順位を配列にします
  tmp = table.map { _1 < 0 ? [1, 2, 3] - [-_1] : [_1] }
  #順位を総当りでまわして判定します
  [1, 2, 3].permutation do |candidate|
    if candidate.zip(tmp).all? { |c, ary| ary.include?(c) }
      puts "嘘つきは#{names[usotsuki]}です。"
      str = names.zip(candidate).map { |n, c| "#{n}が#{c}位" }.join("、")
      puts "ちなみに順位は#{str}です。"
    end
  end
end
```

# 結果

```
嘘つきは三郎です。
ちなみに順位は一郎が2位、二郎が1位、三郎が3位です。
```
Java silver向け 例題 継承 ポリモーフィズム

次のコードの実行結果を答えてください。

```java
class Human {
	String name = "ADAMU";
 
	void jump() {
		System.out.println("Jump");
	}
 
	void selfIntroduction() {
		System.out.println("My name is " + name);
	}

     static void sample() {
		System.out.println("sample Human");
	}
}

class OldMan extends Human {
	String name = "KEBBY";
	
    @Override
	void jump() {
		System.out.println("Step");
	}
 
	@Override
	void selfIntroduction() {
		System.out.println("My name is " + name);
	}

     static void sample() {
		System.out.println("sample OldMan");
	}
 
	void attack() {
		System.out.println("Attack!");
	}
} 

public class ExampleFour {
	public static void main(String[] args) {
		
		Human human01 = new OldMan();
		
		System.out.println(human01.name);
		human01.jump();					
		human01.selfIntroduction();	
        human01.sample();
	}
}

 ```

 正解
 ↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>↓<br>

 ```java
ADAMU
Step
My name is KEBBY
sample Human

```
<br>
スーパークラスの型(Human型)で宣言した変数 human01 にサブクラス(new OldMan())のインスタンスは代入できます。
サブクラスのオブジェクトをスーパークラスの型の変数に代入した場合、
インスタンスメソッド"以外"はスーパークラスのメンバが呼び出されます。
<br>

```java
System.out.println(human01.name);	//スーパークラスのメンバが優先的に呼び出されている
human01.jump();						//サブクラスのメソッドから優先的に呼び出される
human01.selfIntroduction();			//サブクラスのメソッド経由でサブクラスのメンバが呼び出されている
human01.sample();					//staticメソッドのためスーパークラスから呼び出される。
//human01.attack();                   Human型にattackメソッドがないためコンパイルエラー
 ```
<br>
サブクラス型の変数にスーパークラスのオブジェクトを代入するとコンパイルエラー。
キャストするとコンパイルは通りますが実行時エラーが発生します。
<br>

```java
//コンパイルエラー
OldMan human02 = new Human();

//実行時ClassCastException
OldMan human02 = (OldMan) new Human();
```
複数の.envファイルを使いこなす



## はじめに
複数の.envファイルに関しての備忘録。

## 🦁<INS>**結論**</INS>🦁
.envファイルの名前を変えることで、異なる環境（開発、テスト、本番など）に合わせた設定を用意し、管理をしやすくすることができる。
自身の環境で使うもの
テスト環境で使う APIキーを保管してるもの
複数のアカウントを保管
など様々な利用用途に合わせて大事なファイルを保管しておいておける。

:::note info
押さえておくべき点
* envファイルはキーと値のペアで環境変数を定義（環境変数は全て大文字）
* python-dotenvライブラリを使って.envファイルを読み込み、環境変数を設定でload_dotenv()関数にて読み込む
* 環境ごとに合わせたファイル名を付けることができる（例　.env.development、.env.test、.env.production）
* load_dotenv()関数のoverride=Trueパラメータを使って、既存の環境変数を上書きできる。
* gitignoreなどを活用して公開リポジトリには含めないようにする。
:::  


:::note warn
利用シーンに応じた.envファイルの例
* 環境別（本番、開発、テスト）
* アカウント情報（本番、テスト）
:::  


:::note alert
注意点
* GitHubなどで公開しない。
* 環境変数の衝突に注意が必要。
:::  

:::note info
envファイルに入れるべきもの
* APIキー（トークン）
* アカウント情報
* URL
* デバッグモードの切り替え
:::  

## <INS>**コード例**</INS>

```py
from dotenv import load_dotenv

# 共通設定の読み込み
load_dotenv('.env')

# 開発環境用設定の読み込み
load_dotenv('.env.development', override=True)

# 使用例
import os
DATABASE_URL = os.getenv('DATABASE_URL')
print(f"使用するデータベースURLは{DATABASE_URL}です。")
```

## まとめ✍️
envファイルを複数用意することで管理が格段にしやすくなる。一つの.envファイルのみを使用することが一般的だと思っていた方々に、この記事が役立てば幸いです。
初めて学ぶPython　環境編

Pythonを学ぶにあたって自分のPCで勉強用の環境を構築します。

<dl>
 <dt>①Anacondaのインストール</dt>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765031/438abf85-38f9-2c35-15b6-09c2a72183ce.png)

アナコンダはデータサイエンスに特化したプラットフォームでライブラリーや便利な機能を有しています。
Pythonなどのデータサイエンスに使われる言語のライブラリーも含まれています。
Pythonや仮想環境を整えることができます。
<br>
<dt>②仮想環境構築</dt>
ANACONDA.NAVIGATORを開き
EnvironmentsタグからCreateを作成します。</br>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765031/835d5972-c222-6997-e952-4884055b987f.png)
<br></br>
<dt>③拡張機能のインストール</dt>

Visual Studio Codeをインストールします。</dd>
VSCodeを起動して拡張から日本語をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765031/d6dbe64d-0a94-51fe-1e87-a32f8ce9e272.png)

次にLive Serverをインストールします。
LiveServerを利用するとHTMLコードを記述し、コードを保存するとブラウザで結果を
確認することができます。

インストール後にEXPLORERから勉強用のフォルダとファイルを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765031/17a3eb2f-d8aa-2977-e696-f540c3216439.png)

VSCodeではファイルの拡張子をみてプログラミング言語を判断します。
なので拡張子を間違えると入力補完が効かなくなるので注意が必要です。
Fedora CoreOSをISOイメージからインストールする

# 概要
Fedora CoreOSを、ISOイメージを用いてベアメタル環境にインストールする。
インターネットの疎通に問題がなければ、インストール対象マシンのみで操作が完結する。

# 結論(要点)
- ISOイメージで起動した環境では、`coreos-installer`コマンドでFedora CoreOSをディスクにインストールできる。
    - `-i`オプションでIgnition設定ファイルを指定できる。
- 環境内でpodmanやdockerが使えるので、公式の手順に従ってButane設定ファイルを作成後、Ignition設定ファイルに変換する。
- 作成したIgnition設定ファイルを指定して、`coreos-installer`を実行する。

# 手順
詳細な手順は割愛。適当なエディタでButane設定ファイルを作成すること。後は公式を参照。

# 参考
[Installing CoreOS on Bare Metal](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/)
[Producing an Ignition Config](https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/)
[Butane](https://coreos.github.io/butane/)
Arch Linuxインストールバトルはもうやめよう

## Arch系でインストーラー付きのディストリビューションも増えてきた
いろいろあるんです。そういうのも。でも、素のArch Linuxを入れようとすると途端にインストールバトルが始まる、そんな印象を持たれている方も多いと思います。そんなあなたに！

## 救世主のコマンド

インストールメディアからブートしてrootログインが完了してプロンプトが現れたら、

``` # archinstall ```

これだけでいいです。そうすると、シェルスクリプトかなんか、ですかね、走って、設定を促す画面になります。インストールはEnglishのままで(日本語にすると豆腐になる)、あとはMirrorをJapanにしたり、キーボードをjp106にしたり、ロケールをja_JP.UTF8にしたりお好きなデスクトップ環境にしたりできます。ディスク構成もオススメのを選んで(SSDなりHDDをえらんで)。時間をJSTにしたり。ロケールをja_JP.UTF8にしても日本語フォントが自動で入らないようなので、ポストインストールの画面でYesをえらんで

``` # pacman -S ipa-fonts fcitx5-mozc fcitx5-configtool```

あたりをすればログイン画面等で豆腐が出なくて、日本語も打てるようになるので良い感じです。プレインストールの設定画面で追加するソフトのところでipa-fontsなどを書いても同じように豆腐にならなくて済みます。

## 参考
https://japan.zdnet.com/article/35212977/
PDO プリペアードステートメント プレースホルダ

## データベースのデータを表示させる

- `index.php`の作成及び編集  

__●__ ユーザー入力がない場合(SQL文が決まっているパターンで毎回同じような表示をするような時)は query関数を使用 (PDOStatementクラス) 

- 参考: [PDOStatement](https://www.php.net/manual/ja/class.pdostatement)  

```php:index.php
<?php

require 'db_connection.php'; // db_connection.phpの読み込み (データベースの読み込みができる)

// データベースの中身を取得するためにSQL文を書く
// ユーザー入力がない場合(SQL文が決まっているパターンで毎回同じような表示をするような時)は query関数を使用
$sql = 'select * from contacts where id = 3';
// ステートメント
$stmt = $pdo->query($sql); // sql実行される

$result = $stmt->fetchAll();

var_dump($result);
```

※ `index.php`にアクセスしてみる

```
接続成功
array(1) {
  [0]=>
  array(8) {
    ["id"]=>
    int(3)
    ["name"]=>
    string(9) "いいい"
    ["email"]=>
    string(14) "test2@test.com"
    ["url"]=>
    string(16) "http://test2.com"
    ["gender"]=>
    int(1)
    ["age"]=>
    int(4)
    ["contact"]=>
    string(12) "test2
test2"
    ["created_at"]=>
    string(19) "2024-04-06 20:20:58"
  }
}
```

## 名前付きプレースホルダ

- ユーザー入力がある場合(検索画面だったりお問い合わせフォームなどユーザーが入力する場合) prepare, bind, execute の大きく3種類の関数を使用  

- 悪意のあるユーザーが、お問い合わせフォームに delete * 文などを打ち、それが通ってしまうと問題がある。SQLインジェクション対策をする必要がある  

- `index.php`を編集  

```php:index.php
<?php

require 'db_connection.php';

// : を付ける場合は名前付きプレースホルダと呼んだりする
$sql = 'select * from contacts where id = :id'; // ? を付けるか : を付ける(プレースホルダ)
$stmt = $pdo->prepare($sql); // プリペアードステートメント
// :id に実際の値を紐づける必要がある(bind)
// bindRaram と bindValue という2種類の関数がある
$stmt->bindValue('id', 2, PDO::PARAM_INT); // PDO::PARAM_INTは型の入力 id 2 が入力される(紐付け)
$stmt->execute(); // queryが実行される

$result = $stmt->fetchAll();

echo '<pre>';
var_dump($result);
echo '</pre>';
```

結果:  

```
接続成功
array(1) {
  [0]=>
  array(8) {
    ["id"]=>
    int(2)
    ["name"]=>
    string(9) "あああ"
    ["email"]=>
    string(13) "test@test.com"
    ["url"]=>
    string(15) "http://test.com"
    ["gender"]=>
    int(0)
    ["age"]=>
    int(2)
    ["contact"]=>
    string(20) "テスト
テスト"
    ["created_at"]=>
    string(19) "2024-04-06 20:18:56"
  }
}
```

入力で入ってくる値なので実際は `変数` で記述する