
九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、皆さんもよくご存知のとおりですが、Larave
だけでなくPHP
自体もアップデートを繰り返していて、常に新しい機能が加わったりしています。
そして、来たる「2020.11.26」に次期バージョンのPHP 8
がリリースされることになってます(私がPHPを使い始めたのがバージョン4でしたので、何か説明のできない興奮があります)
PHP 8
の目玉機能としては、やはり「JITコンパイラ」による超高速化ですが、プログラミング的にもいくつか「おっ!」と思うものがありました。
そこで
今回は、その気になるPHP 8
の新機能をLaravel
で使ってみることにしました。
ぜひ皆さんのお役に立てましたら嬉しいです
「プレステも、もう
5
になるんですね」
開発環境: Laravel 8.x
目次 [非表示]
関数に渡すパラメータの順番が自由になる
これまでのPHP
では、関数に渡す引数(パラメータ)は必ず順番を守る必要がありました。
例えば、Laravel
のヘルパー関数Str::padLeft()
を見てみましょう。
まずは、定義はこうなっています。
// Laravel から引用
public static function padLeft($value, $length, $pad = ' ')
{
return str_pad($value, $length, $pad, STR_PAD_LEFT);
}
この引数の順番に注目してみると、もし関数を使いたい場合は、
- $value
- $lenth
- $pad
の順番でセットしないといけません。
例えば、こんなカンジです。
$value = '123';
$length = 10;
$pad = '0';
//
引数の順番は決まってます
$text = Str::padLeft($value, $length, $pad);
しかし、PHP 8
からは次のように書くことができます。
$text = Str::padLeft(
value: '123',
length: 10,
pad: '0'
);
そのため、順番は関係なくなり、以下のように書いても同じ結果になります。
$text = Str::padLeft(
pad: '0', //
順番は気にしなくてOK
length: 10, //
ここも
value: '123' //
ここも
);
まだ実際の開発で使っていないですが、可読性は上がると思いますし、IDE
が自動的にこの形式で自動入力してくれるなら、こっちの書き方もアリかなと思ってます(ただし、引数が少ない場合はなしの方がいいですね)
switch()が進化したようなmatch()関数
PHP 8
には新しい条件分岐match()
が追加されます。
これをLaravel
のモデルで使ってみます。
以下は、商品の値段で分岐をする例です。
$item = Item::find(1);
$text = match($item->price) {
500 => 'ワンコインです',
1000, 2000, 3000 => '切りのいい値段です',
default => '好評発売中'
};
$text
の中身としては以下のとおりになります。
- 値段が 500 の場合: 「ワンコインです」
- 値段が 1000, 2000, 3000 の場合: 「切りのいい値段です」
- それ以外: 「好評発売中」
チェーンメソッドでNullなら途中で終了する機能
チェーンメソッドというのは、以下のように->
でつないだコードのことです。
$users = User::get();
$user_names = $users->filter(function($user) {
return $user->id > 3;
})
->pluck('name')
->map(function($user_name) {
return $user_name .'様';
});
この書き方はコードがすっきりするのでとても便利ですが、一点「うーん」な点がありました。
それが、「途中でnull
が返ってきても実行が止まらず、結果エラーが出る」ということです。
これが、PHP 8
では、?->
を使うことで処理が途中で止まる(それ以降のコードはちゃんと実行されます)ようになりました。
例を見てみましょう。
public function index(Request $request)
{
$user_name = $request->user()?->name;
}
この場合、user()
がNULL
の場合、それ以降は無視されることになります。
もしこれまでの->
だけの以下の場合、ログインしている場合は問題なく動きますが、そうでない場合は、Attempt to read property "name" on null
というエラーが発生します。
//
ここは、ログインしてないとエラーになります
$user_name = $request->user()->name;
そのため、これまでは三項演算子を使うかif文
で分岐する必要がありました。
$user = $request->user();
$user_name = !is_null($user) ? $user->name : null;
※ ちなみに、PHP 7
以降なら「Null Coalescing Operator」でもOKです。
$user_name = $request->user()->name ?? null;
ちょっと可読性的に大丈夫かな?と思う気もするんですが、コードが長くなるならとても便利な気がしています。
クラスのメンバ変数を省略して書ける
PHP 8
ではクラス内で使うメンバ変数の定義を省略して書くことができるようになります。
ということで、Laravel
のMailable
を使って見てみましょう
例えば、これまでのPHP
でメンバ変数を使う場合、よく以下のようにコンストラクタの中でデータをセットしていました。
class Contacted extends Mailable
{
// 省略
private User $user; //
メンバ変数を定義
public function __construct(User $user)
{
$this->user = $user; //
メンバ変数へデータを格納
}
しかし、これからはコンストラクタだけで完結できるようになります。
class Contacted extends Mailable
{
// 省略
//
メンバ変数の定義が不要
public function __construct(private User $user) //
private や public をつけるだけ
{
//
メンバ変数への格納も不要!
}
つまり、以下のようにとてもスッキリした形でコードを書くことができるようになります。
class Contacted extends Mailable
{
// 省略
public function __construct(private User $user)
{
}
これまで正直なところ、ココはめんどうだと感じていた部分なので、個人的にすごく嬉しい機能です
try ~ catch の変数を省略できるようになった
これまで try ~ catchを使う場合は以下のように、catch()
の中には変数を指定する必要がありました。
try {
echo $undefined; // わざとエラーを発生させる
} catch (\Exception $exception) {
// エラーの場合
}
これが、PHP 8からは変数名の指定は不要になりました。
try {
echo $undefined;
} catch (\Exception) { //
変数が不要になりました
// エラーの場合
}
そのため、エラー(例外)の中身を知る必要はないときには重宝するんじゃないでしょうか。
型を複数指定できる機能
PHP 7.4
から以下のような「型付きプロパティ」が使えるようになりました。
class Item
{
public int $id;
public string $name;
// 省略
そして、PHP 8
からは、複数の型を宣言できるようになります。
Laravel
のMailable
で例を見てみましょう。
<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class Contacted extends Mailable
{
use Queueable, SerializesModels;
private string|User $user; //
型を2つ指定してます
public function __construct(string|User $user) //
型を2つ指定してます
{
$this->user = $user;
}
public function build()
{
$user_name = $this->user->name ?? $this->user;
return $this->to('admin@example.com')
->view('emails.contacted')
->with([
'user_name' => $user_name
]);
}
}
この中では、変数$user
は「Userモデルか、文字列ならOK」ということになっています。
ただ、その昔Java
を書くときは型宣言は当たり前でしたが、PHP
やPython
がメイン言語になってからはあまり使わなくなってしまい、正直型の宣言はめんどうだな、なんて思うんですが皆さんはいかがでしょうか
インスタンスでも「::class」がつかえるようになった
これまで、インスタンスからクラス名を取得するにはget_class()
を実行する必要がありました。
$user = User::find(1);
dd(get_class($user));
しかし、PHP 8
からはシンプルに::class
を使えるようになりました。
$user = User::find(1);
dump($user::class);
地味な変更ですが、可読性も上がっていいと思います
参考記事
今回、PHP 8
の新機能で参考にさせていただいたページは以下の2つです。
この記事には書いていない記事もありますので、興味のある方はぜひご覧になってください。
What’s new in PHP 8:
https://stitcher.io/blog/new-in-php-8
【PHP8.0】PHP8.0の新機能
https://qiita.com/rana_kualu/items/fe7998fbe773544d5d25
ホントに、こういうきっちりとした記事を書いてくれる方には感謝しかありません。ありがとうございます!
正直、私も彼らのようになりたかったですが、あきらかに向いてないので、今後も「ゆるーく楽しい」記事でやっていきたいと思います
おわりに
ということで、今回はPHP 8
の新機能をLaravel
の中で使ってみました。
ちなみに今回紹介した中で個人的に好きなランキングをつけるとすると、次のとおりです。
- クラスのメンバ変数を省略して書ける
- try ~ catch の変数を省略できるようになった
- チェーンメソッドでNullなら途中で終了する機能
どうやら私は「できるだけなんでも省略したい」と考えているようです(笑)
まぁ、プログラマは「楽しようとする人」は適正があると言われているので、「ヨシ!」とすることにします。
ではでは〜
「現場猫ちゃん、かわいいですね」