YYPHP#43「フレームワークを使うと何ができるの？CakePHPでカレントのメニューの色を変える、レイヤードアーキテクチャとValue Object、どうやってPHPでプログラムを作ってる？PHPUnit、大規模開発、yyphp-quiz No.2: 月間カレンダーの表をつくろう、yyphp-quiz No.3: 多次元配列から要素」

これは2018年07月06日に開催したPHPerイベント[YYPHP#43]のイベントレポートです。

[YYPHP]は一言で「PHPerの部室」です。PHPについて、雑に、ゆるく、ワイワイ話し合う集いです。毎回お題を決めずに雑談を出発点にいろいろなことを突発的にやります。集まった人でコードリーディングをすることもあれば、一緒に開発ツールを触ってみたり、フレームワークについての情報交換をすることもあります。開催はほぼ**毎週**、高田馬場にて。

[YYPHP#43]:  https://yyphp.connpass.com/event/93167/
[YYPHP]: https://yyphp.connpass.com/
YouTubeでの配信映像はこちら-> [YYPHP #43【PHPの情報交換・ワイワイ話そう・仲間作り・ゆるめ・にぎやかめ】 - ](https://youtu.be/H1er5aGynUw)

![](https://qiita-image-store.s3.amazonaws.com/0/889/0051f99f-b555-6064-fcc9-3280e5543a1a.png)

## 参加者9名(リモート9名)

* PHP歴
    * 1年未満: 4名
    * 1年: 1名
    * 3年: 1名
    * 5年: 1名
    * 10年以上: 2名

## 話したいこと/聞きたいこと

### フレームワークを使うとどういったことができるのか？

* エディタとフレームワークの違いを知りたい
    * 全然ちがう種類のもの
* 使ってるフレームワークアンケート
    * 4人 CakePHP3
    * 1人 Laravel
* フレームワークを使うと何ができるか？
    * いろんなめんどくさいことをフレームワークに任せられる
    * 例えば、ログイン(認証)を自分で書くと大変だし、セキュリティが心配だが、フレームワークを使うと楽だし早い。 
    * フレームワーク側にある程度作り込んであって使える。
        * フルスタックフレームワークと言われる
        * ただ「マイクロフレームワーク」という最小なフレームワークは、そういうのがない
* ちゃんとしたPHPを書きたいならPhpStormが楽
    * ちゃんとコードをチェックしてくれる
    * 有料だが、使ったほうが生産的
    * https://www.jetbrains.com/phpstorm/
    * 30日間無料
* [PHP - The Wrong Way](http://www.phpthewrongway.com/ja/#%E5%B8%B8%E3%81%AB%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%92%E4%BD%BF%E3%81%86%E3%81%93%E3%81%A8)
    * 「すべての汎用 PHP フレームワークはクソ!」

### CakePHPとWordPressの連携

* 企業のホームページを作っている
    * 企業情報などはCakePHP
    * WordPressでお知らせ
* WordPressで投稿した記事をCakephpでうまく表示したい
    * 案１：CakePHPでwp_postsテーブルにアクセスする（WordPressのタグがうまく表示されない）
    * 案２：CakePHPでWordPressのURLにアクセスしてWordPressのデザインをメインサイトに合わせる
* WordPressのREST APIから記事をとってきてはどうか？
    * [Posts | REST API Handbook | WordPress Developer Resources](https://developer.wordpress.org/rest-api/reference/posts/#retrieve-a-post)
* 他のサイトはどうやっているのか（WordPressだったらすべてWordPressで作っているのか⇒Yes）
* ヘッドレスCMS
    * 管理画面がないCMS
        * APIでコンテンツを管理する
    * [Headless CMS - Qiita](https://qiita.com/reflet/items/55665a79940a96252c68)

### CakePHPでアクセス中のページのメニューの背景色を変えたい

* [CakePHP3で現在ページのURL・パスを取得する | EasyRamble](https://easyramble.com/current-url-with-cakephp.html)
    * 取ってきたURLに、CSSのClassをつけてあげる
* [php - How to get complete current url for Cakephp - Stack Overflow](https://stackoverflow.com/questions/6836990/how-to-get-complete-current-url-for-cakephp)
* [Class Cake\Routing\Router | CakePHP 3.6](https://api.cakephp.org/3.6/class-Cake.Routing.Router.html#_url)
* [html5 - How do I add active class in menu link using CakePHP? - Stack Overflow](https://stackoverflow.com/questions/23693204/how-do-i-add-active-class-in-menu-link-using-cakephp)

### レイヤードアーキテクチャとValue Object

* レイヤードアーキテクチャに手を出したが、Value Objectがいっぱい出てきてつらいという声がでてきた。
    * どこまでValue Objectにしたらいいか？
    * たくさんValue Objectが出てきても辛くならない方法はないか？
* 参考にしているもの
    * [DDDパターンを活用した Laravelアプリケーション開発](https://speakerdeck.com/shin1x1/201703-ddd-with-laravel)
* 最近見た（使えそう？）
    * [ytake/valueobjects](https://github.com/ytake/valueobjects)
* priceは普通はint型にしそうなのを`Price`クラスを作る
    * `Price`には、マイナスが入らないようにする
    * 税込み価格を計算するメソッドをもたせる
* DBのテーブルのカラムの数だけValue Objectができる
    * 基本的に1カラム、1オブジェクト
    * 使い回せないのか？
* 振る舞いのないValue Objectも作られている
* どうやってエンジニアに設計思想を伝えていくか
    * 熱意
    * 必要性の理解をしっかりしてもらう方が良い
    * フラットで良いならDDDじゃない方が良くないか？
    * DDDが生きるものは2%らしい

### みなさんどうやってPHPでプログラムを作っているのか

* エディタとキーボードを使って作っていますw
* 普段触っているUnityでも
    * 設計してから
    * 振る舞いを作って
    * 仕様を作ってから作る
* 設計はする
* 既存のCakePHPで作られたプログラムを改修するなら
    * CakePHPにはPHPUnitが組み込まれているのでテストコードを書く
        * [テスト - 3.6](https://book.cakephp.org/3.0/ja/development/testing.html)
        * コントローラやモデルをテストする

### 再帰関数でディレクトリのファイルを消そうとしたら、XAMPP内のファイルが全て消えてしまった😱OMG

* ソースコードも消えてしまったので、なぜ消えたかも分からない。
* ディレクトリを登っていって全部消し去ってしまった。
* rsyncで常にバックアップを取ったらどうか
    * バックアップは大事
    * [Windows Subsystem for Linux - Wikipedia](https://ja.wikipedia.org/wiki/Windows_Subsystem_for_Linux)
    * [WSL（Windows Subsystem for Linux）を使ってみた - Qiita](https://qiita.com/Brutus/items/f26af71d3cc6f50d1640)
    * WSLはWindows Proじゃなくても使える
* memcachdは再起動したら内容が消える

### 単体テスト PHPUnit

* 単体テスト書いてますか？
    * 2名 やってる
    * 2名 ちょっと
* レガシーコード = 単体テストがないコード
* すべてすべてに書く必要ないかなと
    * 効果が高いところが分からない
* 必ず書くようにするというのも手

### ライブラリを呼んでいる

* [goodby/csv](https://github.com/goodby/csv)のコードを読み込んでいる
* `\\` ってなんですか？
    * SPL例外をuseせずに使うと `catch (\Exception $e)` のようになる。
    * SPL例外: http://php.net/manual/ja/spl.exceptions.php

### 大規模な開発で人がいっぱいるとき

* どこからが大規模か
* どうやって進めていったらいいか？
* どうやったら、会ったこと無い開発者にちゃんと設計とか書き方が伝わるか？

## 45歳から初めるPHPプログラミング
### `#yyphp-quiz` No.2: 月間カレンダーの表を作ろう

```php
<?php
/**
 * 月間カレンダーの表を生成して返す
 * @param int $first その月の1日の曜日番号。日=0、月=1、火=2、水=3、木=4、金=5、土=6
 * @param int $days その月の日数。30、31、28もしくは29
 * @return array 下記のような月間カレンダーを配列で返す
 * - 週ごとにひとつの配列にする。
 * - 週の配列は日曜日から土曜日の7要素が必ずある。
 * - 週の配列の中身は日付。
 * - 週の配列の中で中で前月や次月の日付になる日は0で埋める。
 * 例:
 * $calendar = getCalendarTable(1, 30);
 * この場合、$calendarの値は次のようになる:
 * [
 *   [ 0,  1,  2,  3,  4,  5,  6],
 *   [ 7,  8,  9, 10, 11, 12, 13],
 *   [14, 15, 16, 17, 18, 19, 20],
 *   [21, 22, 23, 24, 25, 26, 27],
 *   [28, 29, 30,  0,  0,  0,  0],
 * ]
 */
function getCalendarTable(int $first, int $days): array
{
    // todo: 日付関係の関数、クラス、ライブラリを使わずに実装してみて
}

// テストコード
assert(
    getCalendarTable(0, 28) === [
        [ 1,  2,  3,  4,  5,  6,  7],
        [ 8,  9, 10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19, 20, 21],
        [22, 23, 24, 25, 26, 27, 28],
    ],
    '1日が日曜日で28日間ある月'
);
assert(
    getCalendarTable(0, 31) === [
        [ 1,  2,  3,  4,  5,  6,  7],
        [ 8,  9, 10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19, 20, 21],
        [22, 23, 24, 25, 26, 27, 28],
        [29, 30, 31,  0,  0,  0,  0],
    ],
    '1日が日曜日で31日間ある月'
);
assert(
    getCalendarTable(1, 30) === [
        [ 0,  1,  2,  3,  4,  5,  6],
        [ 7,  8,  9, 10, 11, 12, 13],
        [14, 15, 16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25, 26, 27],
        [28, 29, 30,  0,  0,  0,  0],
    ],
    '1日が月曜日で30日間ある月'
);
assert(
    getCalendarTable(4, 30) === [
        [ 0,  0,  0,  0,  1,  2,  3],
        [ 4,  5,  6,  7,  8,  9, 10],
        [11, 12, 13, 14, 15, 16, 17],
        [18, 19, 20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29, 30,  0],
    ],
    '1日が木曜日で30日間ある月'
);
assert(
    getCalendarTable(4, 31) === [
        [ 0,  0,  0,  0,  1,  2,  3],
        [ 4,  5,  6,  7,  8,  9, 10],
        [11, 12, 13, 14, 15, 16, 17],
        [18, 19, 20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29, 30, 31],
    ],
    '1日が木曜日で31日間ある月'
);
assert(
    getCalendarTable(5, 31) === [
        [ 0,  0,  0,  0,  0,  1,  2],
        [ 3,  4,  5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14, 15, 16],
        [17, 18, 19, 20, 21, 22, 23],
        [24, 25, 26, 27, 28, 29, 30],
        [31,  0,  0,  0,  0,  0,  0],
    ],
    '1日が金曜日で31日ある月'
);
```

### `#yyphp-quiz` No.3: 多次元配列から要素を一撃で取り出す関数を実装して


```php
<?php
/**
 * 多次元配列から任意の要素を取り出す
 * @param string $query クエリー
 * @param array $data クエリーにかける対象の配列
 * @return mixed 要素が見つからなかったらNULLを返す
 */
function arrayQuery(string $query, array $data)
{
    // eval等のメタ言語機能を使用しないで実装して
}

$data = [
    'a' => ['b' => ['c' => 'd']],
    'efg' => ['hij', 'lmn', 'opq'],
    's' => 't',
    'u'
];

assert(arrayQuery('.', $data) === $data);
assert(arrayQuery('...', $data) === $data);
assert(arrayQuery('.a', $data) === ['b' => ['c' => 'd']]);
assert(arrayQuery('.a.b', $data) === ['c' => 'd']);
assert(arrayQuery('.a.b.c', $data) === 'd');
assert(arrayQuery('.a.b.c.', $data) === 'd');
assert(arrayQuery('.efg.0', $data) === 'hij');
assert(arrayQuery('.0', $data) === 'u');
assert(arrayQuery('.x', $data) === null);
assert(arrayQuery('.x.x.x', $data) === null);
```

## YYPHPは毎週やってます

PHPについてワイワイ話したい方は、[YYPHPのイベント情報](https://yyphp.connpass.com/)をチェックしてみて下さい。

以上、YYPHPのレポートでした。次回もワイワイやっていきたいと思います！ では、また来週！