LoginSignup
2
2

More than 1 year has passed since last update.

[Laravel]macroについて知る

Last updated at Posted at 2021-11-23

背景

  • Laravelプロジェクトアサイン当初、VSCodeの拡張機能PHP Intelephenseにより、知らないメソッドはよくジャンプしてvender/laravel配下を読みに行くことが多かった
  • そんな中、以下コードを見た
$query->whereLike('code', $this->input)
  • このwhereLikeというメソッドを見て

「LaravelはLIKE検索もできるwhere句もあるんだ~」

とのんきにPHP Intelephenseでジャンプしようと思ったらできない。

おや?

ジャンプできない理由は謎だったが、ドキュメントを確認すると、whereLikeなんてメソッドはない…

  • よくよく調べるとプロジェクト内にこんなソースコードを発見
Builder::macro('whereLike',function...

「なんじゃこりゃ…?」

  • macroというワードとそれ以降に書いてある(特に第2引数)コードの意味がよく分からんかったので、深く理解しようというのが今回の背景

目的

環境

  • Laravel 8.x

内容

前提

  • 今回はmacroを知ったきっかけであるBuilderで理解進める

  • Collectionにもmacroがあるらしい。
    • こっちも利用頻度高いと思うので、取り上げる

概要

  • まずは1次情報からということで公式ドキュメントで

8.x macro

で検索すると、8件のヒット(21/11現在)

  • そもそも「マクロとは?」の答えは以下

関連する複数の操作や手順、命令などを一つにまとめ、必要に応じて呼び出すことができるようにする機能

※参考↓
https://e-words.jp/w/マクロ.html

  • なるほど、意味を知ってしまえばそんな難しくない
    • 「一つにまとめて、必要に応じて使う」といいう点からサービスコンテナの延長の概念だなと感じた

使い方-Builder

公式ドキュメントに沿って行く

ソースコード

マクロの登録

ExampleServiceProbiver.php
use Illuminate\\Support\\Facades\\Response;
use Illuminate\\Support\\ServiceProvider;
use Laravel\\Scout\\Builder;

/**
 * 全アプリケーションサービスの初期起動処理
 *
 * @return void
 */
public function boot()
{
    Builder::macro('count', function () {
        return $this->engine->getTotalCount(
            $this->engine()->search($this)
        );
    });
}
  • 記述するのは場所はどこでもいいと思うが、一般的には公式と同じようにサービスプロバイダ―に記述することが多そう(推測)
    • そうすれば、いつでも使いたい時に作ったメソッドを使用できるから
  • Builderの場合はLaravel\\Scout\\Builder内にあるmacroメソッドを使う。引数は
    • 第2引数:メソッド名
    • 第3引数:メソッドによる処理内容

マクロの使用

ExampleController.php
use App\\Models\\Order;

Order::search('Star Trek')->count();

  • あとはどこでも使うだけ。
    • すごく楽。

使い方-Collection

こちらも公式ドキュメントに沿って行く

ソースコード

マクロの登録

ExampleServiceProbiver.php
use Illuminate\\Support\\Collection;
use Illuminate\\Support\\Str;

Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});
  • 95%くらいbuilderと同じ
    • Biulderと異なるのはmacroメソッド本体の設定場所くらい
  • 記述するのは場所はどこでもよさそう。(理由は上述の通り)
  • Collectionの場合はIlluminate\\Support\\Collection内にあるmacroメソッドを使う。引数はBuilderと同じ以下の通り
    • 第2引数:メソッド名
    • 第3引数:メソッドによる処理内容
  • 今回はtoUpperというメソッドをCollectionに対して使うことで、Collection内の文字列を大文字にするマクロを作った模様。

マクロの使用

  • 使用もBuilderと同じ。
ExampleController.php
$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

dump($upper)

// ↓出力結果
// ['FIRST', 'SECOND']
  • 無事、小文字→大文字に変換されております。

補足

  • 他にはレスポンスに対してマクロを登録したり、

  • そのレスポンスをサービスプロバイダで依存注入(DI)してマクロ登録したり

結構いろんなところで使える。

所見

ただの感想

  • サービスプロバイダに記述するあたりなどみて

独自の処理をメソッドにギュッと凝縮していつでも使える感じにした「お手軽サービスコンテナ」だな

という直感的な感想です笑

  • そもそも現状でもかゆいところに手が届くくらい、組み込み関数は充実している感があるが、

「使いたいやつないなら、自分で作って」

と言わんばかりにサービス精神あふれるLaravelはしゅごい。

引っかかる点

  • ただ、Builderについてはスコープ、Collectionについてはアクセサがある
  • 個人的主観としては、以下の使い分けのイメージ
    • 汎用度が相対的に高い(=スコープが相対的に広い):マクロ
      • 扱うリソースが多岐にわたる(User, Order, Post…etc)
    • 汎用度が相対的に低い(=スコープが相対的に狭い):スコープアクセサ
      • 扱うリソースが限られている(User内だけとか)
  • ただ、そうなると、

マクロとサービスコンテナとの使い分けは?

とかの疑問がわくので、ここら辺は実務で使っていく中で言語化していこうと思います。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2