カテゴリーアーカイブ PHP

著者:杉浦

__callによる未定義メソッドの呼び出し

 PHPには予約関数マジックメソッドがあり、__call()はその一つです。
PHP: マジックメソッド – Manual

__call() は、 アクセス不能メソッドをオブジェクトのコンテキストで実行したときに起動します。

 要は、未定義のメソッドを呼び出した時は代わりに__call()が呼ばれますよ、ということです。__call()は次の様に定義されます。

public mixed __call ( string $name , array $arguments )

$nameには呼ばれた際に使われたメソッド名、$argumentsには呼ばれた際に使われた引数が入ってきます。__call()を利用する事でな様々なことが出来ます。例えばエラーメッセージです。あるクラスが存在しないメソッドに向かってアクセスされようとした時、エラーメッセージを返すには次の様なコードが使えます。

public function __call($method, $parameters)
{
    sprintf('Method %s::%s does not exist.', static::class, $method);
}

 また、よく行うであろう動作をあらかじめ定義し、その動作の省略に割り当てるという使い方もあります。次の例はあるモデルにクエリビルダを繋ぎ、新規クエリビルダ呼び出しを省略する手法です。この手法を用いることで、クエリビルダと同等の働きができ、なおかつDBから引き出されたphp上における振る舞いのメソッドも多様に持つ、という風に見えるモデルを簡単に記述できます。

class Model
{
    public function __call($method, $parameters)
    {
        return $this->newQuery()->$method(...$parameters);
    }
    //省略
}

 クエリビルダへつなげる手法では更にクエリビルダの持つメソッドへチェーンしていくことが出来ます。これにより一見存在しないメソッドが存在するかのように振る舞います。この存在しないように見えるが使用されるメソッドが無秩序に増えた場合、コードを追うことが非常に大変な作業になります。これはgrepや参照呼出しを一発で当てられなくなるためです。何が呼び出されているかをいちいち確認する必要があることが面倒なのです。
 PHPDocを書くことでこの問題を解決できます。PHPDocの@methodはどの様なメソッドがあるかを示す文言で、多くのIDEはこれを追ってくれます。次の様に記述した場合、IDEはselectメソッド、whereメソッドが存在するかの様にModelクラスを扱ってくれます。

/**
 * @method QueryBuilder select(QueryBuilder $query)
 * @method QueryBuilder where(QueryBuilder $query)
 */
class Model
{
    public function __call($method, $parameters)
    {
        return $this->newQuery()->$method(...$parameters);
    }
    //省略
}
  • この記事いいね! (0)
村上 著者:村上

【備忘録】Firebase Cloud Messagingでのプッシュ通知の送信について

実は似たような記事を以前にも投稿しましたが、今回はメッセージを送付する際のHTTP構文についてです。
というのも、送信メッセージやタイトルを変えるだけならまだしも、パラメータを変更したり、追加・削除するときに毎回調べていたので、いい加減自分のためにまとめようと思ったからです。

そのため、この記事は私的重要ポイントのみをまとめてあります。
ご了承ください。

ちなみに、以前の記事はこちら。

【PHP】FireBase Cloud Messagingを利用したプッシュ通知をPHPから送る方法 – 株式会社シーポイントラボ|浜松のシステム開発会社
https://cpoint-lab.co.jp/article/201810/【php】fireBase-cloud-messagingを利用したプッシュ通知をphpから送る/

 

さて、まず Firebase の公式サイトのHTTP プロトコルについてのページがこちら。

Firebase Cloud Messaging の HTTP プロトコル|Firebase
https://firebase.google.com/docs/cloud-messaging/http-server-ref?authuser=0

このページですら毎回検索して探すので、こうしてまとめたかったというのが主ですね。

次に、各項目について。
送信先を指定するパラメータ to について、その具体的な指定値です。

指定値 対象
/topics/all 全端末に送信
/topics/android Android端末にのみ送信
/topics/ios iOS端末にのみ送信
/topics/[トピック名] 特定のトピックに登録されている端末にのみ送信
[デバイストークン] 特定の端末

こちらに関しては、特に説明不要かと思います。
送信先を指定したい場合、こちらの to の値を変更しますが、例が載っていなかったので、よく使いそうなもののみを抜粋しました。

次は dry_run というパラメータです。
こちらは未指定の場合のデフォルトは false になっています。
このパラメータを true にすると、実際にプッシュ通知を送らずに、レスポンス結果を取得することができます。
送信のテスト時に使うパラメータですね。

あとは、badge という、ホーム画面のアイコンにバッヂを追加するためのパラメータです。
こちらにバッヂの値を指定すると、プッシュ通知を受信した時にバッヂが追加されます。
なお、0 を指定すると、バッヂは削除されます。

よく使うのはこのあたりでしょうか。
他にも、Androidのみの設定で icon というパラメータでプッシュ用のアイコン画像を指定できます。
これがないと、アイコンが白い四角形になってしまい非常に味気ないので、Android アプリに通知を送る際は指定したほうが良さそうです。

 

以上、FCM でメッセージを送付する際のHTTP構文についてでした。
なお、レスポンスデータについては、上で挙げた Firebase の公式サイトのHTTP プロトコルについてのページの下の方に載っているので、こちらも参考にしてください。

  • この記事いいね! (0)
著者:杉浦

laravelのエラー画面

 laravelのエラー画面は単なるエラーメッセージのみならず、詳細にエラーが起こるまでの実行過程と実行環境を示してくれます。この記事ではこのエラー画面の説明をします。
 エラーを起こした画面が次です。左上のエラーメッセージと右側のエラーが起きたコードが目につきます。どういうエラーかもわからないニッチなエラーが出たときは左上の赤丸で囲ってある部分の出番です。ここをクリックするとgoogleなどでエラーメッセージをググってくれます。

 手作業でエラーの内容を調べる際には次の画像の赤丸で囲ってある部分、Application framesとAll framesを使い分けるとよいです。通常laravelプロジェクトのフォルダ構成で/vendor以下の内容を改変する事はありません。All frameは/vedor以下も含んだスタックトレース、Application framesは/vendor以下を含まないスタックトレースです。Application framesで異常な値になった部分を大雑把に見つけ出し、All frameでより詳細に絞りこむ方法はよくとります。

 値を見つけ、追っていくと先に述べました。エラー画面で値の中身を追うには下の画像の赤丸部です。次の関数に値を渡すコードの行部分と引数の中身を見ることが出来ます。

 GET、POSTなどの通信に用いた値も右下部に格納されています。あまり見せるべき情報でないので隠してありますが、更に下の方にはサーバの情報も記述されてあります。

  • この記事いいね! (0)
著者:杉浦

万能クラスや数珠つなぎの継承を作らずにコードの共有を行うトレイト

PHP: トレイト – Manual

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。 トレイトとクラスを組み合わせた構文は複雑さを軽減させてくれ、 多重継承や Mixin に関連するありがちな問題を回避することもできます。

 トレイトはtraitと書き、次の様にclassと同じ書き方をし、useで読み込みます。関数などの名前が衝突した際にはinsteadofでどちらを使うか決定する、asで別名として扱う対応を行います。

<?php
trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
    public function moreBigTalk() {
        echo 'X';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
    $this->moreBigTalk();
}

 いまのところ使ったことはないですが可視性の変更も可能です。
 トレイトの特に強力で扱いやすい部分が名前の扱いです。トレイトなしでコードを再利用する場合、共通のクラスを継承する、ユーティリティクラスを作る、別ファイルにしてincludeかrequireしてグローバル領域に配置するといった手法が考えられます。それらの手法の複雑さの原因になりうるという危うい点を、継承を行わず、グローバルを汚染せず、区分をtraitの名前につけてコードの再利用を可能にすることでトレイトは回避しています。
 IDEは画像の様に内部に何が入っているのかアイコンで表示してくれるのでその点でもありがたいです。

  • この記事いいね! (0)
著者:杉浦

phpのロギングライブラリ規定PSR-3

 webアプリケーションにおいてはそのアプリケーション上で起きた動作のログを取る事が望まれます。これは障害や攻撃が起きた際、それがいつどこで起きたのか知るため、また障害や攻撃が起きていると知るための強い助けになります。単に思うがままにログを取るのみでは可読性が悪く肝心な情報が抜けているログを生む確率が大きいです。PSR-3はphpで用いられるロギングライブラリの規格を統一する事でログの可読性、生産性を上げています。
PSR-3: Logger Interface – PHP-FIG
【PHP】PSR-3 Logger Interface(ロガーインタフェース)
 PSR-3はRFC 5424のメッセージプロトコルに沿ったログレベルとそれに合わせたロギングライブラリの実装を規定しています。RFC 5424はログメッセージをIPネットワーク上で転送するための標準規格であるsyslogについて説明しています。
 ロギングライブラリを使う側として特に重要になるのが3. Psr\Log\LoggerInterfaceです。この中にはログレベルの規定と使用例が記述されており、これに従うことによって程よい粒度で他の多くwebアプリケーションのログから大きく外れないログを作れます。PSR-3においてログの文面までは規定されていないのでそこはまた別のことを学ぶ必要があります。

  • この記事いいね! (0)
著者:杉浦

変数の値で変数名を呼び出す可変変数

PHP: 可変変数 – Manual
 phpには可変変数という機能がついています。これは変数名が可変の変数という意味の言葉です。具体的に何をするかというと、次の画像の様な動作です。
 
 可変変数によって式の評価結果などを用いて変数名を動的に変更できます。他言語でも似たようなことを実現する機能はままありますが、ここまで自由な振る舞いはちょっと珍しい印象です。可変変数を雑に扱うとIDEで追いかけることが難しかったり、不意に値が現れたりすることで混乱のもとになります。逆に混乱を抑えられる場合、有効です。例えばコーディング規約を作成し、規約に従う方法です。
 多くのフレームワークや大規模なライブラリなどには可変変数の様なを利用して実現している機能があります。例えばLaravelのEloquentモデルは特定の関数名ならば特定の種類の動作をするという機能(クエリビルダ、アクセサ、ミューテタ)を備えており、これはこの可変変数を用いることで簡単に実現できます。フレームワークに備わった可変変数を用いた機能は漫然と使っていてはなかなか気づきません。公式ドキュメント、リファレンス、といった説明書に書かれた可変名に関する説明を読むことが重要になります。

  • この記事いいね! (0)
著者:杉浦

チートシートとしてのresources/lang/ja/validation.php

 laravelには多彩なバリデーションルールが用意されています。記述も次の様に|区切りで羅列されたルールを持つ配列と同じキーを持つ配列を二つ使うのみで簡単です。

$rules = [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
];
//Request $request Requestはlaravel内でarrayをラッピングした高級クラス
$validatedData = $request->validate($rules);
//もしくは単に配列で
$input = [
    'title' => 'hoge'
    'body' => 'hogehoge'
];
Validator::make($input, $rules);

 ここまで簡単な記述だと適したバリデーションルールをなるべく使いたいものです。しかしrequiredやmaxの様に頻繁に使うもののみならず全てのバリデーションルールを覚えようとした場合、それは一苦労です。バリデーションルール一覧の日本語訳は丁寧に正確にしてあるのですが詳細すぎるのか長大すぎるのかあまりやりたいことではありません。
 laravelには言語設定というものがあります。これはresources/lang/以下に配置するもので、設定されたlocalに合った言語設定が適宜読み込まれます。この言語設定にはテンプレートが出回っており日本語もご多分に漏れません。次のリンクはバリデーションに用いる日本語版言語設定ファイルへのリンクです。
validation.php言語ファイル 5.6 Laravel
 このファイルにはバリデーションのエラーメッセージが含まれています。例えば次です。

'digits_between' => ':attributeは:min桁から:max桁の間で指定してください。',

 これと同様にルール名=>日本語のエラーメッセージの配列の形で様々なルールとその対応が羅列されています。エラーメッセージはユーザに伝えるためのメッセージだけあってルールの内容を簡潔に教えてくれます。このためvalidation.php言語ファイル 5.6 Laravelでざっくりバリデーションルールを読んで詳細をバリデーション 5.6 Laravelで確認するというやり方がバリデーションの処理をコーディングする際に有効です。

  • この記事いいね! (0)
著者:杉浦

Laravelのデバッグ用関数dd()

 dd()はdump and dieの略です。何をやるかというとLaravel用の便利なvar_dump();exit;です。
 dd()の使い方はシンプル。Laravelフレームワークのphpコード内で次の様に記述するのみです。

dd(変数名A,変数名B,..)

 これを実行した場合、次の図の様に渡した変数を読みやすい形で表示するhtmlコードが返されます。
 
 特に便利なのは図にあるquery builderの様な巨大な構造体を読みたい時です。通常のvar_dump()で表示しようとした場合、とても読めたものではありません。var_dumpでは常に全展開の為、長いkeyと深いネストを持ってしまった場合、表示すら難しいです。
 dd()の定義はvendor/laravel/framework/src/Illuminate/Support/helpers.phpにあります。

    /**
     * Dump the passed variables and end the script.
     *
     * @param  mixed  $args
     * @return void
     */
    function dd(...$args)
    {
        foreach ($args as $x) {
            (new Dumper)->dump($x);
        }

        die(1);
    }

 dieはexitと同じなので読み飛ばしです。Dumperの中を追うとvendor/laravel/framework/src/Illuminate/Support/Debug/Dumper.phpを読むことになります。

use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;

class Dumper
{
    /**
     * Dump a value with elegance.
     *
     * @param  mixed  $value
     * @return void
     */
    public function dump($value)
    {
        if (class_exists(CliDumper::class)) {
            $dumper = in_array(PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper : new HtmlDumper;

            $dumper->dump((new VarCloner)->cloneVar($value));
        } else {
            var_dump($value);
        }
    }
}

 ここでSymfonyのvar_dumperに渡してLaravel自身のコードは終わります。Symfonyのvar_dumperの中は満足いくeleganceな表示を行うためにいくらか大きな処理をしています。CliDumper.phpだけで600行程、htmlDumperは900行程で記事に書き起こす程読み込む気力はありませんでした。

  • この記事いいね! (0)
著者:杉浦

ダミーデータ作成ライブラリFakerの紹介

 FakerはPHP上で扱うダミーデータ作成ライブラリです。この記事で扱うのはPHPのFakerですがいくつかの他言語でもFakerという名のダミーデータ作成ライブラリは存在します。

JavaScript faker
Python Faker
Ruby Faker
Perl Data-Faker

 歴史的にはRuby,PerlのFakerが元で、この便利なライブラリをPHP、Javascriptで使う人が出てきて、Pythonでも実装されて、といった具合です。Ruby版はPokemon,BackToTheFuture等の特にニッチなフォーマットがいくつかあります。いずれのFakerも多種多様なフォーマットのランダムなデータを生成でき、ダミーデータの作成を簡単に行えます。
 基本的な使い方はリンク先にある通り

<?php
// require the Faker autoloader
require_once '/path/to/Faker/src/autoload.php';
// alternatively, use another PSR-0 compliant autoloader (like the Symfony2 ClassLoader for instance)

// use the factory to create a Faker\Generator instance
$faker = Faker\Factory::create();

// generate data by accessing properties
echo $faker->name;
  // 'Lucy Cechtelar';
echo $faker->address;
  // "426 Jordy Lodge
  // Cartwrightshire, SC 88120-6700"
echo $faker->text;
  // Dolores sit sint laboriosam dolorem culpa et autem. Beatae nam sunt fugit
  // et sit et mollitia sed.
  // Fuga deserunt tempora facere magni omnis. Omnis quia temporibus laudantium
  // sit minima sint.

 fakerを呼び出し、任意のフォーマット名のプロパティを呼び出せば、そのフォーマットのランダムな値が返ってきます。

$faker->optional($weight = 0.9, $default = 'abc')->word; // 10% chance of 'abc'

の様に重みとデフォルト値をつけると、一定の割合でデフォルト値が出力されます。こういったデータの分布の操作もいくらかできます。
 配布された状態のままでは出力されるデータのパターン数がwebページのテストに困らない程度しかありません。そのため機械学習等のビッグデータを用いたプログラムのテストには使用できません。
 しかしながらデータセットの改変は容易です。データセットの記述されたファイルはfaker/src/Faker/Provider以下にあります。この部分を参考にProviderクラスのどれかを継承して、データセット変数を任意のデータセットで上書き、

$faker->addProvider(new Faker\Provider\en_US\Person($faker));

の様に新たなProviderを追加することで、オリジナルのデータセットでダミーデータを作成できます。

  • この記事いいね! (0)
著者:杉浦

PHPの標準勧告提案PSR

PHPの標準勧告提案PSR
 PHP Standards Recommendations – PHP-FIG
PSRはPHPのコードはこのように作るべきだと推奨する提案の一つです。PSRはPHP-FIG — PHP Framework Interop Group – PHP-FIGによって策定されています。PHP-FIGはPHP Framework Interop Groupとある通り、複数あるPHPフレームワークの各関係者の集団です。その影響力は強く、いくつものフレームワークを始めとして多くのコードがPSRに準拠したコードになっています。
 現在、承認済みのPSRは次の表の通りです。

Accepted

Num Title Editor Coordinator Sponsor
1 Basic Coding Standard Paul M. Jones N/A N/A
2 Coding Style Guide Paul M. Jones N/A N/A
3 Logger Interface Jordi Boggiano N/A N/A
4 Autoloading Standard Paul M. Jones Phil Sturgeon Larry Garfield
6 Caching Interface Larry Garfield Paul Dragoonis Robert Hafner
7 HTTP Message Interface Matthew Weier O’Phinney Beau Simensen Paul M. Jones
11 Container Interface Matthieu Napoli, David Négrier Matthew Weier O’Phinney Korvin Szanto
13 Hypermedia Links Larry Garfield Matthew Weier O’Phinney Marc Alexander
15 HTTP Handlers Woody Gilk N/A Matthew Weier O’Phinney
16 Simple Cache Paul Dragoonis Jordi Boggiano Fabien Potencier
17 HTTP Factories Woody Gilk N/A Matthew Weier O’Phinney

 この中で特に多くの出番があるのはPSR-2、コーディング規約です。インデントはスペース4個、一行はできるだけ80文字以内に最大でも120文字以内、クラス、メソッドの開き括弧は次の行、などなどコードのスタイルについての規約が羅列されています。日本語訳も既にいくつかあります。PSR-2 コーディングガイド(日本語)|北海道札幌市のシステム開発会社インフィニットループ
【PSR】PHPの標準コーディング規約 – Qiita
【PHP】PSR-2 Coding Style Guide(コーディングスタイルガイド)
 チェックツールにはphp_codesniffer、修正ツールには php-cs-fixerなどがあります。

  • この記事いいね! (1)