OmniAICreator/Qiita-1.07M huggingface dataset:
cypher：やはり俺のwithの使い方はまちがっている（collectを使ったページネーションの作法）

# 挨拶

初めまして！株式会社プラハCEO兼エンジニアの [dowanna](https://twitter.com/dowanna6) です！
普段は会社経営とか[社長の給料を社内で一番低くしたり](https://praha-inc.hatenablog.com/entry/2019/07/26/230910?_ga=2.80566291.561475685.1576803948-475732684.1572093857)、[副業にうつつを抜かす自社エンジニアをとっちめたり](https://praha-inc.hatenablog.com/entry/2019/09/05/204758?_ga=2.80566291.561475685.1576803948-475732684.1572093857)していますが
「そういえば俺エンジニアだったな」と思い出したので、advent calendarに２度目の参加を試みました。
チンして5分経ったスープのような生暖かい目で見ていただけると喜びます。


# 本題


neo4jを使っているとcypherクエリ、特にwithで複数のクエリを繋ぐ事がありますよね。

「cypherって、withさえあれば無敵じゃん！」
そんな風に考えていた時期が、僕にもありました。

でも少しずつ複雑なクエリを書き始めると意図しないwithの挙動に悩まされて定期的に嘔吐するようになったので、少しでも誰かの詰まりどころを解消できたら良いなと思い、今日はwithの癖を少し解説したいと思います。


## withケース１：nodeと総数を取得したい
webサービスを作っていると、ページネーションを実装したい時が出てきますよね。
ページネーションの際には「ページサイズ分のnode」と「node総数」が欲しい時がありますよね。
そんな時は、こんなクエリを書く事になるでしょう。


### 実験データの作成
```
create (a:User{id:'1'}),(b:User{id:'2'}),(c:User{id:'3'})
```

### nodeと総数の取得
```
match (u:User)
with u, count(u) as total
return u.id, total
```

よーし、これで今日の仕事終わり！ゼルダ遊ぼ！と思っていたら、こんな結果に：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246648/96e26f89-3043-d472-2b48-d1705c8718ee.png)


あれ！？
total=３になるはずなのに、どうしてtotal=１！？


と思いつつ、こんな具合にクエリを書き換えてみます

```
match (u:User)
with collect(u) as users, count (distinct u) as total // 一度uのリストを作って
unwind users as u                                     // uのリストを元に戻す
return u.id, total
```

すると、当初想定していた結果が得られました：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246648/9d8756dd-bf7a-d65d-003a-897047403cc5.png)


これで無事ゼルダが遊べるわけですが、理由が分からないと気持ち悪いのでneo4jの[コミュニティ](https://community.neo4j.com/t/how-to-get-total-count-and-nodes-with-one-query/13004)に問い合わせてみました。

曰く、

`with u, count(u) is aggregating the count and grouping by u. Since each u is unique, the count would thus be 1 for each u.`

`the collect(u) as users creates a single collection of all users and for this collection we count all users and thus a single collection of users and a count of 3.`



**日本語でおk**

- uはそれぞれ異なるnodeなので、u毎にcountが行われる（count=1)
- collect(u)を行うと、uをまとめたlistに対してcountが行われる(長さ３のリストに対するcount=3)


withでaggregation関数を使う時は、関数の引数（node）が**どのようなgroupを形成しているか**意識する必要がありそうです。
ただwithで渡したnodeに対してcountするのと、collect()した結果とに対してcountするのとでは意味が違うようです。



## withケース2:要素数を制限したい

returnするクエリ結果を絞るだけなら skip X limit Yすれば良いのですが

```
match (u:User)
return u.id
skip 1 limit 1
```


例えば高負荷なクエリを流す必要があるけれど、DBに100万件のuserが存在するため、全てのuserにはクエリを実行したく無い場合：

```
match (u:User)
// 鬼のように複雑で高負荷なmatch,create,setクエリ
return u.id
skip 1 limit 1
```

100万件のuserにクエリを流してからskip limitしても、高負荷なクエリが100万件に実行された後に絞り込んでいるので、パフォーマンス上の問題が出るかもしれません。高負荷なクエリを流す前に、途中の検索結果を絞りたくなりますよね。
そんな時は以下のようなクエリを書けば解決です！

### collectする時に要素数を絞る

```
match (u:User)
with collect(u)[1..2] as users
unwind users as u
// 鬼のように複雑で高負荷なmatch,create,setクエリ
return u.id
```

え〜でもcollectしてunwindなんて無駄っぽいから嫌だよ〜という方にはコチラ

### withで繋ぐ時にskip limitで要素数を絞る
```
match (u:User)
with u
skip 1 limit 1
// 鬼のように複雑で高負荷なmatch,create,setクエリ
return u.id
```


個人的には「withにもskip limitが使える」事を知った時は**ヒャッハー！**と叫びたくなったので、是非皆さんも使って叫んでみてください。


## まとめ
- withの中でaggregation関数を使う時は、groupingに注意
- withもskip limit出来る。ヒャッハー！！
splitで文字列を分割🔪  ❏Ruby❏

`splitメソッド`を使うと文字列を分割できます。

`split("区切りたい文字")`でその文字で区切ったものが配列に入れられます。

実際に見てみましょう。

```ruby:sample.rb
str = "manbow,manbow2,manbow3"
ary = str.split(",")
puts ary[1]
```

【結果】
`manbow2`

【解説】
2行目でstrをカンマ（,）で区切って配列にします。

実際のaryの中身は、
ary = [nambow,manbow2,manbow3]となります。

3行目で配列の2番目を取ってくるので、結果は`manbow2`になります。

<br>
`split(" ")`でスペース区切りとかも使えそうですね！

<br>
ではまた！
初めてのQiita入稿 どんな構成で書き始める？？

#初のQiita入稿をする人が気を付けるといいかもしれないポイントをまとめてみた

##1.構成をつけよう
↑このような、大見出しなどで構成をつけると、見やすいし、記事もまとまる
見出しのつけ方としては、

↓記入例

~~~
#大見出し
##見出し
###小見出し
####小小見出し
#####小小小見出し
######小小小小見出し
~~~

↓表示例
#大見出し
##見出し
###小見出し
####小小見出し
#####小小小見出し
######小小小小見出し


となる



##２.コードの表示方法
Qiitaでは、なにをやったかの説明はもちろん書くが、どのコードを入力したかも是非書きたいことだ。
そこで、シンタックスハイライトというものが有効。

↓記入例
（空行）
~~~
ここにプログラミングコード
~~~
（空行）

↓実行例

~~~
ここにプログラミングコード
~~~

となる。
波線３つで囲えばいいということである。
空行を波線の外側に一つずつ入れることを忘れずに。
[AppStoreConnect]カテゴリ値

|日本語|値|
|:--|:--:|
|エンターテイメント|ENTERTAINMENT|
|グラフィック／デザイン|GRAPHICS_AND_DESIGN|
|ゲーム|GAMES|
|ショッピング|SHOPPING|
|ステッカー|STICKERS|
|スポーツ|SPORTS|
|ソーシャルネットワーキング|SOCIAL_NETWORKING|
|ナビゲーション|NAVIGATION|
|ニュース|NEWS|
|ビジネス|BUSINESS|
|ファイナンス|FINANCE|
|フード/ドリンク|FOOD_AND_DRINK|
|ブック|BOOKS|
|ヘルスケア/フィットネス|HEALTH_AND_FITNESS|
|ミュージック|MUSIC|
|メディカル|MEDICAL|
|ユーティリティ|UTILITIES|
|ライフスタイル|LIFESTYLE|
|開発ツール|DEVELOPER_TOOLS|
|教育|EDUCATION|
|雑誌／新聞|MAGAZINES_AND_NEWSPAPERS|
|仕事効率化|PRODUCTIVITY|
|辞書／辞典／その他|REFERENCE|
|写真／ビデオ|PHOTO_AND_VIDEO|
|天気|WEATHER|
|旅行|TRAVEL|
forの中で非同期処理関数の引数に変数iをもたせたいとき

# forの変数iを非同期処理の関数の引数として渡したい

## 問題のコード

なんのこっちゃという見出しですが、まずはこちらを見てください。

```javascript:script.js
tokumei()
.then(function () { // 成功にたどりかない&失敗にもいかない
    console.log('成功');
}, function () {
    console.log('失敗');
});

function tokumei () {
    var paramList = [];
    var d = new $.Deferred();

    // paramListになにがしかをpushする処理（中略）

    for (var i = 0; i < paramList.length; i++) {
        ajaxFunc(paramList[i]) // ajax関数の呼び出し
        .then(function () {
            if (paramList.length === i + 1) d.resolve(); // resolveされない。
        }, function () {
            d.reject();
        });
    }
    return d.promise();
}

function ajaxFunc(param) {
    var d = new $.Deferred();
    var url = '/api/nanikanoapi?=' + param;

    setTimeout(function () {
        $.ajax({
                url: url,
                dataType: 'jsonp',
                cache: false,
                timeout: 10000
            })
            .done(function (data) {
                if (parseInt(data['response_code']) !== 400){
                    d.resolve();
                } else {
                    d.reject();
                }
            })
            .fail(function () {
                d.reject();
            });
    }, 200);

    return d.promise();
}
```

これ、動きません。
`// resolveされない`んです。
変数iが意図したように渡せません。

### 解決策

forの中で即時関数を実行して**クロージャーを生成**、引数にiを指定して渡してあげればOKでした。

## 正解のコード

```javascript:script.js
tokumei(PDS)
.then(function () {
    console.log('成功'); // 成功にたどり着く
}, function () {
    console.log('失敗');
});

function tokumei () {
    var paramList = [];
    var d = new $.Deferred();

    // paramListになにがしかをpushする処理（中略）

    for (var i = 0; i < paramList.length; i++) {
        (function (i) { // クロージャー生成
            ajaxFunc(paramList[i]) // ajax関数の呼び出し
            .then(function () {
                if (paramList.length === i + 1) d.resolve(); // resoleveされた！
            },function(){
                d.reject();
            });
        })(i);
    }
    return d.promise();
}

function ajaxFunc(param) {
    var d = new $.Deferred();
    var url = '/api/nanikanoapi?=' + param;

    setTimeout(function () {
        $.ajax({
                url: url,
                dataType: 'jsonp',
                cache: false,
                timeout: 20000
            })
            .done(function (data) {
                if (parseInt(data['response_code']) !== 400){
                    d.resolve();
                } else {
                    d.reject();
                }
            })
            .fail(function () {
                d.reject();
            });
    }, 200);

    return d.promise();
}

```

ざっくりした書き方ですが、こんなかんじでいけました！
RedmineのWikiのリンクを新規ウィンドウで開く

#はじめに
RedmineのWikiでリンク集を作りたかったのですが、
Markdownで記述したリンクを新規ウィンドウ（別タブ）で開かせることができませんでした。
それを強制的に新規ウィンドウで開かせるようにする方法をご紹介します。

#前提条件
- Redmine 4.0.5で動作確認しました。
- テキスト書式の設定は「Markdown」です。

#カスタマイズ
lib\redmine\wiki_formatting\markdown\formatter.rb
の34行目を変更します。

```ruby:formatter.rb（変更前）
content_tag('a', content.to_s.html_safe, :href => link, :title => title, :class => css)
```

```ruby:formatter.rb（変更後）
content_tag('a', content.to_s.html_safe, :href => link, :title => title, :class => css, :target => '_blank', :rel => 'noopener')
```

`:target => '_blank'` と `:rel => 'noopener'` を追加しているだけです。
変更後はサービスの再起動をお忘れなく。
KubernetesのDockerコンテナを再起動する方法

時々忘れてしまいますが、KubernetesのDockerコンテナを再起動する方法はないです。
kubectl scale deploymentのreplica数を0にし、また元の数に戻すやり方を使います。

- replicaの数を0にする
 
```
kubectl scale deployment [Deployment Name] --replicas=0 -n [Namespace]
deployment.extensions/[Deployment Name] scaled
```

- podの数が0になっていることを確認

```
kubectl get pods -n  [Namespace]
No resources found.
```

- replicaの数を1にする

```
kubectl scale deployment [Deployment Name] --replicas=1 -n [Namespace]
deployment.extensions/[Deployment Name] scaled
```

- podの数が1になっていることを確認

```
kubectl get pods -n  [Namespace]
NAME                   READY     STATUS    RESTARTS   AGE
[Deployment Name-ID]   1/1       Running   0          64s
```


#### 追記(2020.1.28)
Kubernetes Ver.1.15から、Deploymentリソースに関してrollout restartで再起動が出来るようになりました。使い方は以下です。

```
kubectl rollout restart deployments/[Name] --n [Namespace]
```

Describeしてみると、restartコマンドの中身はScale down->Scale upであることが分かります。

```
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  13s   deployment-controller  Scaled up replica set [Deployment Name-ID]  to 1
  Normal  ScalingReplicaSet  12s   deployment-controller  Scaled down replica set [Deployment Name-ID]  to 0
```
goの配列・sliceを書いたら苦悩しましたこと

#Java/C#風に書いたら駄目でした

型付きだから、もうPerlの世界じゃないと思い、Java/C#風に書いたら駄目でした

```golang
func arr1(){
	a1 := [2]int{1, 2}
	a2 := [3]int{1, 2, 3}

	a1 = a2 //ここは焦点

	fmt.Println(a1, a2)
}
// mainからの呼び出し部分は省略。下同。
```
```sh
$ go run array_slice.go                                                                                                                             
./array_slice.go:9:5: cannot use a2 (type [3]int) as type [2]int in assignment
```
型違いと言われているので、下記とおり修正したら、うまくいきました：

```golang
func arr2(){
	a1 := [3]int{1, 2} //a1の長さも3に変更
	a2 := [3]int{1, 2, 3}

	a1 = a2 //ここは焦点

	fmt.Println(a1, a2)
}
// output: [1 2 3] [1 2 3]
```
どっかで見かけたようでそこまで気にしなかったこと： **配列の長さも、その型定義の一部なので、要素型の同じ配列でも 長さが違うと別型扱いとなります。**

_これは、コンパイルすれば教えてくれるものなので、まだまだそこまで鬱陶しいものではないかもしれません。問題なのは後述のこっそりさられる系⬇_

# ``` v := [長さn]Type{要素数m}``` の新発見
上記コンパイルエラー対応するため、慌てて```a1```の長さを2から3に変更することで通させたんですが、ソースコード``` a1 := [3]int{1, 2} ```をよく見てみると、長さの指定```3```と中身の記述```{1, 2}```個数がずれています。興味持って、いくつかパタン試し：

```golang
func arr3(){
	a1 := [2]int{} // output: [0 0]
	a2 := [2]int{1, 2} // output: [1 2]
	a3 := [2]int{1, 2, 3} // array index 2 out of bounds [0:2]
	fmt.Println(a1, a2, a3)
}
```
(実は言うまでもないかもしれない)**新発見**： ``` v := [長さn]Type{要素数m} ```に対して

- n < m の場合、コンパイルエラー(out of bounds)
- n >= m の場合、コンパイルOK(```m+1 ~ n 個目要素の値は、その要素型の0値となる```と言われてます)

#新発見由来の苦悩
でも、```a2 := [2]int{1, 2}```のような記述を見ると、なんとなく違和感があるように思えます。
そもそも、```{}```に要素記述するれば、配列長さは自動的に検知できるものでしょう、なのにわざわざ```n```を指定するのは、例の[DRY原則](https://ja.wikipedia.org/wiki/Don%27t_repeat_yourself)と相違するじゃないか。
そう思って、n無し版```a2 := []int{1, 2}```試してみたら、無事コンパイルできました！ じゃぁ、今後はもうn指定なんかやめる！(このとき自分は既にarrayからsliceへと別物作っていることとは知らなかった)
でも、さらにいろいろ試してみたら、予想通りに動かないところがありました：

```golang
func arr_or_slice_1() {
	v1 := [1]string{"元の値"} // n指定
	v2 := v1
	v2[0] = "新しい値"
	fmt.Printf("v1[0]:%v\n", v1[0]) // output: v1[0]:元の値
}
func arr_or_slice_2() {
	v1 := []string{"元の値"} // n指定なし
	v2 := v1
	v2[0] = "新しい値"
	fmt.Printf("v1[0]:%v\n", v1[0]) // output: v1[0]:新しい値
}
```
n指定有りなしで、結果が変わってます。これは考えもしなかった結果です。 今までのコーディング経験のベースのところと衝突しているくらいなので、しばらくは目を疑い、更にパソコン壊れているかを疑いました。自分ひとりではどうしても抜き出せないところでしたので、色んな方にこの悩みを聞くことにしました。　当時は、確かだれかから``` sliceになっているから ```と言われた記憶がありますが、``` sliceだからarrayと違う ```という前提知識は頭になかったから、理解できませんし聞き逃しました。

#配列は値型、スライスは参照型
しばらくして、またgoのことを勉強・やってみようと思い、ある記事を呼んでみたら、``` 配列は値型、スライスは参照型 ```との記述に目を留め、実際に手を動かして見たら、この前の苦悩は、一気に解消しました：

```golang
func arr_and_slice() {

	//n指定の場合は 配列
	a1 := [1]int{1}
	a2 := a1
	a2[0] = 2
	fmt.Println(a1, a2) // output: [1] [2]

	//n指定無しの場合は slice
	s1 := []int{1}
	s2 := s1
	s2[0] = 2
	fmt.Println(s1, s2) // output: [2] [2]
}
```
ということで,以下2のことが分かったことで苦悩解消：

- n指定の場合は 配列,指定なしの場合はslice
- 配列は値型、スライスは参照型

---

上記書いた悩みなどは、自分が勉強不足で発生したもので、まだまだ```知っていれば大丈夫```レベルです。
それより、sliceのappendとcapとの間に纏わる```知っていても、気が付かないとやられること```も書きたかったですが、記事書くことは本当に予想以上に時間・頭かかることで、取り敢えずここまでとすることにしました。
今後も是非記事書くことに頑張っていきたいと思います。
Django ORMのサブクエリを使う

この記事は[iRidge Advent Calendar 2019](https://qiita.com/advent-calendar/2019/iridge)の20日目の記事です。

今年担当した開発の中で、DjangoORMのSubqueryをはじめて使いました。やりたかったこと自体は非常にシンプルですが、DjangoのORMで実現するのには情報が少なくそこそこ苦戦したので、記事にしたためておきたいと思います。

## やろうとしたこと

以下はモデルの例です。説明のために実際のモデル定義とは異なり、かなり単純化したものになっています。

```python
class Shop(models.Model):
    identifier = models.CharField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False)
```

```python
class Book(models.Model):
    shop = models.ForeignKey(Shop)
    uuid = models.CharField(max_length=36, unique=True, db_index=True,
                            blank=True)
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False, db_index=True)
```

```python
class User(models.Model):
    shop = models.ForeignKey(Shop)
    device_user_id = models.CharField(max_length=255, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False)
```

```python
class FavoriteBook(models.Model):
    book = models.ForeignKey(Book, db_index=True)
    user = models.ForeignKey(User, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)
```

既存のコードでは、UserとShopで絞り込んだBookの一覧を取得するquerysetが書かれていました。このquerysetに、あるユーザがBookをお気に入りしているか否かをFavoriteBookから情報を引っ張ってきて付与しようとしました。

## 実装

色々試行錯誤したのですが経緯は割愛します。
https://docs.djangoproject.com/en/3.0/ref/models/expressions/#subquery-expressions 
 を参考に以下のような2行のコードで実現できました。

```python
queryset = ... # 既存のqueryset、UserとShopの条件で絞り込んだBookの一覧

# 各Bookに、あるユーザのお気に入り有無の情報を付加する
queryset_fav = FavoriteBook.objects.filter(user=user).filter(book=OuterRef('pk'))
queryset = queryset.annotate(favorite_book_id=Subquery(queryset_fav.values('id')[:1]))
```

### OuterRef
サブクエリが外部のクエリのカラムを参照する時に使用します。
この場合、`filter(book=OuterRef('pk'))`でサブクエリのbook_idが元のquery_setのbook.idを参照するようになります。

### SubQuery

作成しておいた`queryset_fav`をサブクエリとして使用します。
この場合、`favorite_book_id`のカラムが追加され、サブクエリの結果がセットされます。
より具体的に言えば、FaboriteBookに対象のUserとBookのレコードがある（＝対象ユーザにお気に入りされている）Bookにはfavorite_book.idが、そうでない（＝お気に入りされていない）Bookにはnullがセットされます。

このとき発行されるSQLは以下のようなイメージです、

```sql
SELECT `books`.`id`,
       `books`.`shop_id`,
       `books`.`uuid`,
       `books`.`name`,
       `books`.`description`,
       `books`.`created_at`,
       `books`.`updated_at`,
       `books`.`is_deleted`,
       (SELECT U0.`id`
        FROM `favorite_books` U0
        WHERE (U0.`user_id` = 999
          AND U0.`book_id` = (`books`.`id`))
        LIMIT 1) AS `favorite_book_id`
FROM books LEFT OUTER JOIN ...
WHERE ...
ORDER BY ...
```

## おわりに

このようにまとめてみると非常にシンプルですが、実現したいことと実装すべきことが乖離しているような印象を個人的には受け、それが苦戦した要因かと思います。
本当はraw()で生のSQLを書けばそれほど悩まずに済み実装もよりわかりやすかったかもしれません。しかしながら、既存システムへの改修の場合そうもいかないケースはあると思います。今回のケースもSubQueryを使うことがベストな選択かはわかりませんが、選択肢の一つとして知っていてもよいかなと思います。
soracom-cli でワンライナーでグループを作成する

# はじめに

色々サービスの検証をするにあたり、SIMグループを作ったり消したりを繰り返したかったので
その際に利用したコマンドラインです。
あまり需要は無いと思います。。。

## 前提

以下のインストールが必要です。
環境はmacOSです。

* soracom-cli
* jq

## 準備

事前に作成するグループの名前を入力したテキストファイルを準備します

### 作成する SIM グループの名称ファイル

```text:groups.txt
test-group-1
test-group-2
```

### 作成する SIM グループのコンフィグレーションファイル

以下は例です。
必要なものに合わせて設定してください。
`credentialsId` は事前に設定しています。

[グループコンフィグレーション 詳細](https://dev.soracom.io/jp/docs/group_configuration)

```json-doc:test-group-1-config.json,test-group-2-config.json 
[
  {
    "key": "enabled",
    "value": true
  },
  {
    "key": "destination",
    "value": {
      "provider": "aws",
      "service": "kinesis",
      "resourceUrl": "https://firehose.ap-northeast-1.amazonaws.com/xxxxx"
    }
  },
  {
    "key": "credentialsId",
    "value": "soracom_test"
  },
  {
    "key": "contentType",
    "value": "json"
  }
]
```

## SIM グループの一括作成

```bash
cat groups.txt | xargs -L 1 -I @ \
soracom groups create \
--body '{ "tags": { "owner": "daisuke-araki", "name": "@", "env": "trial" } }' \
--profile sandbox
```

## SIM グループのコンフィグレーションの一括設定

ここでは、Funnelのコンフィグレーションを行っています。
グループ作成時に行わないのであれば `namespace` 毎に設定が必要です。
コンフィグレーションをテキストで管理できるのでバージョン管理もできますね。

```bash
soracom groups list --profile sandbox | \
jq -r '.[] | select(.tags.env == "trial") | .groupId, .tags.name' | \
xargs -L 2 -n 2 -t \
sh -c 'soracom groups put-config --group-id $0 --namespace SoracomFunnel --body @$1-config.json --profile sandbox'
```

## SIM グループの一括削除

`jq` コマンドを利用し `env` タグに `trial` が設定されたグループを一括削除します。

```bash
soracom groups list --profile sandbox | \
jq -r '.[] | select(.tags.env == "trial") | .groupId' | \
xargs -L 1 -I @ soracom groups delete --group-id @ --profile sandbox
```
MacでLaravel環境構築

MacでLaravelのローカル環境を構築したのでメモ。

## 1.phpをインストール
```
brew install php@7.2

export PATH="$(brew --prefix php@7.2)/bin:$PATH"
```

## 2.composerをインストール

・ターミナルより以下を実行

```
brew install homebrew/core/composer

Updating Homebrew...
==> Downloading https://getcomposer.org/download/1.8.5/composer.phar
:
```
PHPも勝手にインストールされる？

## 3.larevelをインストールする
```
brew install homebrew/core/composer

Updating Homebrew...
==> Downloading https://getcomposer.org/download/1.8.5/composer.phar
:
```

## 4.composerのパスを通す
.bash_profileに追加

```
export PATH="$PATH:$HOME/.composer/vendor/bin"
source .bash_profile
```

## 5.プロジェクト作成
・プロジェクトを作成したいディレクトリに移動し、プロジェクト作成コマンドを実行する。

```
cd {test project dir}
laravel new {new project name}

----
Crafting application...
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Package operations: 76 installs, 0 updates, 0 removals
  - Installing doctrine/inflector (v1.3.0): Downloading (100%)
  - Installing doctrine/lexer (v1.0.1): Downloading (100%)
  - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)
  - Installing erusev/parsedown (1.7.3): Downloading (100%)
  - Installing symfony/polyfill-ctype (v1.11.0): Loading from cach
 :
```

## 6.ローカルサーバー起動
・以下のコマンドを実行する。

```
cd {created project dir}
php artisan serve

ar-mac-007:asoview-test ar-mac-007$  php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

```
先輩に commit が多すぎると言われgit reset softを覚えた

こんにちは。
最近、プログラミングを始めて、エンジニアを目指している人です。

今回は`git reset --soft`についてメモがてら書きます。

とりあえず、はやく git reset --softのやり方を。。。！！
という方用に、最初に私がやった方法を置いておきます

#やったこと
私がやったのは、 git reset --soft で、
10個くらいのコミットの内容を1つのコミットにまとめるというものです。
まずは

```
git log
```
を実行して、コミットログを表示します。
私の場合ここで、
コミットA
コミットB
コミットC
コミットD
コミットE
コミットF
コミットG
コミットH

みたいな感じのログが表示されました。
やりたいのは
**コードはコミットHの内容のまま、**
**コミットログ的には、コミットAしかコミットしてないよ！という感じ**
にしたかったので、

```
git reset --soft コミットAのコミットID
```
と実行し、何の問題もなく、1発でキレイなコミットを作ったような雰囲気になりましたとさ。
めでたしめでたし。


#詳細

ここからは、`git reset --soft`にたどりつくまでと、
そもそもそれ何？ってところを書きます。

###たどり着くまで
タイトルにあるように、commitが多すぎて、
commitをキレイにしてほしいといわれました。

なんやそのコミットみたいなのが10個以上あって汚い上に、
大量のコミットの中身は、インデントの修正のみ...:baby:
それはあきれられても仕方ないですね。

ということでキレイにしましょう。

まずは `git commit まとめる` で検索！
検索結果...
`git rebase -i` これがまとめる方法らしい！

なるほどなるほど...これは前のコミットに次のコミットの内容を押し込む感じということかな...？
うーん...私のやりたいことは本当にこれなのか？

私がやりたいのは、

- コミットA　←実装完了のコミット
- コミットB　←インデント修正のコミット
- コミットC　←インデント修正のコミット
- コミットD　←インデント修正のコミット
- コミットE　←インデント修正のコミット
- コミットF　←インデント修正のコミット
- コミットG　←インデント修正のコミット
- コミットH　←インデント修正完了のコミット（最終コミット）

上記の中の、
コミットAに、最終コミットの情報を反映させてプルリクを出したいのだ。
しかも全部インデントの修正で同じところばかり触っているので、
BとかCとかをわざわざ反映させる必要なんてないのです。
どうすりゃいいんだい。（今みてみると本当にひどいコミットだ）


先輩に相談してみた

私「先生、私がやりたいことを実現するためにrebaseを行うのは正しいですか？」
先輩「えっ、リセットソフトでよくない？」
リセットソフト....？
なにそれ出てこなかったよ...（ここでググり力のなさが露呈した）
で、とりあえず調べてみた結果をまとめたところ

>最終コミットの内容は保持した状態で、
>コミットだけを削除できる

呪文らしい。
なんと！私がやりたいのはこれではないか！

ということで、[最初に戻る](#やったこと)

ちなみに、
気を付ける点として、

```
git reset --hard
```

という、コミットも変更内容も全部リセットする呪文もあるらしい。
これは、
いろいろいじってどこが原因がわからないけど詰まった！
とかで、前のコミットに戻りたい時に使うらしいです。
怖いので、私はまだ使ったことないですが、Tips程度に乗せておきます。
エンジニア夫婦のよいところわるいところ

#はじめに
これは[ユアマイスターアドベントカレンダー2019](https://qiita.com/advent-calendar/2019/yourmystar) の20日目の記事です。
最近での一番の大きな出来事とエンジニアについて書いた記事になります。

私事で大変恐縮ではございますが、
先日、３年付き合った彼と結婚をして夫婦となりました。

タイトルに**「エンジニア夫婦」**とありますが、
結婚をしたのは最近なので、エンジニア同士が同棲していた時の話になります。
エンジニア同士で結婚をするというのはよくあることなのか、あまりないのかは分かりませんが、同棲、または結婚をすることの**「よいところわるいところ」**をご紹介しつつ、**お互いのためにどうあるべきか**などを、2年近く同棲をしてきた経験を元に綴っていこうかと思います！

*「これから結婚するよーー🙌」*
*「私達はエンジニアカップルです！！👫」*
などの方々に参考・・・？？
読んで頂けたら幸いです



#よいところ

###仕事の話ができる

「仕事の話ができる」というのは、夫婦間でビジネスの関係を築くという意味ではないです。

どのご夫婦でも、仕事から帰ってきたら仕事の話をしたくなるときってあると思います。
楽しかったこと、学んだこと、悔しかったこと、愚痴などなど。

その日に起こったことって、相手に話して共感してほしーなーと思ったりすると思っています。（私はします）

しかし、エンジニアの仕事を話すとなると、専門的な知識の内容が含まれることが多くあり、
その専門的な知識をひたすら話したところでなかなか共感を得られない。
「へーそーなんだー」、「よかったねー」と相づちを打たれ、強引に話題を変えられる始末です。

ところが、それがエンジニア同士であれば、
**お互いの話を理解し合えるので共感を得られる**というよいところがあります。


###お互いの情報を共有し合える

日進月歩で新しい技術が誕生したり、ありとあらゆる情報が飛び交う今の時代、一人でインプットできる情報量は限られてきます。
正直すべてを把握することは無理です。
でも、2人いればインプット量が単純に2倍になります。
お互いに日々インプットした新しい情報、勉強したことなどを共有できるのはとても効率的です。



#わるいところ

###お互いのプライドが高くてけっこう喧嘩する

普段はあまり喧嘩はしない方であると自負をしているのですが、たまにお互いのプライドがぶつかり合い喧嘩になります。
プライドというのは自分たちが経験してきたことや勉強してきたことは**正義**だと思っていることです。
お互い必死の思いで身につけた知識なのでそれがぶつかり合うのは当然といえば当然な気はしますが。。。

ふとした瞬間に、**会話 → 討論 → 喧嘩 → お互いに無視** ってなります。


**【対策】**
プログラミングは一つの正解はなく、
常にベターな回答からベストな回答を求め続けるものです。
そこで大事なのは、どっちが正解かを求めるのではなく、
**お互いの意見を尊重してより良い答えを見つけるようにするべき**です。
というのを頭の片隅にでもおいた上で、2人と「大人になること」が必要です。

と言いつつ、「大人になる」みたいな抽象的な案では、
解決しないと思うので、今後も2人で話し合っていく課題の一つにしたいと思います。


###やたらと周辺機器を買いたがる

周辺機器って言葉が正しいのか不安ですが
iMacや Apple Watch とかをやたらめったら買ってしまいがち。。。？
これはお互いがエンジニアだから起こる現象なのか。。。？
エンジニアをやっていると、少なからず、こういった製品に関心があると思っています。
2人で購入を検討しだすと、止める人が誰もいないので、歯止めが効かなくなることが多々あります。。。

気づいたら Apple 製品だらけになっている、よく喋るロボットが増えてる、
なんてことにならないように注意したいものです(~O~;)

**【対策】**
2人で話し合った結果、
「技術を上げて、欲しい物を買える様にお金を稼ぐこと!!!」
という結論に至りましたφ(..)


##おまけ：エンジニア夫婦あるある

- 日常会話でプログラミング用語を使ってたとえ話をする
- 自宅にホワイトボードを設置したがる
- お互いの読んでる本を読みたくなる 
- 作業中にかける BGM の取り合いが始まる
- 「二人でサービスを作ろう！！」って言ってみる。。

##おわりに
結婚したからといって、生活は特に変わりません。
ですが、節目として、自分たちを見つめ合うきっかけとなりました。
お互いが、お互いの目標や夢を追い続ける。応援し合える。
支え合える。そんな関係を築いていこうと思っています。
SCDVなるものを使ってみた話

SCDV（Sparse Composite Document Vectors）とは文書の類似度を測るための手法（文書の特徴の表し方）です。文書の類似度を測るための手法は他にもいくつかある（たとえばBag of Wordsとかtf-idfとか）のですが、その中でも優れているということで最近使われ始めているようです。
こちらが元論文です。
https://arxiv.org/pdf/1612.06778.pdf

コードはこちらを参考に書いてみました。
https://www.pytry3g.com/entry/text-classification-SCDV



# そもそもSCDVって何がすごいの？
Word2Vecを使って類義語問題を解決して（しようとして）いる点と、その単語群をクラスタリングすることで一定のトピックでまとめる点、さらにはSparse化することによって計算時間を減らして（へらそうとして）いる点があります。
少しやったことがある方はわかると思うのですが、自然言語処理において類義語問題は必ず出てきます。MacintoshとMacとかWindowsとWinとかを同じものと捉える必要がある、というお話です。それを解決するために類義語辞書を持ったりするのですが、準備が面倒だったりアップデートが面倒だったりします。Word2Vecはそこをある程度解決してくれる手法です。それをさらにクラスタリングしてトピック分類して使っています。
また、Sparse化の話はこちらのリンクなどを参照してもらえるのが早いかと。ざっくりいうと、小さな値は無視して計算すると、精度はあんまり下がらないのに計算時間はとっても速くなる、という話です。Sparseというのは「疎」という意味です。小さい値を無視して数値の分布を疎にするという意味だと理解しています。
https://developer.smartnews.com/blog/2017/06/sparse-neural-network/

# 実装時ハマった話
実装時にいろいろ苦労したので、残しておきます。
なお前述のサンプルコードをベースに説明します。

## Mecab->Janome問題
この記事にも書いてあるんですが、Janomeはとっても導入しやすいです。サンプルコードはMecabで書かれていたのですが、インストールに手間取ってあきらめてJanomeにしてしまいました。
https://ushinji.hatenablog.com/entry/2017/11/23/161031

## Word2VecのコーパスとSCDVのコーパスは違う
ここでWord2Vecのコーパスを読み込んでいるのですが、ここで渡すコーパスをSCDVで使うものと一致させないと、知らない単語が出てきて結果が期待と違ったものになってしまいます。
Word2Vecのコーパスがよりリッチなものなら、敢えて別のコーパスを使うという選択ももちろんありです。

```
sentences, train_x, test_x, train_t, test_t = dataset.load_corpus()
```

## number of clustersにご注意
number of clustersというパラメータがあります。これはSCDVのクラスターの数を決めるパラメータです。ここを少なくしすぎてしまうと同じクラスターにたくさんの単語が分類されてしまい、類似した文書がたくさん出てきてしまう結果になると思われます。これはやってみた経験則ですが、コーパスのサイズが大きくなればなるほど、クラスターの数は増やしたほうがよさそうです。

```
    parser.add_argument(
        '--num_clusters', type=int, default=50
    )
```

## window_sizeは計算時間への影響が大きい
window_sizeというパラメータはどこまでの範囲の単語を「隣」と捉えるかの設定です。このパラメータがが大きければ大きいほどWord2Vecの計算時間が長くなります。経験的にはあまり大きくしても結果の改善には寄与しなかったので、1か2ぐらいが適切かなと思っています。

```
    parser.add_argument(
        '--window_size', type=int, default=2
    )
```

## メモリ消費で死んだ
ここで正規化された文書ベクトルの箱を作るのですが、コーパスサイズ*クラスターの数*フィーチャーの数という計算になるので、ターゲットになるコーパスのサイズを増やしたり、前述のとおりそれに従ってクラスターの数を増やしたりすると、すぐに10GBとかいっちゃいます。ご安全に。

```
    def make_gwbowv(self, corpus, train=True):
       # gwbowv is a matrix which contains normalized document vectors.
       gwbowv = np.zeros((len(corpus), self.num_clusters*self.num_features)).astype(np.float32)
```

# その他わかったこと
## Skip-gram
Skip-gramのパラメータを以下で設定します。

```
    parser.add_argument(
       '--sg', type=int, default=1
   )
```

Skip-gramの意味は以下で書かれていますが、あんまり理解していないです。入力層から隠れ層への重みを設定する、というもののようです。むずい。
https://arxiv.org/pdf/1301.3781.pdf

## SCDVの各次元は単語ではない
直感的には文書のベクトルというと単語のベクトルになりそうなのですがそうではなかったみたいです。その素性は、単語の特性のベクトルということらしいです。言い換えると、Word2Vecで単語をベクトル化するのですが、その次元がそのままSCDVの次元になります。

# まとめ
エキスパートではないのでSCDVの意味自体を完全には理解していないと思うのですが、それでもいい感じに使えました。ちょっと頑張った文書処理をしたいのであれば、おためしあれ。
npmのsave-devの使いどころ

# 参考

[node.jsの初歩から実践までが良く分かりました！](https://amzn.to/2ZQuDOT)

#yarnに乗り換えた話
[npmを使い始めて３日目、さっそくyarnに変更しちゃいました](https://qiita.com/osorezugoing/items/74c2fd945a0fee4f2415)

#なぜsave-devを書くのか
たいていパッケージというものはそのパッケージ自身単体で完結するものではなく、複数のパッケージが組み合わさって成り立っている。このような状態のことを依存関係という。npmは自動的に依存関係を保つようにインストールしてくれる。さらにオプションを付け加えるで本番用と開発用など用途別にパッケージを分けることができるようになる。

# save-dev
フォーマッターやビルドツールなどを入れる。
 ・構文チェックに使うもの　eslint
 ・フォーマッターなど prettier

```terminal:開発用に使うとき
npm install --save-dev パッケージ名
npm i -D パッケージ名
```


# production
save-dev以外のものを入れる。

```terminal:本番用に使うとき
npm install --production パッケージ名
npm i -P パッケージ名
```

# オプションは必ずつける
オプションをつけるとパッケージの移動ができます。たとえばdevDependenciesからdependenciesへ移動をオプションなしではできない。そこで私はaliasで次のように設定している。

####
```terminal:aliasの設定
alias npmi='npm install --production'↲
alias npmid='npm install --save-dev'↲
```
plunkerでtensorflow.js その25

#概要

plunkerでtensorflow.jsやってみた。
benchmark作ってみた。

#写真


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b07225af-8761-9c4f-4ddd-2236d838a09f.png)


#成果物

https://embed.plnkr.co/uhhIByud4wAwgpUzXT4x/

以上。
グロースハックについて内定者たちとしたディスカッション

株式会社ウィルゲートの石川です。

今回は[ウィルゲート Advent Calendar 2019](https://qiita.com/advent-calendar/2019/willgate)を[zoe302](https://qiita.com/zoe302)さんから引き継ぎ、12/20の記事を書くことになりました。よろしくお願いします。

「グロースハックせずして、事業成長せず」、とも言われてるこのご時世、斬新なアイディアやちょっとした工夫でカスタマーの満足度が変わり、事業指標に影響を与えます。
今回の記事では、2019年新卒のエンジニア達が内定者時代に行ったとあるディスカッションについて取り上げたいと思います。

# 経緯
2019卒のエンジニアが内定者時代に開発室では、リモートインターンや輪読会を開催しコミュニケーションを図ろうとしてました。この輪読会・交流の場の１企画として、日頃接しない社員とコミュニケーションをしてみるのも面白そうだということで、私が招待されることになりました。
ここで私がチョイスしたのはグロースハックについてでしたが、他の社員は「お金の話」や「転職のすゝめ」だったり、個々の色がでるお話をしていたようでした。

# お題
この企画で参考にしたのは「Creative Mindset」というIDEO社 の Tim Brownさんが書いた本です。
その中から、高山地帯の出生率が低いこと、生まれたての子供が寒さに耐えきれず命を落とすケースが多いことに注目したスタートアップ企業が、開発した電気毛布を改良した電気寝袋に関して取り上げてみました。

<center>
<img width="227" alt="サンプル画像" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507074/1c0cdbac-a777-32e0-b976-e7ce5de4816a.png">
サンプル画像（ひどい絵ですみません）
</center>


参加者には、「なぜ救えるはずの製品が、効果を見出せなかったのか、問題点を議論してほしい、その上での対策、施策も考えて欲しい」、というお題をだしました。

# 当日の様子
昼に私含め社員数名で会社の会議室に集まり、ランチしつつ、当時リリースされたてのSlack Call(スラック の通話機能）でグループ通話で実施しました。

参加した面々が物事を考えることが好きな人たちだったこともあり、様々な意見が飛び出しました。
人の考え方・見え方・捉え方などはバックグラウンドが様々だったり、個性的な部分でもあるので、観察する側からするとすごく興味深いものでした。
ある人は使われ方、思想について意見持っていたり、プロダクトのイメージに注目して意見を出したり、人の行動について注目したりなどなど。。。
みんなで「たしかに」とうなずきたくなるような一幕もあったり。
(写真撮っておけばよかった、と反省しつつ)

# まとめ
ここで学んで欲しかったことというのは、プロダクトに入り込んでしまうと、視野が狭くなりがちで、ユーザを考えたものづくりを見失いがちになるので、「広い視野でどう使わせたいのか」、「どう使われるだろうか」を考えるトレーニングでこの企画を検討、実施してみました。
またディスカッションを通じて、内定者たちのキャラクターや、ものの捉え方・考え方は既存社員にいい刺激になりました。
ものづくりに立ち返ったときにどうして行ったらいいのか、どのようなスタンス・考え方でプロダクトを作っていければ自分たちがワクワクして働けるのか見つめ直せる機会になったと思ってます。
一番嬉しかったのは、このイベントを通じて皆がこういうのがいい、物づくりが楽しくなりそうと言った感想でしたけどね！

明日は[@Dash_Kojima](http://ribastdesumono.hatenablog.com/)さんで「思春期エンジニアだから自室の出入りを監視したい」です！
Insertion Sort

# Pythonで「挿入ソート（Insertion Sort）」
## はじめに

ここでは[「プログラミングコンテスト攻略のためのアルゴリズムとデータ構造」][1]の中で取り上げられている[「AOJ (Aizu Online Judge」)][2]の問題を自分で解いた際に学んだことや、こう考えれば分かりやすいと感じたことなどを自分への整理も兼ねてまとめています。
このテキストはC++で書かれているので、私のようにpythonで勉強をされている初学者の方の参考になれば幸いです。また私自身も初学者ゆえ、至らない点が多々あると思いますので、ご指摘・ご助言頂ければ喜びます。よろしくお願いします。

## 問題詳細

[ALDS 1_1_A: Insertion Sort][3]
挿入ソートで昇順に並べ替える問題です。
問題詳細は上記リンクをご参考ください
## 考え方
・先頭の要素をソート済みとする
・未ソートの部分がなくなるまで、以下の処理を繰り返す
　　1. 未ソート部分の先頭から要素を１つ取り出して、vに入れる
　　2. ソート済みの部分において、vよりも大きい要素を１つずつ移動する
　　3. 最後に空いた位置に「取り出した要素v」を挿入する

## pythonコード
```python
def InsertionSort(A, N):
    for i in range(N):
        v = A[i]       # A[i]は未ソート部分の先頭
        j = i - 1
        while j >= 0 and A[j] > v: 
            A[j+1] = A[j]  # vよりも大きい要素を一つ右に移動させる
            j -= 1     # 比較する位置を移動
        A[j+1] = v     # 空いた部分にvを入れる
        print(*A)

N = int(input())
A = list(map(int, input().split()))

InsertionSort(A, N)
```````

## ポイント
・未ソート部分の先頭の値と比較を行うのはA[j]であり、A[j]の方が大きい場合、A[j+1]にA[j]を移動させる。この時に実質空いているのはA[j]の位置であるが、これと同じタイミングでwhile内でj-1を行うため、未ソート部分の先頭を移動させる際に空いている位置はj+1になります。

## まとめ
以上となります。間違いや改善点などございましたら、よろしくお願いいたします。


[1]:https://book.mynavi.jp/ec/products/detail/id=35408
[2]:https://onlinejudge.u-aizu.ac.jp/home
[3]:https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/1/ALDS1_1_A
Kubernetes が”クラウド界のLinux”と表現される理由について考えてみる

＊オープンソースカンファレンス 2019 Fukuoka の発表をベースにしています。発表時点での個人的見解であります。

５つの視点からながめてみる・・・・

* ソフトウェア
* ポータビリティ
* エコシステム
* 金のなる木
* 縁の下の力持ち

# ソフトウェア

* 両方とも**オープンソースソフトウェア**
* サーバOSとしてのデファクト「**Linux**」
* コンテナオーケストレーションとしてのデファクト「**Kubernetes**」

コミュニティがともに大きく、Linux は"The Linux Foundation" , Kubernetes は "Cloud Native Computing Foundation"が築かれている。

# ポータビリティ

プラットフォームを選ばずに稼働ができる。平たく言うとどちらもいろんなところで動かす事ができる。

* 物理マシン
* 仮想マシン
* クラウドサービス
* 小さいデバイス（Embedded など、IoTなデバイス等）

# エコシステム

単体だけでなく、周囲を様々巻き込むことで更に機能が強化されている。

* ディストリビューション
* プラグイン・モジュール等によるコア機能拡張
* パッケージ管理による機能拡張

![eco.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75458/2b817173-5434-07a7-9e6a-9c331d5f9c58.jpeg)

# 金のなる木

エンタープライズベンダーは、自社プロダクトやサービスに採用し、価値を高めている。

* ハードウェアの接続環境への対応（外部デバイスとして◯◯◯対応など）
* ソフトウェアの提供形式への対応（各種手持ちのM/W の コンテナライズ/マニフェスト/サポート提供）
* クラウドサービス上での対応（as a Service）

![ki.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75458/156cc6a9-cd03-804f-d2e8-1e7a0e7b1aae.jpeg)


# 縁の下の力持ち

**"Linux"** , **" Kubernetes "** はそれ自体は裏方・・・

* 大雑把にいうと”ICTインフラ”の部分に所属
* ”その上で”動かされるソフトウェアやサービスこそ”価値”があるもの

# まとめの図

このように、すごく似ている、だから「**クラウド界のLinux**」と言われるのもうなずける！

![link8s.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75458/1a1d6e32-49ec-6753-007a-4d3b2263e40e.jpeg)
入社して3年、ずっとやってきた仕事をまるっとハックして月200時間業務削減した話

## はじめましてとこの記事で伝えたいこと
・社会人3年目文系卒エンジニア
・大学では倫理学専攻　善く生きる
・柴﨑(崎じゃないよ)

**運用は、入り口と出口を作るのが人間、中の迷路はシステムに走らせる**

## さかのぼること3年前

柴﨑「晴れて社会人だ！プログラミングのことはよくわからないけどITベンチャーでかっこいい社会人になるぞ！！」

柴﨑「ふんふん、、、私の仕事は、CLOUDアプリケーションの中のオプション商品を、契約が入ったら使える状態に設定することね」

柴﨑「商品が使える状態になったらお客様に伝えないといけないのね。商品の設定状況をお客様担当に伝達して、お客様に案内してもらって完了か。」

柴﨑「めちゃめちゃ頑張ってたくさん設定するぞ！」



## そして二年が経ち、、、
- 問題点①　契約管理ツールの発行漏れやミスが起きる
- 問題点②　契約管理ツールから営業の案内用ツールへの移行漏れが起きる
- 問題点③　上記二つの問題点をカバーするために、チェック要員を増やし運用コスト爆増

**止まらないヒューマンエラーとの戦いに、運用フローが肥大化！！**

柴﨑「頑張ってるのにミスを出してしまう、私はダメなやつだ、、、」

### before
![キータ用ビフォー.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474845/f786be6a-5558-0599-794d-5895d37fa2b8.jpeg)



## どうしようもないのか、いやそんなことはない

契約登録から営業にお客様への案内をしてもらうところまで、
一貫して完了できる自社システムを開発

**頑張らなくてもミスが出ない運用フローの完成！！！**
### after
![キータ用アフター.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474845/a5340209-925a-bcce-4997-95a9433254f3.jpeg)

## 運用フローは入り口と出口を抑えれば漏れない　案件が消える分岐を作らない
運用フローもアルゴリズム、ミス発生率の高い分岐はそもそも含んではいけない
フローの入り口に確実に全ての案件がきて、出口を簡単に確認するだけのフローにする

中の分岐は全てシステムを組んでやってもらう　**エンジニアなんだから！！**



## ミスが減っただけでなく
- 社員の対応コストが月200時間削減された
- 自社システムで完結しているため契約者・システム担当者・お客様案内担当が今誰ボールで進捗がどうなってるのか確認できるようになった（今までは社内チャットで直接確認していた）
- 契約者以外でも、新システム上で案件の操作を可能に　

状況に合わせて自由度の高いフローへ　内製のため要望対応も随時できる

## 運用の明るい未来について
運用フローの変更は勇気がいる
その運用が長く、扱っている対象が多ければ多いほど変更へのリスクも高い
フローを変更しなくても明日は困らないかもしれない

でも1年後、2年後、そして未来の後輩たちのことを考えたらどうだろう
今起きている問題は本当に『仕方のない』ものなんだろうか

せっかく愛情注いで商品を作ったなら、
その商品をいっぱい売ってくれる人や売れた後に対応してくれる方への感謝を忘れず、
エンジニアとしてできることを日々追求しましょう！
わが子(商材)は社外ではもちろん、社内でも愛されてこそ！！！

＝＝＝＝＝＝＝＝＝＝＝＝

偉い方「柴﨑！この新しいシステム良いね。
セール○フォー○ではこういうこともできるらしいから、同じ機能つけてよ」

柴﨑「はい！！！！！！！！」

おしまい
素敵なエンジニアになるためにインプットとアウトプットを繰り返す

## はじめに
以前、[アウトプット大全](https://www.amazon.co.jp/%E5%AD%A6%E3%81%B3%E3%82%92%E7%B5%90%E6%9E%9C%E3%81%AB%E5%A4%89%E3%81%88%E3%82%8B%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E5%A4%A7%E5%85%A8-Sanctuary-books-%E6%A8%BA%E6%B2%A2%E7%B4%AB%E8%8B%91/dp/4801400558)を読んだのですが、これによると、2週間に3回使った情報は長期記憶される、とのことです。言い方を変えると、インプット（読書、Web記事読む、人から話を聞く）をどれだけ繰り返しても使わない限りそれらの情報は脳内から忘れ去られる、ということです。何となくわかる気がします。本記事では、エンジニアがインプットするメリットとアウトプットするメリットを書いてみようと思います。

## インプットするメリット

### 1.理解力が高まる
補足：理解力が高まる、とは（自分的の解釈では）本質を短い時間で理解する力が高まる、ということです。書籍を読む、人の話を聞く、これらを繰り返す中で、本質を理解しようと頭を使えば使うほど理解力が高まります。

### 2.単純に知識が増える
これは言わずもがなです。

## アウトプットするメリット

### 1. 頭の中が整理される
補足：情報をインプットしても意外と理解度がチグハグだったり、点と点の状態でしっかりと全体像を捉えて理解できていないことが多々あります。

### 2. 物事をロジカルに考えられるようになる
補足：アウトプットするにはまずは枠組み（章立て）から考えていくのが一般的です。そういった順序を組み立てることは、物事をロジカルに考えるのに非常に有用となります。

### 3. 文章でのコミュニケーション能力が向上する
補足：人に見てもらうケースの場合、「理解してもらう」必要があるので、そこを常に意識しながら書くことで、自然と文章でのコミュニケーション能力が向上します。

### 4. 後で見返すことができる
補足：聞いただけの情報は数日後には必ず忘れます。貴重な時間を割いて仕入れた情報は忘れてもいいように（後で見返して思い出すことができるように）しておく必要があります。

### 5. 必ず誰かの役に立つ
補足：自分がアウトプットした情報を見て誰かが問題を解決できたりそれに共感してその誰かもアウトプットをし始めて、、、、の連鎖って素晴らしいと思います。
※Qiitaや個人ブログに助けられた経験は誰にでもあるハズ。

### 6. 評価される
補足：「〇〇を学習する」という目標を立てても、それに対するアウトプットがないと評価ができないケースがあります（「〇〇を学習しました！」と言われても、何を見て評価をすれば良いかわからない）。学習した内容を技術ブログに書く、Githubにソースを公開する、社内勉強会を開催する等、アウトプットの方法は様々ですが、こういった行動を起こさないと評価しにくくなります。

### 7. エンジニアとしてのプレゼンスが向上する
補足：Qiitaや個人ブログにアウトプットすると、「おっ、よくわからんけどなんかアイツ知ってそう、スゲエ」ってなる。その結果、仕事の幅が広がる（と思う）。
※これは完全に自分のエゴ。

以上です。
Djangoで作ったwebアプリケーションに画像を表示する方法

#自作のアプリケーション上に画像を表示するには
記事投稿を目的としたサービスは特に画像を多用します。
少なくとも記事一覧と記事詳細画面にはその目的に応じた画像を表示させたいでしょう。
今回は記事一覧にサムネイル画像を設置する事をゴールにして、どのように画像のアップロードを行うのかをまとめます。
ちなみに僕は3時間ぐらい調べたり悩んだりしました。

#画像を表示するには
簡単に言うと、htmlのsrc=""にパスを表示する事が出来れば画像が表示されます。
よって、
・そのパスを格納する場所
・パスを関数を使って最適に表示する
これらの処理が必要です。

#参考にした記事
今回は
・画像をアップロードする
https://qiita.com/j54854/items/1f0560142e39d888251c
・アップロードした画像を表示する
https://qiita.com/felyce/items/57421ea191ab89175e9e
それぞれURLの記事を使って行いました。
Qiitaって良記事があっても組み合わせて解決しないといけない課題があった時に探す時間がかかりますよね。。。

#つまづいたところ
画像のファイルとパス設計が出来ても、フロントに出す時のURL取得が上手くいきませんでした。

```
<img class="img-thumbnail" src="{{ day.picture.thumbnail.url }}" alt="Thumbnail image">
```
srcの中で画像のパスを指定することが上手くいかず、結論、
day.picture.thumbnail.urlの.urlを加える事で解消しました。
[BluePrism]プロセスを全員殺したい #blueprism

クリスマスとかアドベントカレンダーとか全然関係ない、Blue Prismの普通の記事です。
だって普通の平日ですよね？別に機嫌悪かったりしませんよ？

# プロセスを終了させる、再度起動させる、で困った

プロセスを終了させるのには
標準VBOの「Utility - Environment」の中に「Kill Process」というのがあります。
しかしこのVBOをお使いになったかたで
「当該のアプリを終了させて、再度立ち上げようとしたときにうまく立ち上がらない」
というようなことに遭遇したかたもいらっしゃるかと思います。

# うまくいかない理由（たぶん）

このVBOで使われているのは
[Process.Kill メソッド](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.process.kill?view=netframework-4.8)
なんですけど、
これの「注意」っていうところに
> すべての子孫がまだ終了していない場合でも、終了が完了したことを示します。

って書いてあって
つまりこれって、Killメソッドだと、孫以下の関連プロセスとかは終了しきれないでオバケになっちゃうってことですよね……？
それのせいで次に起動するときにそれが邪魔になってるってことでは……？

# だったら確実に全部殺すにはどうしたらいいか

このコマンドを使えばいいらしい。Qiita探すとなんでも書いてあってすごいなあ。
[taskkill コマンドで、プロセスを強制終了する](https://qiita.com/rohinomiya/items/a58c7104dc5141a468fa)

うしろにつけるオプションの説明は、[こちらのMicrosoft 公式の説明を参照](https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/taskkill)。

VBOでコマンドを実行するにはどうしたらいいかというと
[DOSコマンドを実行し出力データを取得する](https://dobon.net/vb/dotnet/process/standardoutput.html)

processオブジェクトの説明は
[Process クラス(Microsoft公式の説明)](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.process?view=netcore-3.1)

# これらを踏まえて作ったもの

1. 新しいVBOを作成して、「プロセス絶対殺す」と名前をつけたら、「Utility - Environment」VBOの「Kill Process」アクションをコピーしてきます。
2. Initializeで設定する名前空間は、「Utility - Environment」をそのまま真似して設定しました。DLLも真似して設定しとけばいいと思います。
 ![namespace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/42e99ae1-444e-9267-5c55-eef0948304d2.png)

3. コードステージの中を書き換えて、taskkillコマンドでプロセスを終了させるようにします。
入力引数は、元にした「Kill Process」と同じ「ProcessName」で、出力引数は無しです。
もし気になるなら、コードステージの前に入力引数がちゃんと入ってるかのチェックを入れとくといいかも。

VB

```VB
'Processオブジェクトを作成
Dim p As New System.Diagnostics.Process()

'ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定
p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec")

'taskkillコマンドをここで作ります
p.StartInfo.Arguments = "/c taskkill /F /T /FI ""username eq %USERNAME%"" /IM " & ProcessName

'初期化
p.StartInfo.UseShellExecute = false
p.StartInfo.CreateNoWindow = true

'起動
p.Start()

'プロセス終了まで待機してから終わる
p.WaitForExit()
p.Close()
```

バリエーションとして、プロセスIDを指定してそいつだけ狙ってkillするのも書きました。入力引数は「PID」です。データ型はNumber。c#

```c#
int iPID = (int)PID;
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(iPID);
if (p != null) {

p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
p.StartInfo.Arguments = "/c taskkill /pid " + Convert.ToString(iPID);
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;

p.Start();

p.WaitForExit();
p.Close();
}
```


# 終わりです
標準VBOの中身をずーっと読んでいくといろいろ勉強になるなあ、と最近思います。
あれ、これとこれのVBOは中身いっしょじゃん……？みたいなのも見つけたりしてちょっとおもしろいです。
オレオレAWSチートシート

【適時更新】AWSであれがしたいとなったときに自分が見るやつ

# AWS CLI

## プロファイルを分けて使う

アカウントごとにconfigureを実施し、

```
$ aws configure --profile プロファイル名
```

使う場合は`--profile=プロファイル名`をコマンドの最後に付与する

```:例
$ aws s3 ls --profile=dev
```

- https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html

# ECR

## イメージをローカルPCに取得
pullしてくる

```
$ aws ecr get-login --no-include-email --profile=dev
$ （上記の出力結果をコピペしてdocker loginを実行）
$ docker pull ECRのURI
```

- https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/ECR_AWSCLI.html#AWSCLI_pull_image


# API Gateway

## Lambdaと繋げる（POST）

### 1. APIの準備
1. 「APIを作成」から「REST API」を作成
2. リソースのアクションから「メソッドの作成」を行う
    3. パスを作る場合は、先にリリースの作成を行う
4. 作成したメソッドで、メソッドの実行から「統合リクエスト」をクリック
    5. 統合タイプを「Lambda 関数」に
        6. 「Lambda プロキシ統合の使用」は**チェックしない**
        7. 「Lambda 関数」に対象の関数を設定
    6. マッピングテンプレートで、リクエスト本文のパススルーを設定
        5. 「リクエストの Content-Type ヘッダーに一致するテンプレートがない場合」を選択
        5. Content-Typeに`application/x-www-form-urlencoded`を追加し、以下を設定

```json
{
  "body" : $input.json('$')
}
```

### 2. APIのデプロイ
1. リソースのアクションから「APIのデプロイ」を行う
    2. 新しいステージにし、、適当に名前を設定する
3. 「ステージ」のメニューを選択するとアクセスURLが表示されている
工場の小集団活動の状況をPowerBIで可視化してみる


#概要
工場とかで小集団活動などをやってたりするけど、いろいろ掲示したり、可視化したり、みんなで同じ情報を共有して、議論の土俵を揃えるって本当に大切だと思う。でも、その為にいろいろExcelを加工したり、掲示用に綺麗にしたりなどなどに現場の人が時間を掛け過ぎてやっているとと何の為にやってるのか目的を見失いそうなので、何か簡単に出来ないかと思って、PowerBIでやってみることにしました。

#システム構成
* 小集団活動のアイデアはホワイトボード＋Word議事録（従来通り）
* 運用を簡単にしたいので、OneDrive上にExcelファイルで件数管理（これは人手で修正）
* でも、Excelファイルなので、現場の人でも簡単修正
* 可視化はPowerBIを使う
* 人が入力したら自動でサイネージが切り替わる
![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/36f50f36-80b7-b60a-d5e4-9f0ff905790a.jpeg)

#データ例
本当はあまり良くないのかもしれないけど、小集団活動が開催されない月もあるので、開催・未開催自体もデータに含みます。こんな感じ。
isHeld：０（未開催）、１（開催）

|Date|Team|isHeld|idea|
|---|---|---|---|
|2019/9|A|1|6|
|2019/9|B|1|4|
|2019/9|C|1|3|
|2019/10|A|1|6|
|2019/10|B|0||
|2019/10|C|1|3|



#可視化例
PowerBIで可視化するとこんな感じ。
![002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/67920b25-ac27-0cba-fcfa-ae733fa72f0b.jpeg)

* 活動回数が少ない月が一目で分かる
* 全体で活性化しているチームが分かる
* チームごとの推移が分かる
* 活動自体が未開催でidea件数がnullのところが上手く表示できてないので、この辺りはもう少し頑張る


#これからやること
実はまだサイネージに表示したりするところはやってないので、これからシステム含めてごにょごにょやる予定です。
あとは、その他のアンケートなどもMicrosoft FormsやMicrosoft PowerAppsを使えば、もっと入力も簡単に出来て、簡単に可視化できると思うので、この辺りも地道に調べながら運用しやすいシステムに仕上げていきます。
Symfony4.4から導入されたNotificationEmailが気になったのでさわってみた

[Symfony Advent Calendar 2019](https://qiita.com/advent-calendar/2019/symfony) 20日目の記事です。
Symfony4.4から導入された[NotificationEmail](https://symfony.com/blog/new-in-symfony-4-4-notification-emails)。『NotificationなEmailとは🤔』となったので、実際に触ってみました。

## NotificationEmailとは
NotificationEmailはSymfonyのメールデータ生成クラスのひとつです。TemplateEmailの子クラスで、基本的にはTemplateEmailクラスと同じ使い方です。TemplateMailと大きく違うところは、テンプレートファイルを指定しなくて良いことと、themeというプロパティができたこと、markdown()というメソッドが追加されていることです。

テンプレートファイルはデフォルト定義されており、``` vendor/symfony/twig-bridge/Resources/views/Email ``` に格納されています。左記ディレクトリのthemeで指定したディレクトリにテンプレートファイルが入っています。デフォルトのthemeはdefaultですが、defaultはzurb_2をインポートしており、[Foundation for Emails 2](https://foundation.zurb.com/emails.html)を利用して、テンプレートが作成されています。Foundation for Emails2により、見た目よさげなメールが作成できます。

## インストール
インストールは、composerを使ってインストールします。

```
composer require symfony/mailer
composer require twig/cssinliner-extra
composer require twig/inky-extra
composer require twig/markdown-extra
composer require erusev/parsedown
```

メールを送るだけならsymfony/mailerだけで十分ですが、インラインでのCSS修飾、Markdown記述＆解析が必要なため複数コンポーネントをインストールする必要があります。

## 実装

```php
        $name = 'めもりー';

        $message = <<< MSG_EOR
![Symfony Logo](https://symfony.com/images/logos/header-logo.svg)
# こんにちは！
こんにちは。${name} ちゃん。  
こちらはテストメッセージです。  
SymfonyにNotificationEmailという機能が追加されました！  
[Symfonyって？](https://symfony.com/)  
MSG_EOR;

        $notificationEmail = new NotificationEmail();
        $email = $notificationEmail->from('from@***.co.jp')
            ->to('to@***.co.jp')
            ->subject('テスト送信です')
            ->markdown($message)
            ->action('NotificationEmailについてもっと詳しく', 'https://symfony.com/blog/new-in-symfony-4-4-notification-emails')
            ->importance(NotificationEmail::IMPORTANCE_HIGH)
            ;
        $this->mailer->send($email); // $this->mailerはDIコンテナでMailerInterfaceを刺してます。
```


NotificationEmailのそれぞれのメソッドですが、

| メソッド | 説明 |
|:-------------|:------------------------------------------------------------------|
| from()       | Fromアドレスを指定します。 |
| to()         | To アドレスを指定します。  |
| subject()    | 題名を指定します。 |
| markdown()   | Markdown形式の本文を指定します。独自メソッド |
| action()     | メール下部に指定した文言、リンクでボタンを配置します。独自メソッド |
| importance() | メールの重要度を指定します。メール題名の前に[HIGH]というような文言が入ります。HIGH, MEDIUM, URGENT, LOWがあります。独自メソッド　|
| theme()   | 指定したテーマに切り替えます。独自メソッド。使うことはないかな |

TemplateEmailの子クラスなので、そのほかのTemplateEmailのメソッドも使えますが、おそらく使うことはないでしょう。

## 実行
実行すると以下のようなHTMLメールが送信されます。

<img width="375" alt="IMG_1333.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9882/3f7bd1d1-67a7-26d1-f5fd-b787d09b7f46.png">

良い感じでMarkdownを解析したメールを受け取ることができます。上記の実装サンプルに追加でリストや引用もつけてみましたが、ちゃんと解析されて表示されます。

すっきりとしたレイアウトでテンプレートも不要。Markdownでそれなりに体裁を整えたメールが送信できるので、サイト管理者などに送る通知メールには向いているかなと思いました。現場からは以上です。
【Express + Postgres】非同期とかトランザクションとか考慮したDB接続

# はじめに
以前にも似たような記事（※）を書いたが、より汎用性のありそうなコードを書く機会があったので、本記事にまとめておく。
おそらく、非同期とかトランザクションとかも考慮しているコードになっているはず…

※[【Node.js+Express+PostgreSQL】ExpressにPostgreSQLを導入](https://qiita.com/c6tower/items/c6fc18e14229dbf2f53a)

## 環境
* node 10.15
* express 4.17
* pg 7.12

## サンプルコード

```:command
npm install --save pg
```

```js:index.js
const express = require("express");
const pg = require("pg");
const app = express();
const port = 3000;

app.listen(port, () => {
  console.log(`Start server port: ${port}`);
});

const pool = new pg.pool({
  host: "hoge",
  database: "hogehoge",
  user: "hogehogehoge",
  port: 5432,
  password: "hogehogehogehoge"
});

app.post("/register", (req, res) => {
  const id = req.body.post_id;
  ( async () => {
    const client = pool.connect();
    try{
      await client.query("BEGIN");
      let result = await client.query("SELECT name FROM users WHERE id = $1", [id]);
      const user_name = result.rows[0];
      client.query("INSERT INTO teams (member) VALUES ($1)", [user_name]);
      await client.query("COMMIT");
      res.json({
        msg: "Successfully insert data!"
      });
    } catch {
      await client.query("ROLLBACK");
      throw err
    }  finally {
      client.release();
    }
  })().catch( err => {
    console.log(err.stack);
    res.json({
      msg: "Fail to insert data"
    });
  });
});
```

### 解説
まず、クライアントから送られてきた``post_id``をもとに、``users``テーブルから``name``を検索。
次に、その``name``を``teams``テーブルの``member``列に保存。
以上が実現したい処理の流れ。

* ``const pool = new pg.pool{ ... }``の部分で、DB接続情報の設定。
* Node.jsのDBアクセスは非同期推奨なので、``(async () => { ... })``とする。
* ``const client = await pool.connect();``で同期的にDBに接続。
* 読みやすさ重視で``try{ } catch{ } finally{ }``
    * 処理順がわからなかったが、[ここ](https://qiita.com/eijenson/items/7e9e112e69b37f72353c)が参考になった。
* トランザクションは、``BEGIN``で始まり、``COMMIT``または``ROLLBACK``で終わる。
    * ``await client.query("BEGIN"); ... await client.query("COMMIT");``の場合、これらに囲まれている範囲のSQL文は、正常にデータベースに反映される。
    * ``await client.query("BEGIN"); ... await client.query("ROLLBACK");``の場合、これらに囲まれている範囲のSQL文は、破棄されてデータベースには反映されない。
    * つまり、上記のサンプルコードのように、正常時には``COMMIT``で終わるように、エラー時には``ROLLBACK``で終わるように書けばよい。
* ``client.release();``は、DB接続を切るみたいな認識（要確認）

## おわりに
取り急ぎ、メモとして残したので、抜け漏れなどあるかと。
見つけ次第、随時修正します。

## 参考サイト
* [node-pgのドキュメント](https://node-postgres.com/features/transactions)
* [トランザクションについて](https://qiita.com/komattio/items/838ea5df68eb076e8099)
* [try catch finallyについて](https://qiita.com/eijenson/items/7e9e112e69b37f72353c)
【Laravel初学者向け】頻出キーワードの語彙帳


フレームワークを勉強しようとした時に理解が進まなくなる瞬間があります、それは訳の分からない単語が出た時。
なのでこの記事では、**特にLaravel学習中に単語の意味が解らない/理解が深くない単語が出た**、そんな時に備えてそれなりに**頻出されるキーワードを解説/紹介**していこうと思います。

**なおこの記事は、辞典並みの正確性より、理解を深める事を優先にした作りにしています。**
また、似通った概念は「/」で1項目に括り、同時解説をする事で情報をまとめています。

#フレームワーク/ライブラリ

フレームワークもライブラリも、システム構築をする為の機能を提供してくれるものです。

では逆に、フレームワークとライブラリの違いはなんでしょうか？
フレームワークは「安全性、メンテナンス性、セキュリティ、拡張性」と言った基本的な機能を使うだけで半自動的に組み込んでくれます。
逆に、ライブラリは便利な機能がただ提供されるだけです。

つまり、**フレームワークは、拡張性やセキュリティやメンテナンス性などを半自動的に提供してくれるもの**だと言えますね。

#MVC/Model/View/Controller

**MVCとは、Model/View/Controllerの頭文字をとったものです。**

- 「Model」…プログラムの具体的な処理&データベースからの情報回収/挿入を担当
- 「View」…見た目部分を担当
- 「Coltroller」…利用者の入力と処理を行い、ModelとViewに指示を出す。


# ルーティング

あるアドレスからアクセスしたときに、どのように処理をするのか管理するもの。
「Route::get()」というような記述をするファイル。

#Bladeテンプレート

**Laravelで見た目（View）を作る為の仕組み。**

Bladeテンプレートには簡単に仕組みを挿入する事ができるようになるための工夫がある。
具体的にはディレクティブ（@yield('test')）のような普通なHTMLでは見かけないタグを用いて、他所で設計したHTMLのパーツを埋め込む事が出来る。


#ORM

**データベース（MySQLやMariaDBと言ったもの）を、PHPサイドで使いやすい形式にしてくれるもの。**
つまり、データベースとLaravelとの連絡をPHP（Laravel）方式に統一してくれるナイスな通訳。

本来ならDBから何かの情報を問い合わせる場合、SQLという言語でデータを呼び出してそれをそれを加工するという手間をかけるのだがそれを自動でやってくれるのが、ORMという訳です。


#Composer

**ライブラリ（ソフトウェアが複数集まったもの）をプログラマーが苦労せずに管理できるようにしてくれる仕組み。**
また、**外部から導入したライブラリで自身の製作したアプリの内容が複雑にならなくなるような仕組み。**

まず大前提として、ライブラリとその依存関係について解説します。
PHPでは誰かの作ったウェブサイトのパーツを複数集めた、ライブラリというものがあり便利です。
しかし、このライブラリには依存関係の複雑性という問題点があります。具体的には"複雑になり過ぎて何が必要で、何と連携が組まれるライブラリか解らなくなる"という複雑性です。

例えば、
- Aを動かすには、BとCが必要
- Dを動かすには、BとEが必要
- Fを動かすには、DとEが必要
と言った感じで複雑化すると、作る側が混乱します。
こういった煩雑な管理を自動的にやってくれるのがComposerです。


# PATH/PATHを通す（設定する）

**PATHとは、パソコンにプログラムの名前と位置を通達することにより、手軽に呼び出せるようにしたもの。**
**PATHを通すとは、パソコンに上記の設定をすることそのものです。**
通常、効率化の為に行われる。

本来、プログラムは実行する為に「フルパス」を打ち込む必要がある。
打ち込む内容の例：「C:\windows\test\test.exe」

それをPATHを通すことで、exeファイルを直接的な名前で呼び出すことができるようになる。
打ち込む内容の例：「test.exe」

#XAMPP/MAMP

**ウェブアプリケーションを実行できるようにしてくれるソフトウェアを一括でまとめたもの。**
１個１個自分で設定しなくても良くなるというもの。

XAMPPの場合であれば、
- X…Windows、Linix、macOS、Solaris
- A…Apache
- M…MariaDB(MySQL)
- P…PHP
- P…Perl

MAMPの場合であれば、
- M…Macintosh
- A…Apache
- M…MySQL
- P…PHP


#ヒアドキュメント

ヒアドキュメントとは、長文テキスト（何行にも渡るテキスト）を、一括的に変数化する為の仕組み。
以下に例を示しますが、別に「EOF」部分が、「TXT」など別のものでも問題ない。


```php:ヒアドキュメント

$text = "php";

$text <<<EOF
テスト投稿：{$text}
EOF;

echo $text;

//以下出力結果
テスト投稿：php

```

#ルートパラメーター「{test}」

ルートパラメーターとは、第一関数で、URLの指定を行った際に入力した値の一部を、引数として引用する事が出来る機能。
**例えばURLの一部に、ユーザー名があればそのユーザー名を直接利用できるようにしたもの。**

Route::get('第一引数','第二引数'){}処理を行う際、第一引数（つまり、URLを入れる所）のデータを、引用できるようにする為の関数。

後で説明しますが、このルートパラメーターには、必ずデータが入っていないといけないものと、あっても無くてもいいデータに別れています。
ここでは先に、データが無いといけない方の解説をしていきます。

```php
Route::get('/testpage/{text}',function($text){
 echo $text;
});

//上記の$text部分に"/testpage/{text}"のtext部分が挿入される。

```

##・任意パラメーター「{test?}」

ルートパラメーターの中に「?」の表記がされる事もあります。
あれは、**ルートパラメーターにデータがあっても無くてもいいという表記です。**

こういう表記の事を、正式名称で「任意パラメーター」と言います。

※この記事はこれ以降も編集して追記していきます。

##名前空間

クラスを階層的に管理できるようにする為の仕組み。
ある名前でその範囲をくくることにより、同じ関数名、同じクラス名など名前が被っても問題なくさせる為のもの。
weavescopeをApache2.4でproxyする方法

# 概要
weavescopeはDockerの相関図をリアルタイムに表示してくれるとてもかっこよいソフトだ。
https://github.com/weaveworks/scope

しかし、ポート番号でアクセスするのがかっこ悪いのでproxyを噛まそうとするとよくはまるらしい。
https://github.com/weaveworks/scope/issues/3725

かくいう私もその口。

# 結論
WebSocketも転送してやらないとならない


# Apacheの設定ファイル例のコピペ
via https://github.com/weaveworks/scope/issues/3725#issuecomment-567626454

```
<VirtualHost *:443>
 	ServerName weavescope.<your domain>.jp


	SSLEngine on
	ServerAdmin webmaster@localhost
	SSLCertificateFile /etc/letsencrypt/live/<your domain>/cert.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/<your domain>/privkey.pem
	SSLCertificateChainFile /etc/letsencrypt/live/<your domain>/chain.pem


	ProxyRequests Off
	ProxyPreserveHost On

	RewriteEngine On
	RewriteCond %{HTTP:Connection} Upgrade [NC]
	RewriteCond %{HTTP:Upgrade} websocket [NC]
	RewriteRule /(.*) ws://localhost:4040/$1 [P,L]

	RequestHeader set X-Forwarded-Proto "https"
	RequestHeader set X-Forwarded-Port "443"


	ProxyPass / http://localhost:4040/
	ProxyPassReverse / http://localhost:4040/
	ProxyPass / ws://localhost:4040/
	ProxyPassReverse / ws://localhost:4040/

</VirtualHost>
```