普段Symfony書いているPHPerがLaravel入門してみた

 

お久しぶりです!年末年始にゆる〜くLaravelを触ってみました。
普段はSymfonyを書いているので、比較してみました。

間違っていることや補足コメントくれると嬉しいです!!

https://github.com/kin29/example-laravel-app

migrationファイル

  • Laravel: SQLではない。
  • Symfony: SQL。

コマンド

  • Laravel: php artisan ~
  • Symfony: php bin/console ~
    個人的にartisanっていう単語がなかなか覚えられない🤯

ルーティング

  • Laravel: routes/以下にルーティング定義をする。これによりControllerを作成しなくともルーティング設定ができる。

ref: https://readouble.com/laravel/8.x/ja/routing.html

  • Symfony: Controllerに直接ルーティング定義ができる。yamlによるルーティング定義もできる。

ref: https://symfony.com/doc/current/routing.html

PHPStormのコード補完

フォームリクエスト

  • Laravel: FormRequestを作る(Illuminate\Foundation\Http\FormRequestをextends)
$ php artisan make:request StorePostRequest

実際のdiff: https://github.com/kin29/example-laravel-app/commit/b50df00ccd299284c9207be38c03ebe7ac38914e

  • Symfony: FormTypeを作る(Symfony\Component\Form\AbstractTypeをextends)
$ bin/console make:form

データと移入

  • Laravel: seederというアプリケーション実行に必要なデータを投入できる。factoryでも大量のデータ投入ができる
$ php artisan make:seeder UserSeeder
$ php artisan make:factory PostFactory

ORM

  • Laravel: Eloquentモデル(Eloquent ORM)
$ php artisan make:model Flight //model作成
  • Symfony: Entity(Doctrine ORM)
$ bin/console make:entity //Entity作成

 

ぺチコン2021レポート〜1日目〜

 

今年もぺチコンに参加させてもらいました!(オンライン)
オンラインなので👶がいる私には参加しやすかったです〜
YouTubeでアーカイブも残ってるのもありがたいです!何度も見直しますね(きっと)

今回初めてDiscordも活用させていただきました。リアルタイムでいろんな達人の方々が補足してくれるのでめちゃくちゃ勉強になりました!!!
また、会社のスポンサーツアーにもちょこっと出させてもらいました〜🙌

\ ぺチコン2021のタイムテーブルはこちら /
https://fortee.jp/phpcon-2021/timetable

コロナと落ち着いたら、またオフラインで参加したいです🥺
\ 過去のぺチコンレポートをどうぞ /
https://kin29.info/tag/phpcon/

気になったトークのメモ

🟡PHPにおけるコーディング規約と自動整形

コーディング規約の重要性を再確認させてもらいました。

php-cs-fixerとphp_codesnifferの違いについての理解は曖昧だったので、Discord上での解説もあり超納得でした!

php-cs-fixer → 書式しか見ないが全てを自動修正できる

php_codesniffer → 構造も見るのでeraly exitとかも違反にできるが、全ては自動修正できないより厳しくできる

🟡独自フレームワークPHPアプリケーションの改善戦略

auto_prepend_fileっていう設定ができるの初知りでした!auto_prepend_fileについて別記事書いたので良かったらみてください。

PHPのauto-prepend-fileを設定して、symfony/var-dumperを使ってみる

🟡PHPer が知るべき MySQL クエリチューニング

SQL苦手系PHPerなのでめちゃくちゃ勉強になりました。EXPLAINの見方はよく知らなかったので、わかりやすい説明で大変理解できました!

会社の技術ブログで実際に手を動かしてEXPLAIN使って見たレポを書いたので良かったら見てください。
https://tech.quartetcom.co.jp/2021/10/07/phpcon-2021-report/

🟡PHPで学ぶオブジェクト指向プログラミング入門

いい声なので動画貼っておきます。https://youtu.be/gdCE-UGqeSM?t=18952
変数名、関数名だけでも抽象化は表現できる!
複雑さ=条件分岐 → わかりやすくする=条件分岐を減らす
異なるものを同じように扱う事=ポリモーフィズム
JankenGameのコードはdisplayLangResolverを追加したい!って思ってしまいました。
Smalltalkっていう言語のOOP流派もある(←普段使わない方)
ポリモーフィズムは3つある。サブタイプポリモーフィズム/パラメトリックポリモーフィズム/アドホックポリモーフィズム
いつも通り、成瀬さんの説明はめちゃくちゃわかりやすいです。DDDの本読みました!
「OOPって何?なんでいいの?」って聞かれたらおすすめしたいトークです。

🟡ドメインをモデリングして PHP コードに落とし込む

新原さんも声もいい☺️https://youtu.be/gdCE-UGqeSM?t=23609
例題のドメインがワクチン接種なのが現代的!でコードも見れてわかりやすかった!

モデリング→複数の視点(俯瞰でみるかその中の要素でみるか)、手法で徐々に形にしていく
– ユースケース図 …システム化の範囲、ユーザが見えてくる
– 用語集の作成(ちょっと面倒) …項目は用語/英語表記/内容。英語表記があることでコード上での表記ゆれを防ぐ。解釈のずれがなくなるのでおすすめとのこと。
– 概念モデル図 …クラス図。多重度がわかる。用語を適当にばーっと並べて線で結ぶことからはじめて、徐々にブラッシュアップしていく感じ。
UML図ちゃんとは書いたことない。。。💦

ドメインモデル実装
– 1ドメイン = 1クラス
– POPO(Plain Old PHP Odject)、プレーンなPHPで作成
– クラス名やメソッド名にドメインモデル用語を使う
– setterを作らない方が良い …ドメインロジックによってプロパティ値を変更する

日本語クラスは作ったことないのでやってみたい!PHPStormはバリバリ対応してるらしい。

モデリングしてコードを実装することで理解が深まる、コードを書いてて気づくことが多いのはめちゃわかる!
→モデリングの一環としてコードを書くことと、結構良い!テストで実行検証できるのも良い🙆‍♀️

ステータスの状態遷移図もあると便利。
Enumは型としても使える、日本語も使える!
まずは、用語集→ユースケース図が良さそう、用語集でドメイン知識の認識を合わせることが重要💡
図やドキュメントのメンテは? → Wikiレベルで良い、とりあえずあれば嬉しい。

何度も見返したいトークでした!!!🙇‍♂️

🟡【IMO】コードレビューって難しいよね

IMO=in my option 私の意見では
わたしもレビューされる方が好きです。
レビューしてもらうとその分学びが増える感じが好きです。
pullpanda使ったことないので、使って見たいと思いました!
https://pullpanda.com/

さいごに

二日目レポートも書きます!(きっと)

PHPのauto-prepend-fileを設定して、symfony/var-dumperを使ってみる

 

ぺチコン2021を見ていて、初めて知ったビルドインのオプションを知りました!
\ auto-prepend-fileです! /
今回はそれを使って開発を便利にしていきたいと思いますー🙋‍♂️

教えてくださったスライドはこちらです、ありがとうございます!
https://speakerdeck.com/tzmfreedom/original-framework-php-kaizen?slide=22

簡単にできる事を説明すると、独自関数などを定義したファイルをスクリプト実行前に読み込ませることができます!
それにより、デバック関数を独自に作成して、それをスクリプト内に仕込んでデバックするみたいなことができて便利みたいです。

auto-prepend-fileとは?

https://www.php.net/manual/ja/ini.core.php#ini.auto-prepend-file

auto_prepend_file string
メインファイルの前に自動的に付加されるファイルの名前を指定します。 このファイルは、require 関数のコール時と同様に読み込まれます。 このため、include_path が使用されます。
特別な値 none を指定すると、ファイルを前に追加する機能は無効となります。

逆に、auto_append_fileというのもあるみたいです。

🚨注意

auto-prepend-fileauto_append_fileもexit();が使われるようなスクリプトでは、使用できないとのことです。私はここの中身みたいなーって時は、var_dump($hoge);exit();としちゃってたので注意しないとでした。そういうときはdd($hoge);を使うといいみたいですね。

symfony/var-dumperが使えるようにauto-prepend-fileに追加してみる

Symfonyの公式にも掲載されていました!
https://symfony.com/doc/current/components/var_dumper.html#the-dump-function

In order to have the dump() function always available when running any PHP code, you can install it globally on your computer:

  1. Run composer global require symfony/var-dumper;
  2. Add auto_prepend_file = ${HOME}/.composer/vendor/autoload.php to your php.ini file;
  3. From time to time, run composer global update symfony/var-dumper to have the latest bug fixes.

 

1.composer global require symfony/var-dumper;

PHP8.0.3でやっていきます。

$ php --version
PHP 8.0.3 (cli) (built: May 27 2021 13:40:53) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies
    with Xdebug v3.0.3, Copyright (c) 2002-2021, by Derick Rethans


$ composer global require symfony/var-dumper;
Changed current directory to /Users/shigaayano/.composer
Using version ^5.3 for symfony/var-dumper
./composer.json has been created
Running composer update symfony/var-dumper
Loading composer repositories with package information
Updating dependencies
Lock file operations: 3 installs, 0 updates, 0 removals
  - Locking symfony/polyfill-mbstring (v1.23.1)
  - Locking symfony/polyfill-php80 (v1.23.1)
  - Locking symfony/var-dumper (v5.3.8)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 3 updates, 31 removals
  - Removing symfony/stopwatch (v5.1.2)
  - Removing symfony/service-contracts (v1.1.5)
  - Removing symfony/process (v5.1.2)
  - Removing symfony/polyfill-php73 (v1.11.0)
...

2.php.iniにauto_prepend_file = ${HOME}/.composer/vendor/autoload.phpを追加

php -r "echo phpinfo();" | grep "php.ini"でphp.iniの場所を確認して、最終行とかに追記します。

ちゃんと適用されてるか心配だったので、確認して見ます。
設定されてるみたいです。

php -r "echo phpinfo();" | grep "auto_prepend_file"
auto_prepend_file => /Users/xxx/.composer/vendor/autoload.php => /Users/xxx/.composer/vendor/autoload.php

3.実際に使ってみる

まず、dd($hoge);を使って見ます。
今回、コントローラ内でdd($form)でFormの中身を見たかったのですが、dump後にexitされるためdumpが出力された後はレスポンスも表示されません。

次に、dump($hoge);を使って見ます。
exitされないため、レスポンスがいつも通り表示されてSymfony Profiler > Debugからdumpを確認できます。

 

プロジェクト内のコードを変更せず使えますし、便利なので今後も開発で是非使っていこうと思います🙌!

参考:
https://zenn.dev/kitar/articles/790933413a3090116be8

Constructor property promotionを使ってみる!(PHP8から使えるやつ)

 

お久しぶりです…そろそろ更新頻度上げていきたいと思っております🙇‍♂️

今回はPHP8から使えるようになった、Constructor property promotionを使って見たので、差分と使って見た感想をまとめてみます。

Constructor property promotionとは?

https://www.php.net/releases/8.0/en.php#constructor-property-promotion

👆のPHP7→PHP8の差分を見ての通り、簡潔に言うとコンストラクタの引数にすべてを詰め込めます。コンストラクタの引数にプロパティ定義、初期値もかけちゃいます。

実際にDj-Kin29で適用した差分

詳細: https://github.com/kin29/dj-kin29/pull/34/files

before

class DefaultController extends AbstractController
{
    private AuthHandler $authHandler;
    private GetTopTrackService $getTopTrackService;
    private CreatePlaylistService $createPlaylistService;

    public function __construct(
        AuthHandler $authHandler,
        GetTopTrackService $getTopTrackService,
        CreatePlaylistService $createPlaylistService
    ) {
        $this->authHandler = $authHandler;
        $this->getTopTrackService = $getTopTrackService;
        $this->createPlaylistService = $createPlaylistService;
    }

after

class DefaultController extends AbstractController
{
    public function __construct(
        private AuthHandler $authHandler,
        private GetTopTrackService $getTopTrackService,
        private CreatePlaylistService $createPlaylistService
    ) {
    }

このコード見てて気づきましたが、AbstractControllerをextendsするのやめたいなーと思いました。

使って見た感想

👆のコードを見ての通り、6行もコードが減りました!!!スッキリさせたい私的には大変いい感じです。
慣れるまでは違和感がありましたが、実際に使ってみるとなんだかんだすぐ慣れそうな気がしました。
TypeScriptのコンストラクタの書き方と似てます 💡

dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicudata.67.dylibのエラーでPHP7.4が突然使えなくなった話



ある日、突然MacでPHP7.4.9が使えなくなりました😭😭😭
結構ハマりましたが、お戻りになってきてくれました🙌

結論

icu4cが69.1にあがってしまっていた。
→ brewで67.1を入れ直して、シンボリックリンクを貼ればok

エラー内容

$ php --version
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicudata.67.dylib
Referenced from: /Users/user_xxx/.phpenv/versions/7.4.9/bin/php
Reason: image not found
Abort trap: 6

とりあえず/usr/local/opt/icu4c/lib/libicudata.67.dylibが本当にないのか、
/usr/local/opt/icu4c/lib/以下を確認。
→現在のシンボリックが69.1しかないので、67のシンボリックリンクを作りたい。。。🤤

$ ll /usr/local/opt/icu4c/lib/
total 137024
drwxr-xr-x 28 user_xxx staff 896 4 8 09:10 .
drwxr-xr-x 12 user_xxx staff 384 5 27 17:27 ..
drwxr-xr-x 6 user_xxx staff 192 4 8 09:10 icu
-r--r--r-- 1 user_xxx staff 28672096 5 27 16:15 libicudata.69.1.dylib
lrwxr-xr-x 1 user_xxx staff 21 4 8 09:10 libicudata.69.dylib -> libicudata.69.1.dylib
-r--r--r-- 1 user_xxx staff 28665232 4 8 09:10 libicudata.a
lrwxr-xr-x 1 user_xxx staff 21 4 8 09:10 libicudata.dylib -> libicudata.69.1.dylib
-rw-r--r-- 1 user_xxx staff 2726984 5 27 16:15 libicui18n.69.1.dylib
lrwxr-xr-x 1 user_xxx staff 21 4 8 09:10 libicui18n.69.dylib -> libicui18n.69.1.dylib
...

1.brewでicu4cの67をいれる。

brew tap-newとかbrew extractを使うやり方をしらなくてハマりました。

$ brew tap-new kin29/taps #「kin29」の部分はなんでもokです
Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/kin29/homebrew-taps/.git/
[main (root-commit) 58a4f09] Create kin29/taps tap
3 files changed, 88 insertions(+)
create mode 100644 .github/workflows/publish.yml
create mode 100644 .github/workflows/tests.yml
create mode 100644 README.md
==> Created kin29/taps
/usr/local/Homebrew/Library/Taps/kin29/homebrew-taps

When a pull request making changes to a formula (or formulae) becomes green
(all checks passed), then you can publish the built bottles.
To do so, label your PR as `pr-pull` and the workflow will be triggered.
$ brew extract icu4c kin29/taps --version 67
==> Searching repository history
==> Writing formula for icu4c from revision e2c833d to:
/usr/local/Homebrew/Library/Taps/kin29/homebrew-taps/Formula/icu4c@67.rb
$ brew install kin29/taps/icu4c@67
==> Installing icu4c@67 from kin29/taps
==> Downloading https://github.com/unicode-org/icu/commit/715d254a02b0b22681cb6f861b0921ae668fa7d6.patch?full_index=1
Already downloaded: /Users/user_xxx/Library/Caches/Homebrew/downloads/0dd175e315a7eee5f9fb42af4e03d2130e3a3aa130db4d2b32a58b1c88d87251--715d254a02b0b22681cb6f861b0921ae668fa7d6.patch
==> Downloading https://github.com/unicode-org/icu/releases/download/release-67-1/icu4c-67_1-src.tgz
Already downloaded: /Users/user_xxx/Library/Caches/Homebrew/downloads/5652b331b5400231692d0879d41522870a20598d8771342b622d543c2ed99ca0--icu4c-67_1-src.tgz
==> Patching
==> Applying 715d254a02b0b22681cb6f861b0921ae668fa7d6.patch
patching file source/common/uassert.h
==> ./configure --prefix=/usr/local/Cellar/icu4c@67/67.1 --disable-samples --disable-tests --enable-static --with-library-bits=64
==> make
==> make install
==> Caveats
icu4c@67 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c@67 first in your PATH, run:
echo 'export PATH="/usr/local/opt/icu4c@67/bin:$PATH"' >> /Users/user_xxx/.bash_profile
echo 'export PATH="/usr/local/opt/icu4c@67/sbin:$PATH"' >> /Users/user_xxx/.bash_profile

For compilers to find icu4c@67 you may need to set:
export LDFLAGS="-L/usr/local/opt/icu4c@67/lib"
export CPPFLAGS="-I/usr/local/opt/icu4c@67/include"

For pkg-config to find icu4c@67 you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/icu4c@67/lib/pkgconfig"

==> Summary
🍺 /usr/local/Cellar/icu4c@67/67.1: 258 files, 71.8MB, built in 4 minutes 47 seconds

icu4c@67がインストールされたことを確認!

$ ll /usr/local/Cellar/ | grep icu
drwxr-xr-x 4 user_xxx staff 128 5 27 16:15 icu4c
drwxr-xr-x 3 user_xxx admin 96 5 29 18:04 icu4c@67
$ ll /usr/local/opt/ | grep icu4c
lrwxr-xr-x 1 user_xxx admin 20 5 27 16:15 icu4c -> ../Cellar/icu4c/69.1
lrwxr-xr-x 1 user_xxx admin 23 5 29 18:09 icu4c@67 -> ../Cellar/icu4c@67/67.1 #今回追加分

2.シンボリックリンクを貼る⚠️

ln -s [パス] [リンク名]です。私はパスとリンク名の指定が逆と勘違いしていて、ハマりました💦
(間違えたらunlink [リンク名]で削除できます。)

$ cd /usr/local/opt/icu4c/lib/
$ ln -s ../../../icu4c@67.1/67.1/lib/libicuio.67.1.dylib libicuio.67.dylib
$ ln -s ../../../icu4c@67.1/67.1/lib/libicui18n.67.1.dylib libicui18n.67.dylib
$ ln -s ../../../icu4c@67.1/67.1/lib/libicuuc.67.1.dylib libicuuc.67.dylib
$ ln -s ../../../icu4c@67.1/67.1/lib/libicudata.67.1.dylib libicudata.67.dylib
$ ln -s ../../../icu4c@67.1/67.1/lib/libicutest.67.1.dylib libicutest.67.dylib
$ ln -s ../../../icu4c@67/67.1/lib/libicutu.67.1.dylib libicutu.67.dylib

シンボリックリンクが貼れていることを確認します。

$ ll /usr/local/opt/icu4c/lib/ | grep 67.dy
lrwxr-xr-x 1 user_xxx staff 50 5 29 22:11 libicudata.67.dylib -> ../../../icu4c@67.1/67.1/lib/libicudata.67.1.dylib
lrwxr-xr-x 1 user_xxx staff 50 5 29 22:09 libicui18n.67.dylib -> ../../../icu4c@67.1/67.1/lib/libicui18n.67.1.dylib
lrwxr-xr-x 1 user_xxx staff 48 5 29 22:08 libicuio.67.dylib -> ../../../icu4c@67.1/67.1/lib/libicuio.67.1.dylib
lrwxr-xr-x 1 user_xxx staff 50 5 29 22:09 libicutest.67.dylib -> ../../../icu4c@67.1/67.1/lib/libicutest.67.1.dylib
lrwxr-xr-x 1 user_xxx staff 46 5 29 22:09 libicutu.67.dylib -> ../../../icu4c@67/67.1/lib/libicutu.67.1.dylib
lrwxr-xr-x 1 user_xxx staff 48 5 29 22:09 libicuuc.67.dylib -> ../../../icu4c@67.1/67.1/lib/libicuuc.67.1.dylib

 

PHP7.4お戻りになってくれたー😭😭😭ありがとう🎊

php --version
PHP 7.4.9 (cli) (built: Dec 26 2020 23:21:06) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans

 

助けてくれてありがとうございました🙇‍♂️
ref: https://www.tohuandkonsome.site/entry/2021/05/21/173612


「fn」というワードはPHP7.4から予約語に!(→アロー関数)

 

「fn」というワードはPHP7.4から予約語になったというのを知るに至った経緯として、$ symfony serveでローカルサーバを立てて

$ symfony serve
                                                                                                                        
 [OK] Web server listening                                                                                              
      The Web server is using PHP FPM 7.3.11                                                                            
      https://127.0.0.1:8000                                         


[Web Server ] Jan 18 18:48:55 |INFO   | PHP    listening path="/usr/sbin/php-fpm" php="7.3.11" port=61746                                              

 

ブラウザで表示確認をすると、以下の500エラーがでました😱

(phpenvでいろんなPHPバージョンを使ってます。)

HTTP 500 Internal Server Error
syntax error, unexpected 'fn' (T_STRING), expecting :: (T_PAAMAYIM_NEKUDOTAYIM)
ParseError
in /Users/xxx/my-project/vendor/laminas/laminas-code/src/Generator/ClassGenerator.php (line 480)
470    /**
471     * @param string $implementedInterface
472     * @return bool
473     */
474    public function hasImplementedInterface($implementedInterface)
475    {
476        $interfaceType = TypeGenerator::fromTypeString($implementedInterface);
477
478        return (bool) array_filter(
479            array_map([TypeGenerator::class, 'fromTypeString'], $this->implementedInterfaces),
480            static fn (TypeGenerator $interface): bool => $interfaceType->equals($interface)
481        );
482    }

 

よーく確認してみると、
symfony php --versionphp --versionのバージョンが違う」
ことに気づきました💦

$ symfony php --version
PHP 7.3.11 (cli) (built: Jun  5 2020 23:50:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies

$ php --version
PHP 7.4.9 (cli) (built: Dec 26 2020 23:21:06) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
    with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans

 

そこで、$ symfony serve でもPHP 7.4.9で動くように設定します。

参照:https://symfony.com/doc/current/setup/symfony_server.html#different-php-settings-per-project

$ cd my-project/

$ echo 7.4.9 > .php-version

$ symfony php --version # PHP 7.3.11 -> 7.4.9に変更完了
PHP 7.4.9 (cli) (built: Dec 26 2020 23:21:06) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
    with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans


$ symfony serve # PHP 7.4.9でサーバ立てることに成功

                                                                                                                        
 [OK] Web server listening                                                                                              
      The Web server is using PHP FPM 7.4.9                                                                             
      https://127.0.0.1:8000                                                                                     

[Web Server ] Jan 18 18:50:59 |INFO   | PHP    listening path="/Users/xxx/.phpenv/versions/7.4.9/sbin/php-fpm" php="7.4.9" port=62271

お! PHP7.4.9でサーバ立てるようになったみたいです!
と同時にsyntax error, unexpected 'fn' (T_STRING), expecting :: (T_PAAMAYIM_NEKUDOTAYIM)のエラーもなくなりました🎉

めでたし、めでたし👏

 

syntax error, unexpected ‘fn’ (T_STRING), expecting :: (T_PAAMAYIM_NEKUDOTAYIM)の解明

参照:https://www.php.net/manual/ja/tokens.php

 

Google翻訳先生に訳してもらうと、

構文エラー、予期しない '楽しい'(t_string)、予期する::( t_pamaim_nikoodatim)

おそらく fn = 楽しい って訳してくれてます💦

ググっていくと、「fn」はPHP7.4から予約語になったらしいです!

というかアロー関数(無名関数)が使えるようになり、その予約語としてfnを使います。

(風の噂でアロー関数が使えるようになったというのは知っていたのですが書き方まで知らなかったです😅)

アロー関数は fn (argument_list) => expr という形で記述します。

よって、PHP 7.4まではアロー関数がなかったために以下の該当箇所を、「::」を使うスコープ定義演算子 (::)のことではないですか?と教えてくれたのかもしれません。

static fn (TypeGenerator $interface): bool => $interfaceType->equals($interface)

 

CIのComposerバージョンが2になる(composer self-updateさせてた)せいでテストがコケてた話



今回の目標

CIをphp7.4に対応したい
(Herokuでは既に7.4.7だったので)

 

.circleci/config.ymlのimageをcircleci/php:7.4-node-browsers
にしたところ、composer-plugin-apiに関するエラーが発生しました。

Composer2でcomposer installを実行したのに、composer.lockでcomposer-plugin-apiは1系って書いてあるから互換性ないやないかーみたいなこと言ってる、おそらく。Composer2はcomposer-plugin-api2系使えってこと?

($ composer install -n –prefer-dist以下)

$ php --version
PHP 7.4.9 (cli) (built: Dec 26 2020 23:21:06) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies
with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans

$ composer --version
Composer version 2.0.8 2020-12-03 17:20:38

$ composer install -n --prefer-dist
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Your lock file does not contain a compatible set of packages. Please run composer update.

Problem 1
- ocramius/package-versions is locked to version 1.4.2 and an update of this package was not requested.
- ocramius/package-versions 1.4.2 requires composer-plugin-api ^1.0.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
Problem 2
- symfony/flex is locked to version v1.5.3 and an update of this package was not requested.
- symfony/flex v1.5.3 requires composer-plugin-api ^1.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
Problem 3
- ocramius/package-versions 1.4.2 requires composer-plugin-api ^1.0.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
- ocramius/proxy-manager 2.1.1 requires ocramius/package-versions ^1.1.1 -> satisfiable by ocramius/package-versions[1.4.2].
- ocramius/proxy-manager is locked to version 2.1.1 and an update of this package was not requested.

ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.
If you can not upgrade PHP you can require composer/package-versions-deprecated to resolve this with PHP 7.0+.

You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2.

 

そもそもCircleCIを導入しようとしてましたが、すでにTravis導入済みだったのでCircleCI導入はやめました。すみません💦(ただエラー内容はだいたい一緒だったと思います。)

当時設定していた.travis.ymlのPHPバージョンが7.1~7.3だったので7.4にしようと思います。

ローカルではcomposer1.8系を使っていたのでエラーはみられませんでしたが、
.travis.yamlではbefore_install: composer self-updateにしてたのでcomposer2系でcomposer installを実行しようとしていました。

エラー内容:

xxx/yyy n.n.n requires composer-plugin-api ^1.0.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.

composer.jsonのrequireにcomposer-plugin-api: "^1.0 || ^2.0"を追記で↑のエラーは回避できました!!!

参考:https://github.com/composer/composer/issues/8726

 

[おまけ]composer validate追記したらエラーでた

実際にでてたエラーログです。

$ composer validate
./composer.json is valid for simple usage with composer but has
strict errors that make it unable to be published as a package:
See https://getcomposer.org/doc/04-schema.md for details on the schema
name : The property name is required
description : The property description is required
symfony/debug-pack, symfony/maker-bundle, symfony/profiler-pack, symfony/test-pack are required both in require and require-dev, this can lead to unexpected behavior
require.symfony/debug-pack : unbound version constraints (*) should be avoided
require.symfony/orm-pack : unbound version constraints (*) should be avoided
require.symfony/profiler-pack : unbound version constraints (*) should be avoided
require.symfony/serializer-pack : unbound version constraints (*) should be avoided
require.symfony/test-pack : unbound version constraints (*) should be avoided
require.symfony/twig-pack : unbound version constraints (*) should be avoided

 

1) エラー内容:
xxx/yyy are required both in require and require-dev, this can lead to unexpected behavior

→ requireとrequire-devに同じpackageが書いてあるのがダメみたいなのでrequire-devから重複削除しました。

 

2) エラー内容:
name : The property name is required
description : The property description is required

→ composer.jsonにnameとdescriptionが必要とのことなので、追加しました。

 

3) エラー内容:
require.xxx/yyy: unbound version constraints (*) should be avoided

→ xxx/yyy: "*"はやめるべきとのことなのでバージョン指定をしました。

 

すべて(今回は3つ)のエラーを解消させ、

composer updateでcomposer.lockを更新して再度composer validateするvalidになりました〜🙌

$ composer validate
./composer.json is valid

 

メモ

  • 今回対応での差分

https://github.com/kin29/dj-kin29/pull/10/files

 

 

  • 後々考えてみたら、ローカル環境のcomposerバージョンを2にして、composer updateでcomposer.lockを更新してcommitで良かったのかも😅

composer-plugin-api:^2.0に対応してないpackageだったら、composer.jsonのrequireにcomposer-plugin-api: "^1.0 || ^2.0"追記が必要なのかも。

 



phpenvでPHP7.4系を導入した(configure optionをちょっと深ぼる)

 

実行環境は、macOS Catalina 10.15.7 です。

macOS Big Sur にアップデートしたらどうなるんだろうか….🤔迷ってます

 

(過去記事でphpenvでよく使うコマンドまとめてます。)

phpenvでいろんなPHPバージョンを操る

 

しばらくコードを書いておらず、PHPのバージョンが7.3.7だったので7.4系にバージョンあげますー😅

$ php --version
PHP 7.3.7 (cli) (built: Oct  6 2020 15:27:59) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.7, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.7, Copyright (c) 1999-2018, by Zend Technologies
    with Xdebug v2.7.2, Copyright (c) 2002-2019, by Derick Rethans

$ phpenv versionsに7.4系が入ってなかったので、

$ phpenv update

からの

$ phpenv install 7.4.9

を実行したら、

-----------------------------------------
configure: error: Please reinstall the BZip2 distribution
-----------------------------------------

といわれたので、
bzip2をreinstallしてパスも通しましたが解決しませんでした。

ググって以下でinstallしてみました。

$ PHP_RPATHS="/usr/local/opt/bzip2/lib" PHP_BUILD_CONFIGURE_OPTS="--with-bz2=/usr/local/opt/bzip2" phpenv install 7.4.9

そしたら、

-----------------------------------------
configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>
-----------------------------------------

って言われました。どんどん芋釣で問題出てくる、phpenvあるある。
念のため、iconvもreinstallとパスを通して、以下コマンドで再チャレンジ!

 

!!!解決コマンド!!!!

$ PHP_RPATHS="$(brew --prefix bzip2)" PHP_BUILD_CONFIGURE_OPTS="--with-bz2=$(brew --prefix bzip2) --with-iconv=$(brew --prefix libiconv)"  phpenv install 7.4.9

PHP_RPATHSの指定はなくても良かったかもです🙇‍♂️

\ 🎉7.4系installできたー!🎉 /

[Success]: Built 7.4.9 successfully.
$ phpenv versions
  system
  5.6.1
  7.0.31
  7.1.3
  7.1.30
  7.2.20
  7.3.0
  7.3.7
* 7.4.9 (set by /Users/xxxx/xxxx/.ruby-version)

 

そもそもconfigure optionってなに?

解決できたコマンドは以下ですが、分解して各々の環境変数が何しているか見ていきます。

$ PHP_RPATHS="$(brew --prefix bzip2)" PHP_BUILD_CONFIGURE_OPTS="--with-bz2=$(brew --prefix bzip2) --with-iconv=$(brew --prefix libiconv)"  phpenv install 7.4.9

・PHP_RPATHS

PHP_RPATHS="$(brew --prefix bzip2)" 

そもそもRPATHってなに!?

https://stackoverrun.com/ja/q/2196869 より

-rpath=dir
Add a directory to the runtime library search path. ….

訳)実行中ライブラリの検索パスにディレクトリを追加します。

\ runtime path=rpathってこと?  runtimer? /

 

wikipediaさん(https://en.wikipedia.org/wiki/Rpath)にも同じようなことが書いてある👀

configure optionにも--disable-rpathというオプションがあって、以下のような記述がされていたので、なんか解釈あってそう。

–disable-rpath

実行時にライブラリの検索パスを追加できないようにします。

 

 

・PHP_BUILD_CONFIGURE_OPTS

PHP_BUILD_CONFIGURE_OPTS="--with-bz2=$(brew --prefix bzip2) --with-iconv=$(brew --prefix libiconv)"

そのままですが、ビルド時のconfigure optionを指定できるみたいです。

--with-bz2 …bzip2を有効にし、bzip2の場所を指定をします。

--with-iconv …iconvの場所を指定できます。

 

 

参考:

https://qiita.com/kunit/items/c30147f99a48ebb159d5

https://qiita.com/hnw/items/c227d58528c147de15dd

https://www.ritolab.com/entry/211#aj_5_5

 

まとめ

PHP書いてるけど、こういうmake系は全然わかりません😭まだまだです💦

rpath=replace pathなのかと思ってた。

 

Symfony installerを削除して、Symfony CLI(symfonyコマンド)を入れて使ってみる!

 

お久しぶりです☺️

Symfonyを使っているにもかかわらず、symfonyコマンド使ってないなー
と今更感じたので、この記事を書きます。

 

はじめに

私の場合、Symfony2,3で使っていたSymfony installerを削除する必要がありました。
symfonyというコマンド名でバッテングしてるので、Symfony4からdepricatedになったSymfony installerを削除→Symfony CLIをインストールという手順をしました。
(※ composerを使えば良い話なんですが、symfonyコマンド使ってみたかったので)

Symfony installerが入っている状態

$ symfony

Symfony Installer (1.5.11)
==========================

This is the official installer to start new projects based on the
Symfony full-stack framework.
...

 

ここで、symfony new でプロジェクトを作成しようとすると、
Symfony InstallerはSymfony4から互換性(compatible)なくなったよーって言われました。
また、Symfony4から代わりにcomposer create-project symfony/skeleton [my_project_name]を使ってねーって言ってます。

$ symfony new my_project
PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in phar:///usr/local/bin/symfony/vendor/guzzlehttp/ringphp/src/Client/CurlFactory.php on line 363
PHP Stack trace:

...

[RuntimeException]
The Symfony Installer is not compatible with Symfony 4.x or newer versions.
Run this other command to install Symfony using Composer instead:
composer create-project symfony/skeleton my_project

一瞬、Symfony4からsymfonyコマンドなくなった?って思いましたが、Symfony4.4のBestPracticeでしっかり使っているので、少し混乱しました😅
参考:

 

SymfonyInstallerを削除して、SymfonyCLIをinstallする。

あまり良くない消し方な気がしますが、以下の方法でSymfonyInstallerを消しました。

$ ls -al ~/.symfony
total 0
drwxr-xr-x 3 watashi staff 96 4 4 20:51 .
drwxr-xr-x+ 118 watashi staff 3776 4 20 18:45 ..
drwxr-xr-x 3 watashi staff 96 4 21 09:23 bin
$ ls -al /usr/local/bin/symfony
-rwxr-xr-x 1 watashi staff 246243 7 4 2019 /usr/local/bin/symfony
$ rm -rf ~/.symfony
$ rm -rf /usr/local/bin/symfony
$ symfony -V
-bash: /usr/local/bin/symfony: No such file or directory

そして、SymfonyCLIをインストールします🚀

$ curl -sS https://get.symfony.com/cli/installer | bash
Symfony CLI installer

Environment check
[*] cURL is installed
[*] Gzip is installed
[*] Git is installed
[*] You architecture (amd64) is supported

Download
Finding the latest version (platform: "darwin_amd64")...
Downloading version 4.14.1 (https://github.com/symfony/cli/releases/download/v4.14.1/symfony_darwin_amd64.gz)...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 636 100 636 0 0 1311 0 --:--:-- --:--:-- --:--:-- 1311
100 7909k 100 7909k 0 0 878k 0 0:00:09 0:00:09 --:--:-- 1443k
Uncompress binary...
Making the binary executable...
Installing the binary into your home directory...
The binary was saved to: /Users/watashi/.symfony/bin/symfony

The Symfony CLI v4.14.1 was installed successfully!

Use it as a local file:
/Users/watashi/.symfony/bin/symfony

Or add the following line to your shell configuration file:
export PATH="$HOME/.symfony/bin:$PATH"

Or install it globally on your system:
mv /Users/watashi/.symfony/bin/symfony /usr/local/bin/symfony

Then start a new shell and run 'symfony'

$ mv /Users/watashi/.symfony/bin/symfony /usr/local/bin/symfony

うぉー!Symfony CLIが入りましたー!!! 🎉

$ symfony
Symfony CLI version v4.14.1 (c) 2017-2020 Symfony SAS
Symfony CLI helps developers manage projects, from local code to remote infrastructure

These are common commands used in various situations:

Work on a project locally

new Create a new Symfony project
serve Run a local web server
server:stop Stop the local web server
security:check Check security issues in project dependencies
composer Runs Composer without memory limit
console Runs the Symfony Console (bin/console) for current project
php, pecl, pear, php-fpm, php-cgi, php-config, phpdbg, phpize Runs the named binary using the configured PHP version

Manage a project on Cloud

login Log in with your SymfonyConnect account
init Initialize a new project using templates
link Link current git repository to a SymfonyCloud project
projects List active projects
envs List environments
env:create Create an environment
tunnel:open Open SSH tunnels to the app's services
ssh Open an SSH connection to the app container
deploy Deploy an environment
domains List domains
vars List variables
user:add Add a user to the project

Show all commands with symfony help,
Get help for a specific command with symfony help COMMAND.

 

Symfony CLIを使ってみる

プロジェクトを作成してみます。
今回は、webアプリケーションを作ってみます。
composer create-project symfony/website-skeleton [project_name]git initをしていることがわかります。

$ symfony new symfony_command_test_web_app --full
* Creating a new Symfony project with Composer
  (running /usr/local/bin/composer create-project symfony/website-skeleton /Users/watashi/symfony_command_test_web_app)

* Setting up the project under Git version control
  (running git init /Users/watashi/symfony_command_test_web_app)


 [OK] Your project is now ready in /Users/watashi/symfony_command_test_web_app


 

symfony server:startを使ってローカルサーバを立てて、ブラウザを確認してみると…いい感じにSymfony5.0.8のwelcomeページが表示されましたー!🍺

$ symfony server:start

 [WARNING] run "symfony server:ca:install" first if you want to run the web server with TLS support, or use
 "--no-tls" to avoid this warning


Apr 29 11:13:01 |DEBUG| PHP    Reloading PHP versions
Apr 29 11:13:01 |DEBUG| PHP    Using PHP version 7.3.11 (from default version in $PATH)
Apr 29 11:13:01 |INFO | PHP    listening path="/usr/sbin/php-fpm" php="7.3.11" port=55287
Apr 29 11:13:01 |DEBUG| PHP    started
Apr 29 11:13:01 |INFO | PHP    'user' directive is ignored when FPM is not running as root
Apr 29 11:13:01 |INFO | PHP    'group' directive is ignored when FPM is not running as root
Apr 29 11:13:01 |INFO | PHP    fpm is running, pid 3483
Apr 29 11:13:01 |INFO | PHP    ready to handle connections

 [OK] Web server listening
      The Web server is using PHP FPM 7.3.11

      http://127.0.0.1:8000

 

symfony server:ca:installをしたら、TLSで確認できるらしいので、入れてみる🔐
を「https://」になったー!ブラウザもちゃんとみれる👀

$  symfony server:start
Apr 29 11:29:01 |DEBUG| PHP    Reloading PHP versions
Apr 29 11:29:02 |DEBUG| PHP    Using PHP version 7.3.11 (from default version in $PATH)
Apr 29 11:29:02 |INFO | PHP    listening path="/usr/sbin/php-fpm" php="7.3.11" port=55368
Apr 29 11:29:02 |DEBUG| PHP    started
Apr 29 11:29:02 |INFO | PHP    'user' directive is ignored when FPM is not running as root
Apr 29 11:29:02 |INFO | PHP    'group' directive is ignored when FPM is not running as root
Apr 29 11:29:02 |INFO | PHP    fpm is running, pid 12395
Apr 29 11:29:02 |INFO | PHP    ready to handle connections

 [OK] Web server listening
      The Web server is using PHP FPM 7.3.11

      https://127.0.0.1:8000

 

さいごに

今までは、composerでプロジェクトを作って、php -S 127.0.0.1:8880 -t public/でブラウザ確認をしていたので、symfonyコマンドの方が短いので使って楽したほうがいいなーと思いました。

 

SpotifyAPIを使いプレイリストを簡単に作成してくれるツールDJ-Kin29リニューアルしました!

以前に作成した、アーティスト名を入力するだけでいい感じのSpotifyプレイリストを作成してくれるツールDJ-Kin29を改良しました!

是非、使ってみてください!!!
https://dj-kin29.herokuapp.com/

今回の改良にあたって、認可フローを見直しました。
前回の記事でまとめたので、よかったら参考にしてください。
SpotifyWebAPIの認可フローをまとめてみた

Githubも公開しまーす。
コントリビュート待ってます🍺
https://github.com/kin29/dj-kin29

Before

  • プレーンなPHP
  • Spotify認可のタイミングがフォームを入力後というおかしなタイミング
入力フォーム (index.php)
↓
↓ 作成 (旧:action先=create.php)
↓
(spotifyの認可画面)
redirect_uri: https://dj-kin29.herokuapp.com/create.php
→ 拒否されたら、 https://{redirect_uri}?error=access_denied
↓
↓ 許可されたら、
↓
プレイリスト作成成功
プレイリスト作成完了画面 (complete.php)
or
プレイリスト作成失敗
プレイリスト作成失敗画面 (failed.php)
↓
↓ more create / retry
↓
入力フォーム (index.php)に戻る

After

  • Symfony4を使用
  • Spotify認可のタイミングを、フォーム入力前にした。
1. / (クエリパラメータにcode=xxxを含まない)
- 「Authorization to Spotify」ボタンで、Spotifyとの連携(認可)をスタートする。(リンク先:/auth_spotify)
※ボタン押さずとも連携スタートさせたかったけど、spotify側の認可URLにリダイレクトさせてたらTwitterカードPreviewでエラーになったので、やめました😓

2. /auth_spotify
- Spotifyの認可がスタートする
  - 認可を許可したことがある場合:リダイレクトURL (/code=xxx)に遷移する。
  - 許可していない場合:Spotifyログイン画面 or 認可しますか画面に遷移する。
    - 認可の許可をした場合:/code=xxxにリダイレクトする。
    - 認可を拒否した場合:/error=xxx(エラーページ)にリダイレクトする。(→Re-Tryボタンで再チャレンジ可能)

3. /code=xxx
- フォーム画面。post先は、/create。

4. /create
- SpotifyWebAPIを使って、プレイリストを作成する。
  - 作成成功した場合;完了画面
  - 作成失敗した場合;失敗画面(→Re-Tryボタンで再チャレンジ可能)
- 「More create」ボタンでさらにプレイリスト作成可能(2に戻る)

さいごに

  • Tweetボタン設置しました^^
  • GAを充実させたくて、GTMと格闘しました。
  • 引き続きherokuを使っているので、初動に時間がかかります、、、🙇‍♂️
  • アーティスト名検索では、該当するアーティストの一番上だけを取得し、それに紐付く曲を取得するので、アーティスト名が被っていると期待したプレイリストができないことがあります、、、🙇‍♂️
    (日本のガールズバンドHumpBackのつもりで入力したところ、まだサブサクは解禁してないようで、違うバンドの曲が入っていました。)